2013-05-16 13 views
2

У нас есть рабочая очередь, к которой пользователь может добавить работу. Когда рабочий элемент добавляется, контекст является пользователем (HttpContext). Но это фоновый поток, который обследует очередь и выполняет элементы по порядку.Очередь рабочего и контекст пользователя

Я не могу просто хранить пользователь, потому что, когда HttpContext расположен так будет главный объект

код, который может работать в рабочем нужен Принципал быть правильными для вещей, как PrincipalPermissions и т.д.

также , управление Lifetime (IoC) использует HttpContext для InRequest областей, можно воссоздать HttpContext с правильным принципалом и т.д.

редактировать: Faking HttpContext - это просто приятная функция для управления жизненным циклом, это я могу обойти. Но наш внутренний код сильно зависит от наличия правильного принципала пользователя для потока, поскольку мы используем его для проверки того, имеет ли пользователь доступ к этой части системы. я бы пометить как ответ если кто-то может ответить, как сохранить пользователь принципал с единицей, роли и состоянием IsAuthenticated, а затем использовать его в другом потоке

ответ

0
public void TestMethod1() 
{ 
    System.Net.WebClient client = new System.Net.WebClient(); 
    client.BaseAddress = "http://www.teejoo.com";    

    //Invoke your function here 
    client.OpenReadAsync(new Uri("http://www.teejoo.com/YourLogicalPage.aspx")); 
    //Pur your logical in your page, so you can use httpContext 

    client.OpenReadCompleted += new System.Net.OpenReadCompletedEventHandler(client_OpenReadCompleted); 
} 

void client_OpenReadCompleted(object sender, System.Net.OpenReadCompletedEventArgs e) 
{    
    //to Check the response HERE 
} 
+0

Это не то, что Im после, я не хочу создавать HTTP-запрос, я хочу создать httpcontext для рабочего фона, у которого его нет. На самом деле самое главное, что я могу как-то сохранить и повторно использовать принципала HttpContext – Anders

+0

, вы не можете создать HttpContext в фоновом режиме, так что вы можете пересечь эту проблему, создав httpRequest и посетив страницу, которая в вашем приложении – Eugene

+0

, и есть HttpContext на вашей логической странице. – Eugene

0

Почему бы вам не использовать класс ДОПОЛНИТЕЛЬНОГО для удерживания вам нужна информация? Вы можете создать его во время веб-запроса с соответствующими значениями и передать его в качестве аргумента для рабочего фона.

Клонирование объекта HTTPContext невозможно из-за внутреннего server session state. Даже если это было возможно, использование его вне реального HTTP-запроса просто для проверки значений не похоже на хорошее решение.

+0

. Минимальным требованием является то, что Принцип для потока правильный, потому что мы используем его для проверки доступа к методу с использованием PrincipalAttributes. Так что, если я каким-то образом смогу клонировать принципала с идентичностью, ролями и состоянием IsAuthenticated, которое было бы достаточно хорошим – Anders

+0

, см. Править – Anders

1

Ваша наилучшая практика для использования данных с состоянием из HttpContext заключается в создании собственного контекста приложения, которое принимает конструктор HttpContext в конструкторе (Dependency Injected).

Ваша бизнес-логика никогда не должна зависеть от HttpContext, а скорее от вашего нового контекста приложения (который, возможно, был создан с использованием информации от HttpContext).

Это не только решит ваши проблемы, но и повысит степень проверки вашего кода.

Пример:

public class MyApplicationContext 
{ 
    public IPrincipal ContextPrincipal { get; set; } 

    public MyApplicationContext(HttpContext httpContext) 
    { 
     // Store the current user principal & identity 
     ContextPrincipal = httpContext.User; 

     // Need to grab anything else from the HttpContext? Do it here! 
     // That could be cookies, Http request header values, query string 
     // parameters, session state variables, etc. 
     // 
     // Once you gather up any other stateful data, store it here in 
     // your application context object as the HttpRequest can't be passed 
     // to another thread. 
    } 

} 

public class MyHttpHandler : IHttpHandler 
{ 
    #region IHttpHandler Members 

    public bool IsReusable 
    { 
     // Return false in case your Managed Handler cannot be reused for another request. 
     // Usually this would be false in case you have some state information preserved per request. 
     get { return true; } 
    } 

    public void ProcessRequest(HttpContext context) 
    { 
     // Do some work on another thread using the ThreadPool 
     ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), new MyApplicationContext(context)); 
    } 

    public void DoWork(object state) 
    { 
     // Grab our state info which should be an instance of an 
     // MyApplicationContext. 
     MyApplicationContext context = (MyApplicationContext) state; 

     // Assign this ThreadPool thread's current principal according 
     // to our passed in application context. 
     Thread.CurrentPrincipal = context.ContextPrincipal; 

     // Check if this user is authenticated. 
     if (context.ContextPrincipal.Identity.IsAuthenticated) 
     { 
      var userName = context.ContextPrincipal.Identity.Name; 
     } 

     // Check if this user is an administrator. 
     if (context.ContextPrincipal.IsInRole("Administrator")) 
     { 
     } 

     // Do some long-ish process that we need to do on the threadpool 
     // after the HttpRequest has already been responded to earlier. 
     // 
     // This would normally be some fancy calculation/math, data 
     // operation or file routines. 
     for (int i = 0; i < 30; i++) 
     { 
      Thread.Sleep(1000); 
     } 
    } 

    #endregion 
} 

Ни интерфейс IPrincipal ни IIdentity явно не предлагают метод Dispose. Поэтому им должно быть хорошо поддерживать ссылку на них. Тем не менее, я не тестировал вышеуказанный код, я написал его только для этого вопроса.

Если какой-либо плохой дизайн фактически зависит от базового соединения с базой данных для запроса членства в ролях, вам просто нужно оценить это ранее в конструкторе контекста вашего приложения, в то время как поставщик проверки подлинности форм HttpContext и asp.net все еще не расположены/закрыты.

Вы всегда можете разделить принципал и личность и воссоздать новый экземпляр GenericPrincipal и GenericIdentity или даже создать свое приложение. Класс идентичности, который реализует IIdentity. Здесь есть много возможностей для настройки/расширения.

+0

Проблема в том, что его код в потоковом контуре потока, зависящий от Принципала и принципала, сработает после HttpContext . Для выяснения нашей бизнес-логики не существует какой-либо зависимости от классов System.Web. Но он использует Thread.CurrentPrincipal, который под капотом использует HttpContext (если код запускается под IIS). – Anders

+0

@ Anders: Просмотрите код еще раз. Первое, что я сделал выше, - назначить «Thread.CurrentPrincipal» в новом потоке ThreadPool! Я также объяснил, что сам руководитель не распоряжается - единственное возможное объяснение заключается в том, что базовый провайдер, который заполняет список ролей принципала, не позволяет вам проверять роли. Может быть, вам следует опубликовать трассировку стека за исключением, которое вы получаете? В то же время просто выполните эти проверки раньше и сохраните в своем приложении контекст - или напишите свой собственный IIdentity, чтобы хранить больше информации. – BenSwayne