ASP.NET वेब एपीआई का उपयोग कर सत्र का उपयोग


268

मुझे लगता है कि सत्र और आरईएसटी वास्तव में हाथ से नहीं जाते हैं, लेकिन क्या नए वेब एपीआई का उपयोग करके सत्र राज्य तक पहुंच संभव नहीं है? HttpContext.Current.Sessionहमेशा अशक्त रहता है।


4
[SessionState(SessionStateBehavior.Required)]पर ApiControllerचाल (या क्या करता है .ReadOnlyजहां उपयुक्त हो)।
रोमन स्टार्कोव

@RomanStarkov यह काम करने के लिए नहीं मिल सका। आप किस वातावरण का उपयोग कर रहे थे? .NET कोर
बॉन्डोलिन

@Bondolin नहीं, यह कोर नहीं था।
रोमन स्टार्कोव

@RomanStarkov MVC तो? मुझे इसे ढूंढने में परेशानी हो रही है।
बॉन्डोलिन

जवाबों:


336

MVC

MVC प्रोजेक्ट के लिए निम्नलिखित परिवर्तन करें (WebForms और Dot Net Core नीचे उत्तर दें):

WebApiConfig.cs

public static class WebApiConfig
{
    public static string UrlPrefix         { get { return "api"; } }
    public static string UrlPrefixRelative { get { return "~/api"; } }

    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: WebApiConfig.UrlPrefix + "/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    ...

    protected void Application_PostAuthorizeRequest()
    {
        if (IsWebApiRequest())
        {
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
        }
    }

    private bool IsWebApiRequest()
    {
        return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(WebApiConfig.UrlPrefixRelative);
    }

}

इस समाधान में अतिरिक्त बोनस है जिसे हम AJAX कॉल करने के लिए जावास्क्रिप्ट में आधार URL ला सकते हैं:

_Layout.cshtml

<body>
    @RenderBody()

    <script type="text/javascript">
        var apiBaseUrl = '@Url.Content(ProjectNameSpace.WebApiConfig.UrlPrefixRelative)';
    </script>

    @RenderSection("scripts", required: false) 

और फिर हमारी जावास्क्रिप्ट फ़ाइलों / कोड के भीतर हम अपने वेबपी को कॉल कर सकते हैं जो सत्र तक पहुंच सकते हैं:

$.getJSON(apiBaseUrl + '/MyApi')
   .done(function (data) {
       alert('session data received: ' + data.whatever);
   })
);

WebForms

उपरोक्त करें लेकिन इसके बजाय एक रूटकैलेक्शन लेने के लिए WebApiConfig.Register फ़ंक्शन को बदलें:

