web-dev-qa-db-ja.com

Apiコントローラーに注入されているリポジトリにOwinコンテキストを渡す方法

Unityを使用してコントローラーの依存関係を解決するMVCWebApi owin(ソフトホスト)プロジェクトがあります

このように見えます

public class PacientaiController : ODataController
    {
        private readonly IEntityRepo<Ent.Pacientas> repo;

        public PacientaiController(IEntityRepo<Ent.Pacientas> repo)
        {
            this.repo = repo;
        }

私が解決しようとしている問題は、「OwinContex」をレポに渡す方法です。

public class PacientasEntityRepo:IEntityRepo<Pacientas>,IDisposable
    {
        public PacientasEntityRepo(IOwinContext ctx)
        {
        .........

このようにStartup.csに登録しようとすると

Container.RegisterType<IOwinContext>(new InjectionFactory(o => HttpContext.Current.GetOwinContext()));

HttpContext.CurrentがNULLであるというnull参照を取得します

ここでの主なアイデアは、現在認証されているユーザーをリポジトリに渡すことです。これは、ユーザーに応じて、リポジトリがデータベースをクエリするためのロジックをホストするためです。 (たとえば、ユーザーが管理者の場合はこのデータを返し、ユーザーがゲストの場合はこのデータを返します)

重要なのは、これが自己ホストであるということです。

19
Marty

この設計を採用している理由を脇に置いて、問題に集中しましょう。IOwinContextを挿入します。

HttpRequestMessageメソッドを使用してGetOwinContextインスタンスから取得することもできますが、何らかの方法でHttpRequestMessageを取得する必要もあります。

Unityは、箱から出してHttpRequestMessageを注入することをサポートしていませんが、ここで説明するように、現在のDelegatingHandlerをコンテナーに格納するカスタムHttpRequestMessageを使用できます: Autofac を使用してWebAPIUrlHelperをサービスに挿入します

リンクされた質問はAutofacに関するものですが、Unityで作業するために転送できます。

CurrentRequestCurrentRequestHandlerは、 Andrew Davey の回答からそのまま使用できます。

public class CurrentRequest
{
    public HttpRequestMessage Value { get; set; }
}

public class CurrentRequestHandler : DelegatingHandler
{
    protected async override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        var scope = request.GetDependencyScope();
        var currentRequest = (CurrentRequest)scope.GetService(typeof(CurrentRequest));
        currentRequest.Value = request;
        return await base.SendAsync(request, cancellationToken);
    }
}

次に、DelegatingHandlerを次のものに登録する必要があります。

httpConfiguration.MessageHandlers.Insert(0, new CurrentRequestHandler());

そして、CurrentRequestIOwinContextをコンテナに登録します

container.RegisterType<CurrentRequest>(
            new HierarchicalLifetimeManager());

container.RegisterType<IOwinContext>(
    new HierarchicalLifetimeManager(),
    new InjectionFactory(c => c.Resolve<CurrentRequest>().Value.GetOwinContext()));

httpConfiguration.DependencyResolver = new UnityHierarchicalDependencyResolver(container);

カスタム委任ハンドラーのほかに、Web.APIにフックしてHttpRequestMessageをキャプチャする場所が他にもあります。たとえば、独自のIHttpControllerActivatorを作成し、ここで説明するようにExecuteAsyncメソッドを使用できます。 : ASP.NET Web API 2での依存性注入

25
nemesv

セルフホストアプリケーションでは、HttpContextがありません。状態を移動するには、別の方法が必要です。オプションは、次のような自己実装のHttpContextを使用することです。

https://github.com/danielcrenna/graveyard/tree/master/httpcontext-shim

2
Peter

問題は、Startupが呼び出されたときにHttpContextが存在しないことだと思います。したがって、おそらく必要なのは、代わりに次のようなFuncを使用することです。

public class PacientasEntityRepo:IEntityRepo<Pacientas>,IDisposable
{
    public PacientasEntityRepo(Func<IOwinContext> ctx)
    {
    .........

次に、スタートアップのコードを次のように変更します。

Container.RegisterType<IOwinContext>(new InjectionFactory(() => HttpContext.Current.GetOwinContext()));
1
Steen Tøttrup