Access HttpContext.Current.Session in Nancy Module - asp.net

I've read a lot of answers saying to just use the built-in Nancy Session/User object, but this isn't an option in my case.
Using WCF I was able to access the ASP.Net Session["SomethingStuffedIntoSessionFromAWebForm"] by enabling aspNetCompatibilityEnabled in the web.config (other stuff had to been done too, probably), but I can't seem to figure out how to get a handle on the System.Web.HttpContext.Current.Session (or anything else in the current context) from within a Nancy module.
My 1st thought was to inject it in the bootstrapper but I can't even get a handle on the System.Web.HttpContext.Current.Session there either. Any ideas?
Edit
I ended up just stuffing an encrypted version of my desired session object into a cookie upstream and checking/validating against it in the module's BeforePipeline... not too crazy about this approach, but it suits my needs for now.
As far as I can tell, when a Nancy module handles a request, it bypasses the Asp.Net pipeline, so while I actually do have access to HttpContext.Current, Session is not populated.

Inherit IRequiresSessionState to enable Asp.net Session.
public class NancyAspHttpRequestHandler
: NancyHttpRequestHandler, IRequiresSessionState
{
}
and use NancyAspHttpRequestHandler in handler registration, this can be possible using Nancy.AspNet hosting.
This will solve the problem

Related

Is it possible to access HttpContext.Current.Session from Web API

Is it possible to access HttpContext.Current.Session through a WebAPI ? can we make it inheriting IRequiresSession?
I have a generic handler doing a Session set after an API call which I want to remove.
public void AccountController : ApiController, IRequiresSessionState
{
public void Login()
{
setsession(){}
}
}
Technically, yes, although I'd really advise against this practice - a REST API should be completely stateless (cookies and other client-side state is OK).
If you absolutely must do this, you can grab the HTTP context like so:
var context = Request.Properties["MS_HttpContext"] as HttpContext;
At which point you just use its Session property to get the session.
Note that this breaks certain contracts assumed by System.Net.Http - specifically it means your API controllers can never be self-hosted because they're coupled to ASP.NET. If you're OK with this, and with the fact that your API controllers may not work properly from a web farm unless you re-architect everything to use distributed sessions - well then, go for it.
P.S. It is also possible to use IRequiresSessionState, but you can't use it on the controller itself, you need to use it on an HttpControllerHandler and set it as the RouteHandler. The approach is discussed in this MSDN thread. Again, I can't recommend strongly enough against this idea, it violates the basic principle of a Web API - but, if you've got a really good reason for it, then it's another option which is a bit more reusable.
Casting it as HttpContext did not work for me using Web Api 2.1. However I could use HttpContextWrapper.
var context = Request.Properties["MS_HttpContext"] as HttpContextWrapper;
Yes - although not recommended. Here's a working answer based on the answers above (for WebAPI version 2.x)
var context =(HttpContextWrapper)Request.Properties["MS_HttpContext"];
var sessionId = context.Request.Params["ASP.NET_SessionId"];

Are ASMX Web Service Enable Session and ResponseFormat Required