public static void Register(RouteCollection routes)
{
    routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: WebApiConfig.UrlPrefix + "/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

और उसके बाद Application_Start में निम्नलिखित कॉल करें:

WebApiConfig.Register(RouteTable.Routes);

डॉट नेट कोर

Microsoft.AspNetCore.Session NuGet पैकेज जोड़ें और फिर निम्नलिखित कोड परिवर्तन करें:

Startup.cs

ConfigureServices फ़ंक्शन के भीतर AddDistributedMemoryCache और AddSession विधियों को सेवा ऑब्जेक्ट पर कॉल करें :

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

    services.AddDistributedMemoryCache();
    services.AddSession();

और कॉन्फ़िगर फ़ंक्शन में UseSession में कॉल जोड़ें :

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
ILoggerFactory loggerFactory)
{
    app.UseSession();
    app.UseMvc();

SessionController.cs

अपने नियंत्रक के भीतर, शीर्ष पर एक उपयोग कथन जोड़ें:

using Microsoft.AspNetCore.Http;

और फिर अपने कोड के भीतर HttpContext.Session ऑब्जेक्ट का उपयोग करें जैसे:

    [HttpGet("set/{data}")]
    public IActionResult setsession(string data)
    {
        HttpContext.Session.SetString("keyname", data);
        return Ok("session data set");
    }

    [HttpGet("get")]
    public IActionResult getsessiondata()
    {
        var sessionData = HttpContext.Session.GetString("keyname");
        return Ok(sessionData);
    }

अब आपको हिट करने में सक्षम होना चाहिए:

http://localhost:1234/api/session/set/thisissomedata

और फिर इस URL पर जाकर इसे बाहर निकाला जाएगा:

http://localhost:1234/api/session/get

डॉट नेट कोर के भीतर सत्र डेटा तक पहुँचने के बारे में अधिक जानकारी: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state

प्रदर्शन की चिंता

प्रदर्शन के बारे में नीचे साइमन वीवर का जवाब पढ़ें। यदि आप WebApi प्रोजेक्ट के अंदर सत्र डेटा एक्सेस कर रहे हैं, तो इसका बहुत गंभीर प्रदर्शन परिणाम हो सकता है - मैंने देखा है ASP.NET समवर्ती अनुरोधों के लिए 200ms देरी लागू करता है। यदि आप कई समवर्ती अनुरोधों को जोड़ सकते हैं और यह विनाशकारी हो सकता है।


सुरक्षा चिंतायें

सुनिश्चित करें कि आप प्रति उपयोगकर्ता संसाधनों को लॉक कर रहे हैं - एक प्रमाणित उपयोगकर्ता को आपके WebApi से डेटा पुनर्प्राप्त करने में सक्षम नहीं होना चाहिए, जिसके लिए वे एक्सेस नहीं करते हैं।

ASP.NET वेब एपीआई में प्रमाणीकरण और प्राधिकरण पर Microsoft का लेख पढ़ें - https://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

क्रॉस-साइट रिक्वेस्ट फॉरगेरी हैक हमलों से बचने के लिए Microsoft का लेख पढ़ें। (संक्षेप में, AntiForgery.Validate विधि देखें) - https://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks


7
उत्तम। सरल और यह काम करता है। गैर-एमवीसी के लिए, केवल Application_PostAuthorizeRequest () को Global.ascx.cs में जोड़ें।
mhenry1384

1
धन्यवाद @JCallico, मुझे लगता है कि ज्यादातर लोग पहले ASP.NET पेज को हिट करते हैं जो सत्र बनाता है।
रॉकलन

3
मुझे IsWebApiRequest () को सही करने के लिए संशोधित करने की आवश्यकता है जहां पथ WebApiConfig.UrlPrefix के साथ शुरू होता है, साथ ही WebApiConfig.UrlPrefixRelative। इसके अलावा, उम्मीद के मुताबिक काम करता है।
gb2d

7
इस फिक्स के बारे में उल्लेख करने के लिए एक बात। आवश्यक होने पर SessionStateBehavior सेट करते समय, आप वेबपीआई को टोंटी मार रहे हैं, क्योंकि आपके सभी अनुरोध सत्र ऑब्जेक्ट पर ताले के कारण सिंक्रनाइज़ किए गए चलेंगे। आप इसके बजाय इसे SessionStateBehavior.eadonly के रूप में चला सकते हैं। इस तरह यह सत्र वस्तु पर ताले नहीं बनाएगा।
माइकल केर हेंसन

2
"आवश्यक" सत्र राज्य व्यवहार सेट करते समय सावधान रहें। लिखने की अनुमति के साथ अनुरोध सत्र को बंद कर देगा और प्रति ग्राहक के लिए कई HttpApplications को रोका जाएगा। आपको प्रत्येक मार्ग के लिए सत्र राज्य को एक उपयुक्त स्तर पर सेट करना चाहिए। कृपया मेरे जवाब का यहाँ उल्लेख करें: stackoverflow.com/a/34727708/1412787
एक्सल विल्केक

66

आप कस्टम रूटहैंडलर का उपयोग करके सत्र राज्य तक पहुंच सकते हैं।

// In global.asax
public class MvcApp : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        var route = routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        route.RouteHandler = new MyHttpControllerRouteHandler();
    }
}

// Create two new classes
public class MyHttpControllerHandler
    : HttpControllerHandler, IRequiresSessionState
{
    public MyHttpControllerHandler(RouteData routeData) : base(routeData)
    { }
}
public class MyHttpControllerRouteHandler : HttpControllerRouteHandler
{
    protected override IHttpHandler GetHttpHandler(
        RequestContext requestContext)
    {
        return new MyHttpControllerHandler(requestContext.RouteData);
    }
}

// Now Session is visible in your Web API
public class ValuesController : ApiController
{
    public string Get(string input)
    {
        var session = HttpContext.Current.Session;
        if (session != null)
        {
            if (session["Time"] == null)
                session["Time"] = DateTime.Now;
            return "Session Time: " + session["Time"] + input;
        }
        return "Session is not availabe" + input;
    }
}

यहाँ पाया गया: http://techhasnoboundary.blogspot.com/2012/03/mvc-4-web-api-access-ession.html


