Cannot share ASP.NET session with wcf service - asp.net

So, I have on same machine asp.net app and wcf service. And I'm trying to share asp.net session between them.
I have configured Sql server to store my session data.
I have ASPState Db and two tables in tempdb: ASPStateTempSessions, ASPStateTempApplications
And both have rows with data.
In asp.net app and wcf service configs I have added :
<sessionState mode="SQLServer" sqlConnectionString="Data Source=localhost;integrated security=True;Application Name=app" />
In Asp.net app I set user like this
HttpContext.Current.Session["User"] = userName;
In logs I saw an entry that user was actually setted. (and checked via JS)
In wcf service:
[ServiceContract(SessionMode = SessionMode.Allowed)]
public interface IDbWebService
{
[OperationContract]
[WebInvoke]
Data GetBlahBlah(string env);
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public partial class WebService : IDbWebService
{
public Data GetBlahBlah(string env)
{
//trying to get data here, nothing, just null
_log.InfoFormat("USER: {0}", HttpContext.Current.Session["User"]);
}
}
But I cannot get Session["User"].
What I'm doing wrong, maybe I have missed something obvious ?
Thanks in advance!

See this post:
Losing Session State with ASP.NET/SQL Server
Make sure your application ID's are the same in IIS manager and that you have the same machine key set in both configs. Both are used in the generation and encryption of session state, so if they are different you will not be able to share session entries.
On a separate note, relying on Session State to pass information between an application and a web service would seem to violate layered responsibility patterns. Your web service is now reliant on the client to provide data through this backdoor means that is not represented anywhere in the service contract. Another client consuming the service would have to provide data in the same fashion in order for the service to function correctly. Is there a reason why the data can't be supplied in the method signature?

Related

Keep getting null reference error when setting session variables [duplicate]

I have an ASMX webservice hosted alongside my ASP.NET web app. Now, I need to get the users session into the Webservice. To test this I made this simple method:
[WebMethod(EnableSession = true)]
public string checkSession()
{
return HttpContext.Current.Session["userid"].ToString();
}
So, first I login to my web app, then in the browser goto my webservice and click "checkSession" on that auto generated test page. I have tested this on 3 computers. All 3 of those work fine with the webapp(so the sessions are being created etc), and 2 of those return the value of Session["userid"] on invoking the webmethod, however the last computer returns "Object reference not set to an instance of an object" because Session is null.
So, whats the difference between these computers and why can my ASP.NET app get the sessions on all computers but the webservice cant?
maybe it's too late, but have you tried this:
[WebMethod(EnableSession = true)]
public string checkSession()
{
return HttpContext.Current.Session.SessionID
}
SessionIDs are stored as cookies on the client's browser by default (Session State Overview). So check if that cookie is being created properly on that problem computer. Maybe cookies are disabled for some reason? In that case it would not be sending the SessionID to the server when you are hitting that web service.
Can you check how many worker processes is your application using? You can check it in your App pool settings in IIS.
If more than one worker process are being used then it is called to be running a web garden. If that is the case then in proc session will not be useful as this session is not shared among the worker processes. Have a look at http://www.west-wind.com/weblog/posts/2005/Apr/20/Why-you-shouldnt-use-InProc-Session-State-in-ASPNET
Have you got Session disabled in IIS, this would over rule .net.
Have a look at this http://technet.microsoft.com/en-us/library/cc732964(v=ws.10).aspx - it tells you how to disable session, but shows where to check the setting.
Thanks
Fran
By default web services are and should be stateless. However if you must use session information be sure to use the marker interfaces IReadOnlySessionState and IRequiresSessionState in order to access, use, or modify session state information in the webservice.
Web service by default wont support Session. You need to explicitly specify the parameter in web method attribute
These two things work for me
<add name="Session"
type="System.Web.SessionState.SessionStateModule"/> under
<httpModules>
enableSessionState="true" in <page> tag
A session object is accessible by:
var session = this.Session;
var contextSession = this.Context.Session;
best way to do this approach check before your session is not null and in the other side you
initialize the selected session with your value and then when and where web service working with httpcontext.current.session have value !
web services are stateless and best way is get value in web service instead of set or initialize session value

Why is accessing session state and HttpContext in WebAPI considered bad design?

I have several .asmx web services that I want to upgrade to WebAPI. These web services look somewhat like this:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class TheWebService : System.Web.Services.WebService {
[WebMethod(EnableSession = true)]
public string SomeMethod(string SomeInput)
{
MySessionModel TheSession = HttpContext.Current.Session["UserSession"] as MySessionModel;
return SomeClass.SomeMethod(SomeInput, TheSession);
}
}
Basically, I have a single-page application. I'm using Forms Auth to login and redirect users to their "profile" and then, from this page, the app uses web services to communicate with the server. The web services only return raw strings so I don't need serialization at teh web service level. For the moment, the app is hosted in IIS and soon I'll be deploying it into azure.
I've looked around on the web, and several posts suggest that using session state and HttpContext is bad design. Why is using HttpCurrent and session state a bad idea in this case?
There is nothing innately wrong with using ASP.NET Session, as long as you don't use it as a catch-all basket for any old data. Shopping carts, for example, do not belong in Session: they belong in a Shopping Cart persistence component.
Also, and I suspect the reason for the Azure tag on this question, if you are running in a load-balanced environment such as an Azure Cloud Service, you need to use an external session provider such as a SQL Database or a shared cache. Using the in-process session provider (the default) will cause very odd, often unreproducable bugs as users are switched between different servers with different copies of the session.
As for HttpContext.Current, well, for Web API, things like Inversion of Control, Dependency Injection, and simple testability are important. A clean, testable Web API version of that service might look something like this:
public class TheWebService : ApiController {
private readonly IUserSession _userSession;
public TheWebService(IUserSession userSession)
{
_userSession = userSession;
}
public string SomeMethod(string SomeInput)
{
MySessionModel TheSession = _userSession.Get();
return SomeClass.SomeMethod(SomeInput, TheSession);
}
}
public interface IUserSession
{
MySessionModel Get();
}
You could still use HttpContext.Current.Session["UserSession"] in a class like this:
public class CurrentContextUserSession : IUserSession
{
public MySessionModel Get()
{
return HttpContext.Current.Session["UserSession"] as MySessionModel;
}
}
You would then use an IoC container such as Unity or Ninject to set CurrentContextUserSession as the implementation of IUserSession for Web API to use when constructing instances of TheWebService. But when you were writing your tests, you could use a mock or stub implementation of IUserSession that had no dependency on HttpContext.Current.
In your specific example, you are using the Session only inside the WebMethod, which is fine as it is already coupled to ASP.NET but many people tend to use this at other layers of their application which is a really bad design.
Common problems of using HttpContext.Current in those layers are:
the code cannot be easily unit tested in isolation
the code is tightly coupled to an ASP.NET context
This being said, having stateful services that depend on the session is bad design. In the example you have shown, that's an ASMX WebService which is depending on the ASP.NET Session state meaning that the client should be passing cookies around in order to invoke this service. Also stateful services are harder to scale.

ASP.NET MVC project architecture problems — authorization and session

I am finishing a project that started another programmer. Alter the entire architecture is not possible, but some things I want to overwrite. Namely - the authorization, and a way to store the current user session.
The project represents a client that communicates with the server through the soap-services. On the server, there is Security-Services, and several others, for example, A-service, B-Service.
Security service provides authentication and session key with which initialized other services.
The project is written in ASP.NET MVC3, the head of a user model, which is implemented as singletone-Class, which describes the methods of interacting with services.
How authorization works - there is CustomMembershipProvider with overridden ValidateUser method, which operates on Security-service. If successful authorization occurs the user registration in asp.net - FormsService.SignIn (model.UserName, false) and then initizalied user class:
class SiteUser
{
public static SiteUser Current
{
get
{
if (HttpContext.Current.Session.IsNewSession & &! HttpContext.Current.User.Identity.IsAuthenticated)
{
throw new UserAutorizationExeption () {Reason = AuthExceptionReason.NewSession};
}
if (HttpContext.Current.Session [sessionKey] == null)
{
FormsAuthentication.SignOut ();
throw new UserAutorizationExeption () {Reason = AuthExceptionReason.ServerSessionExpired};
}
return HttpContext.Current.Session [sessionKey] as W1User;
}
set
{
if (HttpContext.Current.Session! = null)
{
HttpContext.Current.Session [sessionKey] = value;
}
}
}
public SiteUser ()
{
}
public static SiteUser Create ()
{
SiteUser.Current = new SiteUser ();
return SiteUser.Current;
}
/ / Web-services methods go here
}
The main problem is that now the session is stored in memory:
web.config:
<sessionState mode="InProc" timeout="20" />
Set SqlServer-mode is problematic because it would be difficult SiteUser serialized. How can I get around this?
And there are problems with authorization - how to correctly do Asp.Net synchronization sessions with a session on services?
Sorry for my English, if needed clarification - ask questions. Thank you.
I personally prefer things simpler hence if I could, I would have a dedicated user to use the services so you do not have to impersonate the user down to the services layer hence having to maintain a session key.
Having said that it is not always possible, especially in a SOA environment where service layer does provide services to 3rd parties and auditing, etc. In fact my project looks like this.
You cannot get away from having a session if you need to impersonate the user to the service layer. InProc session provides better performance and SqlServer mode provides better scalability - decision on trade off is yours.
There is an alternative to store user's session key in the user table itself and retrieve every time and invalidate when user logs out. But this is only a custom implementation of user session.

asp web service: check if user is logged-in

I'm creating a web service that'll be called from a web form in asp.net. How does the web service check if the user is logged-in and if it is the logged-in user that's actually requesting the service?
thanks
It cannot. Since you're going to call the web service from ASP.NET, you're building a 3-tier application.
Tier 1 is the browser and tier 2 is ASP.NET web application. They share cookies and session variables, so ASP.NET can always authenticate the user. And you already know that.
Tier 3 is the web service. Communication between 2 and 3 is done over a different HTTP connection, sharing different cookies (actually none) and session variables (again, actually none because calls are stateless).
You then have no way to allow the web service on tier 3 to authenticate the client on tier 1.
HOWEVER...............
There is still a possibility, but only if your web service is local to your ASP.NET webapp. That's unlikely to occur, really, because web services are made for remote calls, not local calls. I don't think it's your case.
If this is a local web service, as djechelon suggests, They will share session state you are all set. Use djechelon's answer, ignore mine :)
If not: ask the larger question: what is stoping someone from calling your web service outside the context of your web app: using a tool like soapUI?
1) lock down your service (using WCF Security).
http://msdn.microsoft.com/en-us/library/ms731925.aspx
2) create a local webservice that checks authentication/authorization, and calls the webservice: passing the authorization information.
This is one approach that values the operation the WS performs over redundant Webservice calls. It is your disgression if a WS that calls another fits your performance needs.
You can Enable Session in WebMethod like this:
[WebMethod(EnableSession = true)]
public string DoSomthing(string para)
{
user = new SystemUser();
if (!user.Authenticate())
{//401 Unauthenicated}
}
Authenticate Method:
public bool Authenticate()
{
try
{
if (HttpContext.Current.Session["UName"] == null || HttpContext.Current.Session["Role"] == null)
{
return false;
}
else
{
this.Id = HttpContext.Current.Session["UName"].ToString();
this.Role = (Core.Role)HttpContext.Current.Session["Role"];
return true;
}
}
catch (Exception ex)
{
throw new Exception("Authenticate",ex);
}
}

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.

Resources