मुझे लगता है कि सत्र और आरईएसटी वास्तव में हाथ से नहीं जाते हैं, लेकिन क्या नए वेब एपीआई का उपयोग करके सत्र राज्य तक पहुंच संभव नहीं है? HttpContext.Current.Session
हमेशा अशक्त रहता है।
मुझे लगता है कि सत्र और आरईएसटी वास्तव में हाथ से नहीं जाते हैं, लेकिन क्या नए वेब एपीआई का उपयोग करके सत्र राज्य तक पहुंच संभव नहीं है? HttpContext.Current.Session
हमेशा अशक्त रहता है।
जवाबों:
MVC
MVC प्रोजेक्ट के लिए निम्नलिखित परिवर्तन करें (WebForms और Dot Net Core नीचे उत्तर दें):
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 }
);
}
}
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 ला सकते हैं:
<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 पैकेज जोड़ें और फिर निम्नलिखित कोड परिवर्तन करें:
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();
अपने नियंत्रक के भीतर, शीर्ष पर एक उपयोग कथन जोड़ें:
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
आप कस्टम रूटहैंडलर का उपयोग करके सत्र राज्य तक पहुंच सकते हैं।
// 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
प्रदर्शन, प्रदर्शन, प्रदर्शन!
वहाँ एक बहुत अच्छा है, और अक्सर अनदेखी कारण है कि आप WebAPI में सत्र का उपयोग क्यों नहीं किया जाना चाहिए।
जिस तरह से ASP.NET काम करता है, जब सत्र उपयोग में है, तो एकल क्लाइंट से प्राप्त सभी अनुरोधों को क्रमबद्ध करना है । अब मैं ऑब्जेक्ट सीरियलाइज़ेशन के बारे में बात नहीं कर रहा हूं - लेकिन उन्हें प्राप्त क्रम में चला रहा हूं और प्रत्येक को अगले चलाने से पहले पूरा होने की प्रतीक्षा कर रहा हूं। यदि दो अनुरोध एक साथ सत्र तक पहुंचने का प्रयास करते हैं तो यह गंदा धागा / दौड़ की स्थिति से बचने के लिए है।
समवर्ती अनुरोध और सत्र राज्य
ASP.NET सत्र की स्थिति तक पहुंच प्रति सत्र अनन्य है, जिसका अर्थ है कि यदि दो अलग-अलग उपयोगकर्ता समवर्ती अनुरोध करते हैं, तो प्रत्येक अलग सत्र तक पहुंच की अनुमति दी जाती है। हालाँकि, यदि एक ही सत्र (समान सत्र मान का उपयोग करके) के लिए दो समवर्ती अनुरोध किए जाते हैं, तो पहले अनुरोध को सत्र की जानकारी तक विशेष पहुंच प्राप्त होती है। पहला अनुरोध समाप्त होने के बाद ही दूसरा अनुरोध निष्पादित होता है।(दूसरा सत्र भी एक्सेस प्राप्त कर सकता है यदि सूचना पर अनन्य लॉक को मुक्त कर दिया जाता है क्योंकि पहला अनुरोध लॉक टाइम-आउट से अधिक है।) यदि @ पेज निर्देश में EnableSessionState मान ReadOnly पर सेट है, तो केवल-पढ़ने के लिए अनुरोध। सत्र की जानकारी सत्र डेटा पर अनन्य लॉक के परिणामस्वरूप नहीं होती है। हालाँकि, सत्र डेटा के लिए रीड-ओनली अनुरोधों को अभी भी सेशन डेटा के क्लियर होने के लिए रीड-राइट रिक्वेस्ट द्वारा लॉक सेट का इंतजार करना पड़ सकता है।
तो इसका Web Web के लिए क्या मतलब है? यदि आपके पास कई AJAX अनुरोधों को चलाने वाला एप्लिकेशन है तो केवल एक ही समय में चलने में सक्षम होने जा रहा है। यदि आपके पास एक धीमी अनुरोध है, तो यह उस क्लाइंट से अन्य सभी को तब तक अवरुद्ध करेगा जब तक कि यह पूरा न हो जाए। कुछ अनुप्रयोगों में यह बहुत ही सुस्त प्रदर्शन को जन्म दे सकता है।
तो आपको शायद एमवीसी नियंत्रक का उपयोग करना चाहिए यदि आपको उपयोगकर्ता सत्र से कुछ चाहिए और वेबएपी के लिए इसे सक्षम करने के अनावश्यक प्रदर्शन के दंड से बचना चाहिए।
आप इसे आसानी से Thread.Sleep(5000)
एक WebAPI विधि में डालकर और सत्र को सक्षम करके अपने लिए आसानी से देख सकते हैं । इसके लिए 5 अनुरोध चलाएं और उन्हें पूरा होने में कुल 25 सेकंड लगेंगे। सत्र के बिना वे सिर्फ 5 सेकंड में कुल ले लेंगे।
(यह एक ही तर्क सिग्नलआर पर लागू होता है)।
ठीक है तुम सही हो, बाकी स्टेटलेस है। यदि आप एक सत्र का उपयोग करते हैं तो प्रसंस्करण स्टेटफुल हो जाएगा, बाद के अनुरोध राज्य (एक सत्र से) का उपयोग करने में सक्षम होंगे।
एक सत्र को फिर से निर्जलित करने के लिए, आपको राज्य को संबद्ध करने के लिए एक कुंजी की आपूर्ति करनी होगी। एक सामान्य asp.net एप्लिकेशन में जो कि एक कुकी (कुकी-सत्र) या url पैरामीटर (Cookieless session) का उपयोग करके आपूर्ति की जाती है।
यदि आपको सत्र भूल जाने की आवश्यकता है, सत्र REST आधारित डिज़ाइनों में अप्रासंगिक हैं। यदि आपको सत्यापन के लिए सत्र की आवश्यकता है, तो एक टोकन का उपयोग करें या आईपी पते द्वारा अधिकृत करें।
यदि आप 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 परियोजना से उधार ले सकते हैं ।
इस मुद्दे को ठीक करने के लिए:
protected void Application_PostAuthorizeRequest()
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}
Global.asax.cs में
पिछले एक काम नहीं कर रहा है, यह एक ले लो, यह मेरे लिए काम किया।
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
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);
}
मैं 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;
}
}
}
}
उम्मीद है की यह मदद करेगा।
मैंने @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);
}
}
@LachlanB के उत्तर पर एक बात का उल्लेख करने की आवश्यकता है।
protected void Application_PostAuthorizeRequest()
{
if (IsWebApiRequest())
{
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
यदि आप लाइन को छोड़ देते हैं if (IsWebApiRequest())
यदि आपकी साइट को वेब फ़ॉर्म पृष्ठों के साथ मिलाया गया है, तो पूरी साइट पर पृष्ठ लोडिंग सुस्ती का मुद्दा होगा।
हां, सत्र रेस्ट एपीआई के साथ हाथ से नहीं जाता है और हमें इस प्रथाओं से बचना चाहिए। लेकिन आवश्यकताओं के अनुसार हमें किसी भी तरह सत्र को बनाए रखने की आवश्यकता होती है ताकि हर अनुरोध में क्लाइंट सर्वर राज्य या डेटा का आदान-प्रदान कर सके या बनाए रख सके। तो, REST प्रोटोकॉल को तोड़े बिना इसे प्राप्त करने का सबसे अच्छा तरीका है JWT जैसे टोकन के माध्यम से संवाद करना।
मूल बातों पर वापस जाकर इसे सरल क्यों न रखें और अपने एपीआई में पारित करने के लिए एक छिपे हुए 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 */}
}
[SessionState(SessionStateBehavior.Required)]
परApiController
चाल (या क्या करता है.ReadOnly
जहां उपयुक्त हो)।