14
अद्यतन: यदि आपका API सत्र से पढ़ता है, और सत्र को संशोधित नहीं करता है, तो IRequiresSessionState के बजाय IReadOnlySessionState का उपयोग करना एक अच्छा विचार हो सकता है। यह सुनिश्चित करता है कि एपीआई फ़ंक्शन के प्रसंस्करण के दौरान सत्र लॉक नहीं है।
वारिक

6
MVC 4 में मेरे लिए काम नहीं कर रहा है - मार्ग। RouteHandler मेरे लिए एक संपत्ति भी नहीं है। @LachlanB लगता है कि मेरे लिए क्या काम किया है।
bkwdesign

3
MVC समाधान को इंगित करने के लिए @bkwdesign धन्यवाद। यह उत्तर केवल वेब एपीआई से संबंधित है।
वारिक

2
यह रूट विशेषता का समर्थन नहीं करता है। विचार?
टिम एस

जैसा कि bkwdesign ने बताया है, यह अब समर्थित नहीं है। हालाँकि, डेटाटॉकेंस का उपयोग करके प्रति रूट सत्र व्यवहार को परिभाषित करने का एक तरीका है: stackoverflow.com/a/34727708/1412787
एक्सल

46

WebAPI में सत्र का उपयोग करने से क्यों बचें?

प्रदर्शन, प्रदर्शन, प्रदर्शन!

वहाँ एक बहुत अच्छा है, और अक्सर अनदेखी कारण है कि आप WebAPI में सत्र का उपयोग क्यों नहीं किया जाना चाहिए।

जिस तरह से ASP.NET काम करता है, जब सत्र उपयोग में है, तो एकल क्लाइंट से प्राप्त सभी अनुरोधों को क्रमबद्ध करना है । अब मैं ऑब्जेक्ट सीरियलाइज़ेशन के बारे में बात नहीं कर रहा हूं - लेकिन उन्हें प्राप्त क्रम में चला रहा हूं और प्रत्येक को अगले चलाने से पहले पूरा होने की प्रतीक्षा कर रहा हूं। यदि दो अनुरोध एक साथ सत्र तक पहुंचने का प्रयास करते हैं तो यह गंदा धागा / दौड़ की स्थिति से बचने के लिए है।

समवर्ती अनुरोध और सत्र राज्य

ASP.NET सत्र की स्थिति तक पहुंच प्रति सत्र अनन्य है, जिसका अर्थ है कि यदि दो अलग-अलग उपयोगकर्ता समवर्ती अनुरोध करते हैं, तो प्रत्येक अलग सत्र तक पहुंच की अनुमति दी जाती है। हालाँकि, यदि एक ही सत्र (समान सत्र मान का उपयोग करके) के लिए दो समवर्ती अनुरोध किए जाते हैं, तो पहले अनुरोध को सत्र की जानकारी तक विशेष पहुंच प्राप्त होती है। पहला अनुरोध समाप्त होने के बाद ही दूसरा अनुरोध निष्पादित होता है।(दूसरा सत्र भी एक्सेस प्राप्त कर सकता है यदि सूचना पर अनन्य लॉक को मुक्त कर दिया जाता है क्योंकि पहला अनुरोध लॉक टाइम-आउट से अधिक है।) यदि @ पेज निर्देश में EnableSessionState मान ReadOnly पर सेट है, तो केवल-पढ़ने के लिए अनुरोध। सत्र की जानकारी सत्र डेटा पर अनन्य लॉक के परिणामस्वरूप नहीं होती है। हालाँकि, सत्र डेटा के लिए रीड-ओनली अनुरोधों को अभी भी सेशन डेटा के क्लियर होने के लिए रीड-राइट रिक्वेस्ट द्वारा लॉक सेट का इंतजार करना पड़ सकता है।

तो इसका Web Web के लिए क्या मतलब है? यदि आपके पास कई AJAX अनुरोधों को चलाने वाला एप्लिकेशन है तो केवल एक ही समय में चलने में सक्षम होने जा रहा है। यदि आपके पास एक धीमी अनुरोध है, तो यह उस क्लाइंट से अन्य सभी को तब तक अवरुद्ध करेगा जब तक कि यह पूरा न हो जाए। कुछ अनुप्रयोगों में यह बहुत ही सुस्त प्रदर्शन को जन्म दे सकता है।

