मुझे कहना है कि मुझे काफी आश्चर्य हुआ कि कंस्ट्रक्टर के अंदर HttpContext शून्य है। मुझे यकीन है कि यह प्रदर्शन कारणों से है। पुष्टि की है कि IPrincipal
नीचे वर्णित के रूप में उपयोग करने से यह कंस्ट्रक्टर में अंतःक्षिप्त हो जाता है। यह अनिवार्य रूप से स्वीकार किए जाते हैं उत्तर के रूप में ही कर रहे हैं, लेकिन एक अधिक स्पष्ट तरीके से।
किसी के लिए भी यह सवाल जेनेरिक के जवाब की तलाश में है "वर्तमान उपयोगकर्ता कैसे प्राप्त करें?" आप बस User
से सीधे पहुँच सकते हैं Controller.User
। लेकिन आप इसे केवल एक्शन विधियों के अंदर ही कर सकते हैं (मेरा मानना है कि नियंत्रक केवल HttpContexts और प्रदर्शन कारणों से नहीं चलते हैं)।
हालाँकि - यदि आपको कंस्ट्रक्टर में इसकी आवश्यकता है (जैसा कि ओपी ने किया था) या अन्य इंजेक्टेबल ऑब्जेक्ट बनाने की आवश्यकता है जो वर्तमान उपयोगकर्ता की आवश्यकता है तो नीचे एक बेहतर तरीका है:
उपयोगकर्ता प्राप्त करने के लिए IPrincipal इंजेक्षन
पहले मिलते हैं IPrincipal
औरIIdentity
public interface IPrincipal
{
IIdentity Identity { get; }
bool IsInRole(string role);
}
public interface IIdentity
{
string AuthenticationType { get; }
bool IsAuthenticated { get; }
string Name { get; }
}
IPrincipal
और IIdentity
उपयोगकर्ता और उपयोगकर्ता नाम का प्रतिनिधित्व करता है। अगर al प्रिंसिपल ’अजीब लगे तो विकिपीडिया आपको सुकून देगा ।
यह महसूस करना महत्वपूर्ण है कि क्या आप इसे प्राप्त करते हैं IHttpContextAccessor.HttpContext.User
, ControllerBase.User
या ControllerBase.HttpContext.User
आपको एक ऐसी वस्तु मिल रही है जिसकी गारंटी एक ऐसी ClaimsPrincipal
वस्तु है जो लागू होती हैIPrincipal
।
कोई अन्य प्रकार का उपयोगकर्ता नहीं है जो ASP.NET User
अभी उपयोग करता है , (लेकिन ऐसा नहीं है कि कुछ और कहें जो लागू नहीं हो सका IPrincipal
)।
इसलिए यदि आपके पास कोई ऐसी चीज है जिस पर 'वर्तमान उपयोगकर्ता नाम' की निर्भरता है जिसे आप इंजेक्ट करना चाहते हैं तो आपको इंजेक्शन लगाना चाहिए IPrincipal
और निश्चित रूप से नहीं IHttpContextAccessor
।
महत्वपूर्ण:IPrincipal
सीधे अपने नियंत्रक, या एक्शन विधि पर इंजेक्शन लगाने में समय बर्बाद न करें - यह तब से बेकार है जब User
से आप पहले से ही वहां उपलब्ध हैं।
इन startup.cs
:
// Inject IPrincipal
services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
फिर आपके DI ऑब्जेक्ट में उस उपयोगकर्ता की आवश्यकता है जिसे आप IPrincipal
वर्तमान उपयोगकर्ता प्राप्त करने के लिए इंजेक्ट करते हैं।
यहां सबसे महत्वपूर्ण बात यह है कि यदि आप यूनिट टेस्ट कर रहे हैं तो आपको भेजने की आवश्यकता नहीं है HttpContext
, लेकिन केवल कुछ का मजाक उड़ाने की जरूरत है जो प्रतिनिधित्व करता है IPrincipal
जो अभी हो सकता है ClaimsPrincipal
।
एक अतिरिक्त महत्वपूर्ण बात जो मैं 100% सुनिश्चित नहीं हूं। यदि आपको वास्तविक दावों तक पहुंचने की आवश्यकता है, तो आपको ClaimsPrincipal
कास्ट IPrincipal
करने की आवश्यकता है ClaimsPrincipal
। यह ठीक है क्योंकि हम 100% जानते हैं कि रनटाइम में यह उस प्रकार का है (क्योंकि यही HttpContext.User
है)। मैं वास्तव में कंस्ट्रक्टर में ऐसा करना पसंद करता हूं क्योंकि मुझे पहले से ही पता है कि कोई भी IPrincipal
होगा ClaimsPrincipal
।
यदि आप मॉकिंग कर रहे हैं, तो बस एक ClaimsPrincipal
सीधा बनाएं और जो भी लेता है उसे पास करें IPrincipal
।
वास्तव में, IClaimsPrincipal
मुझे यकीन नहीं है के लिए कोई इंटरफ़ेस नहीं है। मुझे लगता है कि एमएस ने फैसला किया कि ClaimsPrincipal
सिर्फ एक विशेष 'संग्रह' था जो एक इंटरफ़ेस को वारंट नहीं करता था।