Подтвердить что ты не робот

Как передать контекст Owin в Repo, который вводится в контроллер Api

У меня есть проект MVC WebApi owin (soft hosting), который использует Unity для разрешения зависимостей контроллера

которые выглядят следующим образом

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()));

Я получаю null ref, говоря, что HttpContext.Current равно NULL

Основная идея здесь состоит в том, чтобы передать аутентифицированного пользователя в репо, поскольку Repo использует Logic для запроса базы данных в зависимости от пользователя. (скажем, если пользователь является администратором, а затем верните эти данные, если пользователь гость - верните эти данные)

Суть в том, что это сам хост!

4b9b3361

Ответ 1

Давайте отложим, почему у вас есть этот дизайн и сконцентрирован на проблеме: вводя IOwinContext:

вы также можете получить его из экземпляра HttpRequestMessage с помощью метода GetOwinContext, однако вам также нужно как-то получить HttpRequestMessage.

Unity не поддерживает инъекцию HttpRequestMessage из коробки, но вы можете использовать пользовательский DelegatingHandler, который хранит текущий HttpRequestMessage в контейнере, как описано здесь: Ввести WebAPI UrlHelper в службу с помощью Autofac

Связанный вопрос касается Autofac, но вы можете перенести его для работы с Unity:

CurrentRequest и CurrentRequestHandler можно использовать из 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());

И зарегистрируйте CurrentRequest и IOwinContext в контейнере

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

Ответ 2

В самоходовом приложении у вас нет HttpContext. Вам нужен другой способ перемещения состояния. Опция заключается в использовании самоисполненного HttpContext, например:

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

Ответ 3

Я думаю, проблема в том, что HttpContext не существует в момент вызова Startup, поэтому, возможно, вам понадобится Func, например:

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

а затем измените код в Startup на это:

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