तो आपको शायद एमवीसी नियंत्रक का उपयोग करना चाहिए यदि आपको उपयोगकर्ता सत्र से कुछ चाहिए और वेबएपी के लिए इसे सक्षम करने के अनावश्यक प्रदर्शन के दंड से बचना चाहिए।

आप इसे आसानी से Thread.Sleep(5000)एक WebAPI विधि में डालकर और सत्र को सक्षम करके अपने लिए आसानी से देख सकते हैं । इसके लिए 5 अनुरोध चलाएं और उन्हें पूरा होने में कुल 25 सेकंड लगेंगे। सत्र के बिना वे सिर्फ 5 सेकंड में कुल ले लेंगे।

(यह एक ही तर्क सिग्नलआर पर लागू होता है)।


18
यदि आप केवल सत्र से पढ़ते हैं, तो आप [SessionState (SessionStateBehavior.ReadOnly)] का उपयोग करके इसे प्राप्त कर सकते हैं।
रॉकलन

21

ठीक है तुम सही हो, बाकी स्टेटलेस है। यदि आप एक सत्र का उपयोग करते हैं तो प्रसंस्करण स्टेटफुल हो जाएगा, बाद के अनुरोध राज्य (एक सत्र से) का उपयोग करने में सक्षम होंगे।

एक सत्र को फिर से निर्जलित करने के लिए, आपको राज्य को संबद्ध करने के लिए एक कुंजी की आपूर्ति करनी होगी। एक सामान्य asp.net एप्लिकेशन में जो कि एक कुकी (कुकी-सत्र) या url पैरामीटर (Cookieless session) का उपयोग करके आपूर्ति की जाती है।

यदि आपको सत्र भूल जाने की आवश्यकता है, सत्र REST आधारित डिज़ाइनों में अप्रासंगिक हैं। यदि आपको सत्यापन के लिए सत्र की आवश्यकता है, तो एक टोकन का उपयोग करें या आईपी पते द्वारा अधिकृत करें।


10
मैं इसके बारे में आश्वस्त नहीं हूं। Microsoft के उदाहरणों में वे प्राधिकरण विशेषता का उपयोग करके दिखाते हैं। मैंने कोशिश की है और यह प्रपत्र आधारित प्रमाणीकरण के साथ काम करता है। वेब एपीआई प्रमाणीकरण स्थिति से अवगत है जो डिफ़ॉल्ट प्रमाणीकरण कुकी में पारित किया जा रहा है।
निशान

4
यहाँ वह नमूना है जिसका मैं उल्लेख कर रहा हूँ, code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7 । यह नए REST पर आधारित वेब API का उपयोग करता है प्रपत्र प्रमाणीकरण।
निशान

4
मैंने सत्र राज्य की आवश्यकता के बिना सफलतापूर्वक [अधिकृत] विशेषता का उपयोग किया है। मैंने पहचान सेट करने के लिए सिर्फ एक प्रमाणीकरण संदेश हैंडलर लिखा।
एंटनी स्कॉट

57
आपको नीचे इसलिए चिह्नित किया गया क्योंकि आपने उसकी समस्या का उत्तर नहीं दिया, और इसी तरह, वेब एप एक अतुल्यकालिक ढांचा है जो कि अजाक्स भारी वेब एप के साथ शानदार काम करता है। किसी ने नहीं कहा कि आपको वेब एपीआई ढांचे का उपयोग करने से लाभ प्राप्त करने के लिए रेस्टफुल डिजाइन के सभी किरायेदारों का सम्मान करना होगा।
ब्रायन ओग्डेन

3
@निशान। यह बताना सही है कि वेब एपीआई को सत्र की स्थिति के बारे में पता नहीं है। नकारात्मक जवाब अभी भी एक जवाब है। अप वोट।
एंटोनी मेल्टज़ाइम

20

यदि आप nerddinner MVC उदाहरण की जाँच करते हैं, तो तर्क बहुत अधिक है।

आपको केवल कुकी को पुनः प्राप्त करना होगा और इसे वर्तमान सत्र में सेट करना होगा।

Global.asax.cs

public override void Init()
{
    this.AuthenticateRequest += new EventHandler(WebApiApplication_AuthenticateRequest);
    base.Init();
}

void WebApiApplication_AuthenticateRequest(object sender, EventArgs e)
{
    HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);

    SampleIdentity id = new SampleIdentity(ticket);
    GenericPrincipal prin = new GenericPrincipal(id, null); 

    HttpContext.Current.User = prin;
}

