ASP.NET Core में वर्तमान HttpContext को एक्सेस करें


132

मुझे HttpContextएक स्थिर विधि या उपयोगिता सेवा में वर्तमान तक पहुंचने की आवश्यकता है ।

क्लासिक ASP.NET MVC के साथ और System.Web, मैं सिर्फ HttpContext.Currentसंदर्भ को सांख्यिकीय रूप से एक्सेस करने के लिए उपयोग करूंगा । लेकिन मैं ASP.NET कोर में यह कैसे करूँ?

जवाबों:


149

HttpContext.CurrentASP.NET Core में अब मौजूद नहीं है लेकिन एक नया है IHttpContextAccessorजिसे आप अपनी निर्भरता में इंजेक्ट कर सकते हैं और वर्तमान को पुनः प्राप्त करने के लिए उपयोग कर सकते हैं HttpContext:

public class MyComponent : IMyComponent
{
    private readonly IHttpContextAccessor _contextAccessor;

    public MyComponent(IHttpContextAccessor contextAccessor)
    {
        _contextAccessor = contextAccessor;
    }

    public string GetDataFromSession()
    {
        return _contextAccessor.HttpContext.Session.GetString(*KEY*);
    }
}

3
अच्छी बात! यह भी ध्यान देने योग्य है कि IHttpContextAccessorकेवल उन स्थानों पर उपलब्ध होगा जहां डीआई कंटेनर उदाहरण का समाधान कर रहा है।
तुगलक

6
@tugberk अच्छी तरह से, सिद्धांत रूप में, आप भी इस्तेमाल कर सकते हैं CallContextServiceLocatorयहां तक कि एक गैर-डि इंजेक्शन उदाहरण से, एक सेवा को हल करने: CallContextServiceLocator.Locator.ServiceProvider.GetService<IHttpContextAccessor>()। व्यवहार में, यह एक बहुत अच्छी बात है अगर आप इससे बच सकते हैं :)
केविन शैले

17
CallContextServiceLocator का उपयोग न करें
davidfowl

9
@davidfowl जब तक आपके पास एक वैध तकनीकी कारण नहीं है ('स्टेटिक्स खराब हैं' के अलावा), मुझे यकीन है कि लोग इसका इस्तेमाल करेंगे यदि उनके पास कोई अन्य विकल्प नहीं है।
केविन शैले

7
हालांकि, लोगों को शायद ही कभी एक वैध तकनीकी कारण है। यह एक स्टैटिक का उपयोग करना अधिक आसान है और जो परीक्षण क्षमता की परवाह करता है :)
davidfowl

35

Necromancing।
हाँ आप
बड़े प्रवास करने वालों के लिए गुप्त टिप दे सकते हैंjunksकोड के टुकड़े (आह, फ्रायडियन पर्ची)।
निम्नलिखित विधि एक हैक का एक दुष्ट कार्बुनकल है जो सक्रिय रूप से शैतान के एक्सप्रेस काम (.NET कोर फ्रेमवर्क डेवलपर्स की आँखों में) को पूरा करने में लगी हुई है, लेकिन यह काम करता है :

में public class Startup

एक संपत्ति जोड़ें

public IConfigurationRoot Configuration { get; }

और फिर ConfigureServices में DI के लिए एक सिंगलटन IHttpContextAccessor जोड़ें।

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();