I have been asked to change a legacy .asmx web service and there are a few issues I would appreciate some guidance on.
The web methods are decorated like this:
[WebMethod(EnableSession = true), ScriptMethod(ResponseFormat = ResponseFormat.Json)]
In my particular method, I am returning data from a database, which I return as a list of to of objects using JSON.
I noticed that the JSON is still returned without the: ScriptMethod(ResponseFormat = ResponseFormat.Json part.
In that case:
can I safely remove this from here?
if it still works, does that mean it will be configured elsewhere in a base class or config file perhaps?
What is the purpose of the (EnableSession = true) and is it required if the service does not update the data and the read data is rarely changed?
Sorry for the basic rather vague questions but I've not worked with .asmx web services before. Can someone point me in the right direction please?
Thanks
EnableSession = true allows you to access the Session collection, which is part of the HttpContext.Current.Session. If the code in your web method does not use the Session collection, then yes it is safe to remove, but if it does use the Session collection, then removing this attribute will cause your web service logic to throw an exception, because it will not have access to the Session collection.
ScriptMethod(ResponseFormat = ResponseFormat.Json) is explicitly defining that this web method will return JSON, but since JSON is the default return type, then removing it does not matter. So the short answer is, yes it is fine to remove this, but it will not hurt to leave it there (in fact I would argue that is better to because it explicitly states this thing is returning JSON data).
AS #Karl already said if you need to access Session in webmethod, you've to decorate your method with the said attribute.
Now I've seen people complaining about webmethod not returning JSON response on SO and Asp.net official forum even though they have decorated their method with
ScriptMethod(ResponseFormat = ResponseFormat.Json)
because they might have missing configuration in web.config.
I would suggest you to go through Dave Ward's below articles that may help you to understand what needs to be done to return JSON response with ASMX:
ASMX and JSON – Common mistakes and misconceptions
ASMX ScriptService mistake: Installation and configuration

Best way to perform authentication on every request

In my asp.net mvc 2 app, I'm wondering about the best way to implement this:
For every incoming request I need to perform custom authorization before allowing the file to be served. (This is based on headers and contents of the querystring. If you're familiar with how Amazon S3 does rest authentication - exactly that).
I'd like to do this in the most perfomant way possible, which probably means as light a touch as possible, with IIS doing as much of the actual work as possible.
The service will need to handle GET requests, as well as writing new files coming in via POST/PUT requests.
The requests are for an abitrary file, so it could be:
GET http://storage.foo.com/bla/egg/foo18/something.bin
POST http://storage.foo.com/else.txt
Right now I've half implemented it using an IHttpHandler which handles all routes (with routes.RouteExistingFiles = true), but not sure if that's the best, or if I should be hooking into the lifecycle somewhere else?
I'm also interested in supporting partial downloads with the Range header. Using
response.TransmitFile(finalPath);
as I am now means I'll have to do that manually, which seems a bit lowlevel?
Many thanks for any pointers.
(IIS7)
I think having a custom handler in the middle that takes care of this is exactly how you should be doing it.
TransmitFile is the lightest-weight programmatic way to serve a file that I am aware of.
However, you might not need to write your own HttpHandler. You can use the MVC handler and just dedicate a controller action to the job. Something like:
http://storage.foo.com/Files/Download/SomeFileIdentifier
...routing to...
public FilesController
{
public ActionResult Download(string id)
{
//...some logic to authenticate and to get the local file path
return File(theLocalFilePath, mimeType);
}
}
The File() method of controller uses TransmitFile in the background, I believe.
(PS, If you want shorter URLs, do it via custom routes in global.asax.)

ASP.net web services

I am using a web service which sets the Thread.CurrentPrincipal object while logging in and soon later when another webmethod of the same web service accesses Thread.CurrentPrincipal, its different/resets
Can someone tell me if this is expected or can different webmethod calls from the same client can access the same Thread.CurrentPrincipal object
Thanks
As soon as you stop using a thread it goes back into the thread pool.
The next call will take a thread from the thread pool, but you have no control which one you get.
You need to send information about which user is making the call, with each request.
This is expected, every new web request is actually new thread. And every web request reset stuff like CurrentThread, CurrentCulture and so on.
What are you trying to do is authentication session. There are many possible solutions. But to suggest something I have to specify technology you use.
For example, ASP.NET ASMX Services can use Forms Authentication. Also they are aware about ASP.NET Session.
With WCF, you can enable ASP.NET support, so you will have same stuff like for ASP.NET ASMX Services. But you also can leverage on Windows Communication Foundation Authentication Service.
Anyways need more info from you.
If you are using the built-in ASP .NET authentication for your website and then just calling the web service from a web page, you may be able to enable session variables and user context information in the methods of the web service with a decoration. Like this:
[WebMethod(EnableSession=true)]
public void MyWebMethod()
{
string mySessionVar = HttpContext.Current.Session["sessionVar"].ToString();
IPrincipal currentUser = HttpContext.Current.User;
...
}
If that doesn't solve your problem, tell us what are you using the Thread.CurrentPrincipal object for (what you are pulling out of the Thread.CurrentPrincipal object). Perhaps there is another solution.

Readonly access to session in a web service call?

We have a .net asmx web service that gets called from javascript (using ASP.Net AJAX), and requires access to Session.
[WebMethod(true)]
public string DoSomethingOnTheServer() { }
We're running into the problem of session being locked on a read/write request. Is there any way to mark a web service method as requiring read-only access to Session?
Thanks!
This is a really old thread, but i stumbled on it in my search for an answer to the same question.
I found the answer else where, and will leave it here for other internets in my place:
In Global.asax you can specify for each request, what access the request should have to the session object, and thereby if it should block or not.
private void Application_BeginRequest(object sender, EventArgs e)
{
// This will set the session to read only for asmx services
// This will make the asmx services non blocking for other requests as it doesnt lock the session object
if (Context.Request.Path.Contains(".asmx/"))
{
Context.SetSessionStateBehavior(SessionStateBehavior.ReadOnly);
}
}
This way asmx services always only have read only access to the session and will not block other requests
This http://msdn.microsoft.com/en-us/library/aa480509.aspx page seems to suggest that the answer is "no" - you cannot mark a WebSerivce as having EnableSessionState=ReadOnly.
If you are making simultaneous Web service calls from the same process, the requests will be serialized at the server so that only one will execute at any one time. Unlike .ASPX pages that have support for read-only access to the HttpSessionState object, which allows for simultaneous processing of multiple requests, there is no such capability with ASP.NET Web services. All Web method calls with sessions enabled have read/write access and will be serialized within each session.
Warning: That article is old (2002).
According to the MSDN documentation of the WebMethod Attribute there are several possible properties, so I'm not sure what the 'true' value in your WebMethod Attribute going to do.
Have you tried:
[WebMethod(EnableSession=true)]
According to this document that should give you full access to the session.

Resources