enter code here

आपको अपने "सेम्पलडिटी" वर्ग को परिभाषित करना होगा, जिसे आप nerddinner परियोजना से उधार ले सकते हैं ।


पहचान वर्ग NerdDinner_2.0 \ NerdDinner \ मॉडल \ NerdIdentity.cs में है।
mhenry1384

यह मेरे लिए काम नहीं करता (.NET 4 में)। मेरे पास कभी वह कुकी नहीं है। क्या यह केवल तभी काम करता है जब आपके पास फॉर्म ऑथेंटिकेशन चालू हो?
mhenry1384

लॉगिन फ़ॉर्म के माध्यम से प्रमाणित करने के बाद कुकी वास्तव में उत्पन्न हो जाती है। आप यह भी अनुकूलित कर सकते हैं कि कैसे / जब यह बन जाता है, तो stackoverflow.com/questions/7217105 देखें लेकिन आपको अभी भी उपयोगकर्ता को वेब सर्वर के खिलाफ प्रभावी रूप से प्रमाणित करने की आवश्यकता है
JSancho

प्रश्न HttpContext.Current.Session के लिए पूछता है और यह उत्तर स्पष्ट रूप से नहीं बताता है कि क्या करने की आवश्यकता है। @LachlanB उत्तर देखें।
जेक्लिको

14

इस मुद्दे को ठीक करने के लिए:

protected void Application_PostAuthorizeRequest()
{
    System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}

Global.asax.cs में


4
चेतावनी! यह सभी अनुरोधों के लिए सत्र को सक्षम करेगा। यदि आपका एप्लिकेशन एम्बेडेड संसाधनों का उपयोग कर रहा है तो यह वास्तव में प्रदर्शन को नुकसान पहुंचा सकता है।
13

@cgatian कोई वैकल्पिक समाधान तय किया ?
किकेनेट

मुझे लगता है कि सबसे अच्छा तरीका वही है जो @ ट्रेफोर सुझाव देता है। सभी अनुरोधों के लिए इसे सक्षम न करें। बस ऐसे रूट जिनमें URL में "/ api" या कुछ है। इसके अलावा, यदि संभव हो तो सत्र राज्य केवल अपने एपीआई नियंत्रकों के लिए पढ़ें।
cgatian

10

पिछले एक काम नहीं कर रहा है, यह एक ले लो, यह मेरे लिए काम किया।