फिर कन्फिगर में

    public void Configure(
              IApplicationBuilder app
             ,IHostingEnvironment env
             ,ILoggerFactory loggerFactory
    )
    {

DI पैरामीटर जोड़ें IServiceProvider svp, ताकि विधि इस प्रकार दिखे:

    public void Configure(
           IApplicationBuilder app
          ,IHostingEnvironment env
          ,ILoggerFactory loggerFactory
          ,IServiceProvider svp)
    {

अगला, System.Web के लिए एक प्रतिस्थापन वर्ग बनाएँ:

namespace System.Web
{

    namespace Hosting
    {
        public static class HostingEnvironment 
        {
            public static bool m_IsHosted;

            static HostingEnvironment()
            {
                m_IsHosted = false;
            }

            public static bool IsHosted
            {
                get
                {
                    return m_IsHosted;
                }
            }
        }
    }


    public static class HttpContext
    {
        public static IServiceProvider ServiceProvider;

        static HttpContext()
        { }


        public static Microsoft.AspNetCore.Http.HttpContext Current
        {
            get
            {
                // var factory2 = ServiceProvider.GetService<Microsoft.AspNetCore.Http.IHttpContextAccessor>();
                object factory = ServiceProvider.GetService(typeof(Microsoft.AspNetCore.Http.IHttpContextAccessor));

                // Microsoft.AspNetCore.Http.HttpContextAccessor fac =(Microsoft.AspNetCore.Http.HttpContextAccessor)factory;
                Microsoft.AspNetCore.Http.HttpContext context = ((Microsoft.AspNetCore.Http.HttpContextAccessor)factory).HttpContext;
                // context.Response.WriteAsync("Test");

                return context;
            }
        }


    } // End Class HttpContext 


}

अब कॉन्फ़िगर में, जहां आपने जोड़ा है IServiceProvider svp, इस सेवा प्रदाता को केवल बनाए गए डमी क्लास में स्थिर चर "ServiceProvider" में सेव करें। System.eb.HttpContext (System.Web.HttpContext.ServiceProvider)

और HostingEnvironment.sHost को सही पर सेट करें

System.Web.Hosting.HostingEnvironment.m_IsHosted = true;

यह अनिवार्य रूप से System.Web ने क्या किया, बस आपने इसे कभी नहीं देखा (मुझे लगता है कि चर को जनता के बजाय आंतरिक के रूप में घोषित किया गया था)।

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider svp)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    ServiceProvider = svp;
    System.Web.HttpContext.ServiceProvider = svp;
    System.Web.Hosting.HostingEnvironment.m_IsHosted = true;


    app.UseCookieAuthentication(new CookieAuthenticationOptions()
    {
        AuthenticationScheme = "MyCookieMiddlewareInstance",
        LoginPath = new Microsoft.AspNetCore.Http.PathString("/Account/Unauthorized/"),
        AccessDeniedPath = new Microsoft.AspNetCore.Http.PathString("/Account/Forbidden/"),
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        CookieSecure = Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest

       , CookieHttpOnly=false

    });

ASP.NET वेब-फॉर्म्स की तरह, जब आप कोई HttpContext एक्सेस करने का प्रयास कर रहे हैं, तो आपको एक NullReference मिलेगा, जैसे कि कोई नहीं है, जैसे कि यह Application_StartGlobal.asax में हुआ करता था।

मैं फिर से जोर देता हूं, यह केवल तभी काम करता है जब आप वास्तव में जोड़े

services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();

जैसे मैंने आपको लिखा होना चाहिए।
DI पैटर्न के भीतर ServiceLocator पैटर्न में आपका स्वागत है;)
जोखिम और दुष्प्रभावों के लिए, अपने निवासी डॉक्टर या फार्मासिस्ट से पूछें - या github.com/aspnet पर .NET कोर के स्रोतों का अध्ययन करें , और कुछ परीक्षण करें।


शायद अधिक सहायक विधि इस सहायक वर्ग को जोड़ रही होगी

namespace System.Web
{

    public static class HttpContext
    {
        private static Microsoft.AspNetCore.Http.IHttpContextAccessor m_httpContextAccessor;


        public static void Configure(Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor)
        {
            m_httpContextAccessor = httpContextAccessor;
        }


        public static Microsoft.AspNetCore.Http.HttpContext Current
        {
            get
            {
                return m_httpContextAccessor.HttpContext;
            }
        }


    }


}

और उसके बाद HttpContext.Configure को Startup-> Configure में कॉल करें

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider svp)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();


    System.Web.HttpContext.Configure(app.ApplicationServices.
        GetRequiredService<Microsoft.AspNetCore.Http.IHttpContextAccessor>()
    );

37
इस
आर्ट

2
क्या हेल्पर विधि वाला संस्करण प्रत्येक परिदृश्य में ठीक से काम करता है। विभिन्न जीवनकाल के साथ आईओसी कंटेनर में मल्टीथ्रेडिंग, एसिक्स और सेवाओं के बारे में सोचना?
तमस मोलनार

7
मुझे पता है कि हम सभी को अपने रास्ते से बाहर जाना होगा कि यह कैसे ज्वलनशील शैतानी है ... लेकिन अगर आप कोर के लिए एक बड़ी परियोजना को चित्रित कर रहे थे, जहां HttpContext.Current का उपयोग कुछ कठिन-से-पहुंच वाले स्थिर वर्गों में किया गया था .. यह शायद काफी उपयोगी होगा। वहाँ, मैंने कहा।
ब्रायन मैकके

