2016-03-07 3 views
0

Я устанавливаю свойство на Request.Properties внутри DelegatingHandler после того, как я вырву некоторые данные из заголовка входящего запроса в веб-API.Как получить доступ к Request.Properties за пределами Web API-контроллера

Все это работает нормально. Я также могу получить доступ к Request.Properties как внутри контроллера, так и в моих фильтрах «Действие» и «Исключение». Однако мне также необходимо получить доступ к этим данным из-за пределов контроллера (я называю класс бизнес-уровня с контроллера). Это данные, которые я хочу включить в некоторые журналы в других местах,

Я могу видеть HttpContext.Current из этого класса, и я могу видеть исходный заголовок отсюда, поэтому, я думаю, я мог бы вырвать его снова, но поскольку у меня есть уже сделал это и поместил его в Свойства, кажется, имеет смысл получить его оттуда. Однако, похоже, у меня нет доступа к Request.Properties из другого места.

Если это неправильный способ сделать это, как еще я могу обойти эти данные для каждого запроса, чтобы он был доступен из любой точки стека в веб-API?

+0

Используйте что-то вроде [AutoFac] (http://autofac.org/) для DI (инъекция зависимостей). У меня есть хороший пример. На самом деле я просто ответил на днях [здесь] (http://stackoverflow.com/a/35826744/1260204) (* Извините за бесстыдную вставку моего ответа *). Если вы перейдете в «Решение 2 - IoC/DI», вы можете его повторно использовать. Обновите класс 'WebUserInfo' (в верхней части ответа) и поместите интерфейс по своему усмотрению. Добавьте инфраструктуру Autofac. И теперь добавьте свой интерфейс 'IUserInfo' в конструкторы вашего уровня сервиса, Autofac позаботится обо всем остальном, и теперь у вас есть доступ, где вам это нужно. – Igor

+1

Обратите внимание, что если вы вырвите из «HttpContext.Current», код будет работать только при работе в IIS. Используя OWIN для самостоятельного размещения веб-api, нет «HttpContext.Current» (если ваше приложение не устанавливает его вручную). – danludwig

+0

Забыл упомянуть: вам также нужно будет зарегистрировать свои типы услуг с помощью рамки DI, и они могут быть введены в ваши веб-контроллеры api.Если вы используете несколько проектов, убедитесь, что общие интерфейсы определены в центральном расположении. Но ситуации, подобные этому, - это то, где действительно сияет инфраструктура DI. – Igor

ответ

0

Мне также нужно получить доступ к [Request.Properties] данным из-за пределов контроллера (я называю класс бизнес-уровня с контроллера). Это данные, которые я хочу включить в некоторые журналы в других местах ... Однако у меня нет доступа к Request.Properties из любого места. Если это неправильный способ сделать это, как еще я могу передать данные для каждого запроса, чтобы он был доступен из любой точки стека в веб-API?

Вы можете получить его от HttpContext.Current, хотя он не идеален. Имейте в виду, что если любые другие не-веб-приложения потребляют один и тот же бизнес-уровень, то HttpContext.Current будет null. HttpContext.Current только не является нулевым, когда вы работаете в IIS, а поток IIS обрабатывает выполнение стека запросов. Если вы когда-либо планируете самостоятельно размещать веб-api, используя OWIN без IIS, не будет HttpContext.Current.

Лично, если данные действительно является достаточно важным, чтобы быть переданы в бизнес-слой, чтобы быть зарегистрированным, то я бы просто передать его в метод бизнес-слоя:

public Task<HttpResponseMessage> SomeAction(SomeModel model) { 
    ... other code 
    someBusinessLayerObject.SomeMethod(arg1, arg2, Request.Properties["myHeaderKey"]); 
} 

... Если вам нужны другие значения от Request.Properties, то вы можете просто передать весь словарь методам, которые в конечном итоге будут использовать его значения.

Третий вариант, если вы используете инверсию управляющего контейнера, заключался бы в том, чтобы добавить какой-то класс зависимостей объекта с областью действия и поместить туда данные. Затем конструктор вводит его в класс бизнес-уровня:

public interface IHaveRequestData { 
    IDictionary<string, object> Properties { get; set; } 
} 

public class RequestData : IHaveRequestData { 
    public IDictionary<string, object> Properties { get; set; } 
} 

// ioc registration pseudocode 
iocContainer.Register<IHaveRequestData, RequestData>(Lifetime 
    .WhateverYouNeedSoThatOneOfTheseGetsCreatedForEachWebRequest); 

public class SomeController : ApiController { 
    private readonly IHaveRequestData RequestData; 
    public SomeController(IHaveRequestData requestData) { 
     RequestData = requestData; 
    } 

    public Task<HttpResponseMessage> SomeAction() { 
     // you may even be able to do this part in an action filter 
     RequestData.Properties = Request.Properties; 
    } 
} 

public class SomeBusinessLayerComponent { 
    private readonly IHaveRequestData RequestData; 
    private readonly ILog Log; 
    public SomeBusinessLayerComponent(IHaveRequestData requestData, ILog log) { 
     RequestData = requestData; 
     Log = log; 
    } 

    public Task SomeMethod() { 
     Log.Info(RequestData["myHeader"]); 
    } 
} 
+0

Спасибо за это. Это был подход, который я собирался взять (захватить его в контроллере, передать его бизнес-слою), но я надеялся, что есть другой способ его получить. К счастью, это только один уровень от контроллера. Если бы это было необходимо в кучу мест, я бы, вероятно, рассмотрел DI. – ChrisC

Смежные вопросы