Web_piConfig.cs में App_Start पर

    public static string _WebApiExecutionPath = "api";

    public static void Register(HttpConfiguration config)
    {
        var basicRouteTemplate = string.Format("{0}/{1}", _WebApiExecutionPath, "{controller}");

        // Controller Only
        // To handle routes like `/api/VTRouting`
        config.Routes.MapHttpRoute(
            name: "ControllerOnly",
            routeTemplate: basicRouteTemplate//"{0}/{controller}"
        );

        // Controller with ID
        // To handle routes like `/api/VTRouting/1`
        config.Routes.MapHttpRoute(
            name: "ControllerAndId",
            routeTemplate: string.Format ("{0}/{1}", basicRouteTemplate, "{id}"),
            defaults: null,
            constraints: new { id = @"^\d+$" } // Only integers 
        );

Global.asax

protected void Application_PostAuthorizeRequest()
{
  if (IsWebApiRequest())
  {
    HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
  }
}

private static bool IsWebApiRequest()
{
  return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(_WebApiExecutionPath);
}

यहां चौथा: http://forums.asp.net/t/1773026.aspx/1


यह सबसे सरल उपाय है लेकिन कोड में कुछ गलतियाँ हैं ताकि यह वास्तव में काम न करे। मैंने इस पर आधारित एक और समाधान पोस्ट किया है, मेरा मिलान करने के लिए आपका संपादन करने के लिए स्वतंत्र महसूस करें।
रॉकलैन

_WebApiExecutionPath लाइन पर थोड़ा सुधार सार्वजनिक स्थैतिक स्ट्रिंग को पढ़ने की जरूरत है _WebApiExecutionPath = "~ / api";
स्टीफन इबिचोंडो

8

LachlanB के उत्तर पर अनुसरण करने के बाद, यदि आपका ApiController किसी विशेष निर्देशिका (जैसे / एपीआई) के भीतर नहीं बैठता है, तो आप इसके बजाय RouteTable.Routes.GetRouteData का उपयोग करके अनुरोध का परीक्षण कर सकते हैं:

protected void Application_PostAuthorizeRequest()
    {
        // WebApi SessionState
        var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
        if (routeData != null && routeData.RouteHandler is HttpControllerRouteHandler)
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
    }

8

मैं asp.net mvc में यह एक ही समस्या थी, मैंने इसे अपने आधार एपीआई नियंत्रक में यह विधि डालकर तय किया कि मेरे सभी एपीआई नियंत्रक से विरासत में मिले:

    /// <summary>
    /// Get the session from HttpContext.Current, if that is null try to get it from the Request properties.
    /// </summary>
    /// <returns></returns>
    protected HttpContextWrapper GetHttpContextWrapper()
    {
      HttpContextWrapper httpContextWrapper = null;
      if (HttpContext.Current != null)
      {
        httpContextWrapper = new HttpContextWrapper(HttpContext.Current);
      }
      else if (Request.Properties.ContainsKey("MS_HttpContext"))
      {
        httpContextWrapper = (HttpContextWrapper)Request.Properties["MS_HttpContext"];
      }
      return httpContextWrapper;
    }

फिर अपने एपीआई कॉल में जिसे आप अभी-अभी करना चाहते हैं, उस सत्र को एक्सेस करना चाहते हैं:

HttpContextWrapper httpContextWrapper = GetHttpContextWrapper();
var someVariableFromSession = httpContextWrapper.Session["SomeSessionValue"];

मेरे पास यह Global.asax.cs फ़ाइल में भी है जैसे अन्य लोगों ने पोस्ट किया है, निश्चित नहीं कि अगर आपको अभी भी ऊपर की विधि का उपयोग करने की आवश्यकता है, लेकिन यहां यह सिर्फ मामले में है:

/// <summary>
/// The following method makes Session available.
/// </summary>
protected void Application_PostAuthorizeRequest()
{
  if (HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith("~/api"))
  {
    HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
  }
}

आप केवल एक कस्टम फ़िल्टर विशेषता भी बना सकते हैं, जिसे आप अपनी एपीआई कॉल पर चिपका सकते हैं, जिसे आपको सत्र की आवश्यकता है, तो आप अपने एपीआई कॉल में सत्र का उपयोग कर सकते हैं जैसे कि आप सामान्य रूप से HttpContext.Current.Session ["SomeValue"] के माध्यम से कर सकते हैं:

  /// <summary>
  /// Filter that gets session context from request if HttpContext.Current is null.
  /// </summary>
  public class RequireSessionAttribute : ActionFilterAttribute
  {
    /// <summary>
    /// Runs before action
    /// </summary>
    /// <param name="actionContext"></param>
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
      if (HttpContext.Current == null)
      {
        if (actionContext.Request.Properties.ContainsKey("MS_HttpContext"))
        {
          HttpContext.Current = ((HttpContextWrapper)actionContext.Request.Properties["MS_HttpContext"]).ApplicationInstance.Context;
        }
      }
    }
  }

उम्मीद है की यह मदद करेगा।


6

मैंने @LachlanB दृष्टिकोण का पालन किया और जब सत्र कुकी अनुरोध पर मौजूद थी तब वास्तव में सत्र उपलब्ध था। गायब हिस्सा यह है कि ग्राहक को पहली बार सत्र कुकी कैसे भेजी जाती है?

मैंने एक HttpModule बनाया जो न केवल HttpSessionState उपलब्धता को सक्षम करता है, बल्कि एक नया सत्र तैयार होने पर ग्राहक को कुकी भी भेजता है।

public class WebApiSessionModule : IHttpModule
{
    private static readonly string SessionStateCookieName = "ASP.NET_SessionId";

    public void Init(HttpApplication context)
    {
        context.PostAuthorizeRequest += this.OnPostAuthorizeRequest;
        context.PostRequestHandlerExecute += this.PostRequestHandlerExecute;
    }

    public void Dispose()
    {
    }

    protected virtual void OnPostAuthorizeRequest(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;

        if (this.IsWebApiRequest(context))
        {
            context.SetSessionStateBehavior(SessionStateBehavior.Required);
        }
    }

    protected virtual void PostRequestHandlerExecute(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;

        if (this.IsWebApiRequest(context))
        {
            this.AddSessionCookieToResponseIfNeeded(context);
        }
    }