2
यह शुद्ध बुराई है ... और उचित है कि मैं इसे हैलोवीन पर लागू करने जा रहा हूं। मुझे DI और IoC से प्यार है ... लेकिन मैं बुराई स्टेटिक चर के साथ बुराई स्टेटिक क्लासेस के साथ एक विरासत ऐप के साथ काम कर रहा हूं, कि हमें Kestrel का उपयोग करने पर जोर देने की जरूरत है और HttpContext को इंजेक्ट करने की कोशिश करना हमारे लिए सबकुछ बिना तोड़-फोड़ के उचित होगा।
डेक्सटर

2
हां, यह MIGRATIONS का सही उत्तर है। ;)
टॉम स्टिकेल

23

बस अन्य उत्तरों में जोड़ने के लिए ...

ASP.NET कोर 2.1 में, वहाँ विस्तार विधि , कि रजिस्टर करेंगे सही जीवन भर के साथ:AddHttpContextAccessorIHttpContextAccessor

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpContextAccessor();

    // Other code...
}

2
खुशी है कि शैतानी कार्बुनकल का अधिक आधिकारिक विकल्प देखने के लिए!
केन ल्योन

@Ken Lyon;) khellang: सिंगलटन सही जीवनकाल है। स्कोप गलत होगा। या लेखन के समय बहुत कम था, ऐसा था। लेकिन सभी बेहतर अगर AddHttpContextAccessor विशिष्ट फ्रेमवर्क संस्करण के लिए एक संदर्भ की आवश्यकता के बिना इसे सही ढंग से करता है।
स्टीफन स्टीगर

क्या आप कृपया एक उदाहरण साझा कर सकते हैं?
टूलकिट

@ टूलकिट ने कुछ उदाहरण कोड जोड़े। यह सुनिश्चित नहीं है कि ऊपर दिए गए पाठ पर यह क्या मूल्य प्रदान करता है, हालांकि।
मारेल

22

आपके साथ मेरे स्थैतिक कार्यान्वयन में IHttpContextAccessor को इंजेक्ट करके सबसे कानूनी तरीका मेरे साथ आया था:

public static class HttpHelper
{
     private static IHttpContextAccessor _accessor;
     public static void Configure(IHttpContextAccessor httpContextAccessor)
     {
          _accessor = httpContextAccessor;
     }

     public static HttpContext HttpContext => _accessor.HttpContext;
}

फिर स्टार्टअप कॉन्फिगर में IHttpContextAccessor असाइन करके काम करना चाहिए।

HttpHelper.Configure(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>());

मुझे लगता है कि आपको सर्विस सिंगलटन को पंजीकृत करने की भी आवश्यकता होगी:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

सुंदर। बस वही जो चिकित्सक ने आदेश किया!
श्राप्नुल

5

इस लेख के अनुसार: ASP.NET Core में HttpContext को फ्रेमवर्क घटकों के बाहर एक्सेस करना

namespace System.Web
{
    public static class HttpContext
    {
        private static IHttpContextAccessor _contextAccessor;

        public static Microsoft.AspNetCore.Http.HttpContext Current => _contextAccessor.HttpContext;

        internal static void Configure(IHttpContextAccessor contextAccessor)
        {
            _contextAccessor = contextAccessor;
        }
    }
}

फिर:

public static class StaticHttpContextExtensions
{
    public static void AddHttpContextAccessor(this IServiceCollection services)
    {
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    }

    public static IApplicationBuilder UseStaticHttpContext(this IApplicationBuilder app)
    {
        var httpContextAccessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>();
        System.Web.HttpContext.Configure(httpContextAccessor);
        return app;
    }
}

फिर:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticHttpContext();
        app.UseMvc();
    }
}

आप इसे इस तरह से उपयोग कर सकते हैं:

using System.Web;

public class MyService
{
   public void DoWork()
   {
    var context = HttpContext.Current;
    // continue with context instance
   }
}

2

स्टार्टअप में

services.AddHttpContextAccessor();

नियंत्रक में

public class HomeController : Controller
    {
        private readonly IHttpContextAccessor _context;

        public HomeController(IHttpContextAccessor context)
        {
            _context = context; 
        }
        public IActionResult Index()
        {
           var context = _context.HttpContext.Request.Headers.ToList();
           return View();
        }
   }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.