2016-02-17 7 views
5

मैं एएसपी.Net वेब एपीआई 2/.NET 4.5.2 का उपयोग कर रहा हूं।कतारबद्ध पृष्ठभूमि कार्य आइटम के अंदर प्रिंसिपल बनाए रखना

मैं पृष्ठभूमि कार्य आइटम कतार में कॉलिंग प्रिंसिपल को बनाए रखने की कोशिश कर रहा हूं। इसके लिए मैं कोशिश कर रहा हूँ:

Thread.CurrentPrincipal = callingPrincipal; 

लेकिन जब मैं ऐसा करते हैं, मैं एक ObjectDisposedException मिलती है:

System.ObjectDisposedException: सुरक्षित संभाल बंद कर दिया गया

कैसे क्या मैं वर्तमान प्रिंसिपल को पृष्ठभूमि कार्य आइटम के अंदर रखता हूं?
क्या मैं किसी भी तरह प्रिंसिपल की एक प्रति बना सकता हूं?

public void Run<T>(Action<T> action) 
{ 
    _logger.Debug("Queueing background work item"); 
    var callingPrincipal = Thread.CurrentPrincipal; 
    HostingEnvironment.QueueBackgroundWorkItem(token => 
    { 
     try 
     { 
      // UNCOMMENT - THROWS EXCEPTION 
      // Thread.CurrentPrincipal = callingPrincipal; 
      _logger.Debug("Executing queued background work item"); 
      using (var scope = DependencyResolver.BeginLifetimeScope()) 
      { 
       var service = scope.Resolve<T>(); 
       action(service); 
      } 
     } 
     catch (Exception ex) 
     { 
      _logger.Fatal(ex); 
     } 
     finally 
     { 
      _logger.Debug("Completed queued background work item"); 
     } 
    }); 
} 
+0

क्या आपको वास्तव में 'थ्रेड.कुरेंट प्रिंसिपल' की आवश्यकता है, या आपको वास्तव में 'HttpContext.User' की आवश्यकता है? शायद इस बारे में विस्तार से बताएं कि आपको इस तरह के मौजूदा प्रिंसिपल को क्यों प्रवाह करना है। –

+0

पृष्ठभूमि प्रिंस में वर्तमान प्रिंसिपल को रखने के पीछे क्या कारण है? – Win

+0

कुछ व्यक्तिगत डेटा प्राप्त करने के लिए जो बहुत समय लेने वाला है, उदाहरण के लिए। – VMAtm

उत्तर

5

ClaimsPrincipal बाहर बदल जाता है अब एक प्रति निर्माता है: अन्य तरह से, उदाहरण के लिए, Task करने के लिए वर्तमान OperationContext गुजर उपयोग करने के लिए है।

var principal = new ClaimsPrincipal(Thread.CurrentPrincipal); 

यह सभी पहचान और दावों की जानकारी को बनाए रखते हुए इस मुद्दे को हल करने के लिए प्रतीत होता है। पूरा कार्य निम्नानुसार है:

public void Run<T>(Action<T> action) 
{ 
    _logger.Debug("Queueing background work item"); 
    var principal = new ClaimsPrincipal(Thread.CurrentPrincipal); 

    HostingEnvironment.QueueBackgroundWorkItem(token => 
    { 
     try 
     { 
      Thread.CurrentPrincipal = principal; 
      _logger.Debug("Executing queued background work item"); 
      using (var scope = DependencyResolver.BeginLifetimeScope()) 
      { 
       var service = scope.Resolve<T>(); 
       action(service); 
      } 
     } 
     catch (Exception ex) 
     { 
      _logger.Fatal(ex); 
     } 
     finally 
     { 
      _logger.Debug("Completed queued background work item"); 
     } 
    }); 
} 
0

अपनी स्थिति की समस्या यह है कि पृष्ठभूमि कार्य के बाद Thread.CurrentPrincipal निपटारा किया जा रहा निष्पादित किया जा रहा है। यह एएसपी.नेट मॉडल के कारण होता है - अनुरोध उपयोगकर्ता संदर्भ में संभाला जा रहा है और इसके बाद उपयोगकर्ता से संबंधित सभी मान मुक्त हो जाते हैं। तो यह आपकी पहचान के साथ बिल्कुल होता है। बाद में इसका प्रतिरूपण करने के लिए उपयोगकर्ता और उसकी पहचान के बारे में जानकारी को सहेजने का प्रयास करें।

आप ASP.NET साइटों में आपरेशन धारण करने के कारण एक support article from Microsoft समीक्षा कर सकते हैं, लेकिन मुझे नहीं लगता कि कि यह आपके लिए उपयोगी होगा:

System.Security.Principal.WindowsImpersonationContext impersonationContext; 
impersonationContext = 
    ((System.Security.Principal.WindowsIdentity)callingPrincipal.Identity).Impersonate(); 

//Insert your code that runs under the security context of the authenticating user here. 

impersonationContext.Undo(); 

या, हो सकता है, आप उपयोगकर्ता का उपयोग कर सकते .Token, कुछ इस तरह:

HostingEnvironment.QueueBackgroundWorkItem(token => 
{ 
    try 
    { 
     _logger.Debug("Executing queued background work item"); 
     using (HostingEnvironment.Impersonate(callingPrincipal.Identity)) 
     { 
      using (var scope = DependencyResolver.BeginLifetimeScope()) 
      { 
       var service = scope.Resolve<T>(); 
       action(service); 
      } 
     } 
     // UNCOMMENT - THROWS EXCEPTION 
     // Thread.CurrentPrincipal = callingPrincipal; 
    } 
    catch (Exception ex) 
    { 
     _logger.Fatal(ex); 
    } 
    finally 
    { 
     _logger.Debug("Completed queued background work item"); 
    } 
}); 

मेरा सुझाव है कि आप अपने वास्तुकला डिजाइन की समीक्षा करने के ताकि आप अन्य संदर्भ है, जिसमें उपयोगकर्ता पहचान अब रहना होता करने के लिए पृष्ठभूमि आपरेशन बाहर ले जाने के लिए एक रास्ता मिल सकता है।

// store local operation context 
var operationContext = OperationContext.Current; 
TaskFactory.StartNew(() => 
{ 
    // initialize the current operation context 
    OperationContext.Current = operationContext; 
    action(); 
}) 
+0

ओपी प्रतिरूपण से काफी अलग है।ओपी होने वाली समस्या मुख्य धागा है जबकि पृष्ठभूमि थ्रेड संसाधित हो रहा है। ** यह एएसपी.Net ** में एक अच्छा अभ्यास नहीं है, यही वजह है कि युवाल इट्ज़कोकोव और मैं पूछ रहा हूं। आम तौर पर, हम बैकग्राउंड थ्रेड में प्रसंस्करण से पहले डाटाबेस जैसे डाटाबेस को लगातार स्टोरेज में स्टोर करते हैं। – Win

+0

मैं समस्या को समझता हूं और यह समझाने की कोशिश करता हूं कि लंबे ऑपरेशन के लिए 'CurrentThread' से कैसे बाध्य नहीं किया जाए। – VMAtm

संबंधित मुद्दे