    protected virtual void AddSessionCookieToResponseIfNeeded(HttpContext context)
    {
        HttpSessionState session = context.Session;

        if (session == null)
        {
            // session not available
            return;
        }

        if (!session.IsNewSession)
        {
            // it's safe to assume that the cookie was
            // received as part of the request so there is
            // no need to set it
            return;
        }

        string cookieName = GetSessionCookieName();
        HttpCookie cookie = context.Response.Cookies[cookieName];
        if (cookie == null || cookie.Value != session.SessionID)
        {
            context.Response.Cookies.Remove(cookieName);
            context.Response.Cookies.Add(new HttpCookie(cookieName, session.SessionID));
        }
    }

    protected virtual string GetSessionCookieName()
    {
        var sessionStateSection = (SessionStateSection)ConfigurationManager.GetSection("system.web/sessionState");

        return sessionStateSection != null && !string.IsNullOrWhiteSpace(sessionStateSection.CookieName) ? sessionStateSection.CookieName : SessionStateCookieName;
    }

    protected virtual bool IsWebApiRequest(HttpContext context)
    {
        string requestPath = context.Request.AppRelativeCurrentExecutionFilePath;

        if (requestPath == null)
        {
            return false;
        }

        return requestPath.StartsWith(WebApiConfig.UrlPrefixRelative, StringComparison.InvariantCultureIgnoreCase);
    }
}

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

3

@LachlanB के उत्तर पर एक बात का उल्लेख करने की आवश्यकता है।

protected void Application_PostAuthorizeRequest()
    {
        if (IsWebApiRequest())
        {
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
        }
    }

यदि आप लाइन को छोड़ देते हैं if (IsWebApiRequest())

यदि आपकी साइट को वेब फ़ॉर्म पृष्ठों के साथ मिलाया गया है, तो पूरी साइट पर पृष्ठ लोडिंग सुस्ती का मुद्दा होगा।


0

हां, सत्र रेस्ट एपीआई के साथ हाथ से नहीं जाता है और हमें इस प्रथाओं से बचना चाहिए। लेकिन आवश्यकताओं के अनुसार हमें किसी भी तरह सत्र को बनाए रखने की आवश्यकता होती है ताकि हर अनुरोध में क्लाइंट सर्वर राज्य या डेटा का आदान-प्रदान कर सके या बनाए रख सके। तो, REST प्रोटोकॉल को तोड़े बिना इसे प्राप्त करने का सबसे अच्छा तरीका है JWT जैसे टोकन के माध्यम से संवाद करना।

https://jwt.io/


-4

मूल बातों पर वापस जाकर इसे सरल क्यों न रखें और अपने एपीआई में पारित करने के लिए एक छिपे हुए HTML मान में सत्र मूल्य को संग्रहीत करें?

नियंत्रक

public ActionResult Index()
        {

            Session["Blah"] = 609;

            YourObject yourObject = new YourObject();
            yourObject.SessionValue = int.Parse(Session["Blah"].ToString());

            return View(yourObject);
        }

cshtml

@model YourObject

@{
    var sessionValue = Model.SessionValue;
}

<input type="hidden" value="@sessionValue" id="hBlah" />

जावास्क्रिप्ट

$ (दस्तावेज़)। पहले से ही (फ़ंक्शन) {

    var sessionValue = $('#hBlah').val();

    alert(sessionValue);

    /* Now call your API with the session variable */}

}


1
यदि आवेदन MVC और WebAPI दोनों का उपयोग करता है तो क्या होगा? इसके अलावा, सर्वर साइड पर स्टोर की जाने वाली कुछ चीजें भी अधिक उचित हैं, जैसे कि शेयरपॉइंट सुरक्षा टोकन। एज़्योर ब्लॉब्स कंटेनर की तरह टोकन भंडारण के लिए एक विशेष आवरण को लागू करने के बजाय, कभी-कभी इस प्रकार के डेटा के लिए उचित पुन: उपयोग सत्र होता है। शेयरपॉइंट सुरक्षा संदर्भ जैसा कि ऐप टेम्प्लेट में लागू किया गया है, इन सुरक्षा संदर्भों को संग्रहीत करने के लिए सत्र का उपयोग करता है, और डेटा के केवल छोटे टुकड़े को स्थानांतरित किया जा रहा है (सत्र टैग) कुछ किलोबाइट डेटा के बजाय। अगर ये प्रसंग और छोटा होगा तो भयानक होगा ...
कॉन्सटेंटिन इसेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.