StructureMap IOC/DI and object creation - asp.net-mvc

I'm building small web shop with asp.net mvc and Structuremap ioc/di. My Basket class uses session object for persistence, and I want use SM to create my basket object through IBasket interface. My basket implementation need HttpSessionStateBase (session state wrapper from mvc) in constructor, which is available inside Controller/Action. How do I register my IBasket implementation for SM?
This is my basket interface:
public interface IBasketService {
BasketContent GetBasket();
void AddItem(Product productItem);
void RemoveItem(Guid guid);
}
And SM registration:
ForRequestedType(typeof (IBasketService)).TheDefaultIsConcreteType(typeof (StoreBasketService));
But my StoreBasketService implementation has constructor:
public StoreBasketService(HttpSessionStateBase sessionState)
How do I provide HttpSessionStateBase object to SM, which is available only in controller?
This is my first use of SM IOC/DI, and cann't find solution/example in official documentation and web site ;)

If you absolutely have to have your StoreBasketService use the session, I'd be tempted to define an interface and wrapper around HttpSessionState instead of using HttpSessionStateBase so that you can register it with StructureMap as well.The wrapper would get the session state from the current context. Register the wrapper with StructureMap and then have your StoreBasketService take the interface as the argument to the constructor. Structure map should then know how to create an instance of the interface wrapper and inject it into your StoreBasketService class.
Using an interface and wrapper will allow you to mock the wrapper in your unit tests, muc in the same way HttpSessionStateBase allows mocking the actual session.
public interface IHttpSessionStateWrapper
{
HttpSessionState GetSessionState();
}
public class HttpSessionStateWrapper : IHttpSessionStateWrapper
{
public virtual HttpSessionState GetSessionState()
{
return HttpContext.Current.Session;
}
}
ForRquestedType(typeof(IHttpSessionStateWrapper))
.TheDefaultIsConcreteType(typeof(IHttpSessionStateWrapper));
public class StoreBasketService
{
HttpSessionState session;
public StoreBasketService( IHttpSessionstateWrapper wrapper )
{
session = wrapper.GetSessionState();
}
// basket implementation ...
}
However, you can have StructureMap actually store your basket in the session using .CacheBy(InstanceScope.HttpContext) when registering it. It may actually be better to have your StoreBasketService implement internal storage instead of storing things in the session -- then you lose the dependency on the session state entirely (from the perspective of your class) and your solution could be simpler. Your internal storage could be a Dictionary<Guid,Product> since this is how you access them via your interface.
See also:
http://www.lostechies.com/blogs/chad_myers/archive/2008/07/15/structuremap-basic-scenario-usage.aspx
http://www.lostechies.com/blogs/chad_myers/archive/2008/07/17/structuremap-medium-level-usage-scenarios.aspx

ForRequestedType<IBasketService>()
.TheDefault.Is.OfConcreteType<StoreBasketService>()
.WithCtorArg("sessionState").EqualTo(HttpContext.Current.Session);
?? does that work?

I just started with StructureMap, and I do not get the results you are describing.
I performed a simple test using a simple class, configuring Structuremap to cacheby HttpContext, and from what I can see, CacheBy.HttpContext means within the same request you will get the same instance... not within the same Session
The constructor of my class, sets the date/time in a private field
I have a button which gets 2 instances of MyClass with one second interval...
It then display the time of both instances in a label.
Pressing the first time this button, object A and B are same instance, as their creation time is exactly the same, as expected.
Clicking the button a second time, you would expect the creation time to not have changed if instances would be cached in session... however, in my test I get a new creation time ...
Structuremap configuration:
ObjectFactory.Initialize(x=>x.ForRequestedType<MyClass>(). CacheBy(InstanceScope.HttpContext));
Button clicked event of test page
protected void btnTest_Click(object sender, EventArgs e)
{
MyClass c = ObjectFactory.GetInstance<MyClass>();
System.Threading.Thread.Sleep(1000);
MyClass b = ObjectFactory.GetInstance<MyClass>();
lblResult.Text = String.Format("cache by httpcontext First:{0} Second:{1} session id {2} ", c.GetTimeCreated(), b.GetTimeCreated(),Session.SessionID);
}
MyClass
public class MyClass
{
private DateTime _timeCreated;
public MyClass()
{
_timeCreated = DateTime.Now;
}
public string GetTimeCreated()
{
return _timeCreated.ToString("dd/MM/yyyy hh:mm:ss");
}
}

You could also use one of the ObjectFactory.Inject methods to inject the HttpSessionStateBase into StructureMap. It would then invoke the constructor with the injected HttpSessionStateBase.

I just made my first attempt at creating an custom scope... build a small web application with it, and as far as I can see, it seems to work. This will cache the object inside the current user session and will return the same object as long as you remain inside the same session:
public class HttpSessionBuilder : CacheInterceptor
{
private readonly string _prefix = Guid.NewGuid().ToString();
protected override CacheInterceptor clone()
{
return this;
}
private string getKey(string instanceKey, Type pluginType)
{
return string.Format("{0}:{1}:{2}", pluginType.AssemblyQualifiedName, instanceKey, this._prefix);
}
public static bool HasContext()
{
return (HttpContext.Current.Session != null);
}
protected override bool isCached(string instanceKey, Type pluginType)
{
return HttpContext.Current.Session[this.getKey(instanceKey, pluginType)] != null;
}
protected override object retrieveFromCache(string instanceKey, Type pluginType)
{
return HttpContext.Current.Session[this.getKey(instanceKey, pluginType)];
}
protected override void storeInCache(string instanceKey, Type pluginType, object instance)
{
HttpContext.Current.Session.Add(this.getKey(instanceKey, pluginType), instance);
}
}
You have to configure the ObjectFactory as follows in the global.asax Application_start
ObjectFactory.Initialize(x=>
x.ForRequestedType<MyClass>().InterceptConstructionWith(new HttpSessionBuilder()));

Related

AddTransient service using info from request

I've got an app in asp.net core using the built-in DI framework. I'd like to add a per-request (i.e. transient) service to the provider, but I'd like to actually make use of the request in its construction.
services.AddTransient<IMyService>(provider => { ... });
That's the closest overload I can find, but the provider object doesn't have anything about the current request. Is there a way to achieve what I'm trying to do, without upgrading to a more robust DI framework?
As posted in the comments, you can inject the IHttpContextAccessor into your services and access it, if the HttpContext is the only thing you need.
public class MyService : IMyService
{
private readonly HttpContext context;
public MyService(IHttpContextAccessor httpContextAccessor)
{
if(IHttpContextAccessor==null)
throw new ArgumentNullException(nameof(httpContextAccessor));
context = httpContextAccessor.HttpContext;
}
}
However, if you need something that's only available in the controller or outside of HttpContext, you can create a factory and pass the parameters to the factory
public class MyServiceFactory : IMyServiceFactory
{
// injecting the HttpContext for request wide service resolution
public MyServiceFactory(IHttpContextAccessor httpContextAccessor) { ... }
public IMyService Create(IDependency1 dep1, IDependency2 dep 2, string someRuntimeConfig)
{
IServiceProvider provider = this.context.RequestServices;
var myService = new MyService(provider.GetService<ISomeRepository>(), dep1, dep2, someRuntimeConfig);
return myService;
}
}
and then inject the IMyServiceFactory to your classes where you'd need IMyService.

Unit of Work pattern implementation

I am creating an application with ASP.NET MVC and Entity framework code first. I am using repository and unit of work pattern with influence of from following link.
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Here I have question about the implementation of Unit Of Work in that link unit of work is implemented via directly writing entities in class itself like.
public class UnitOfWork : IDisposable
{
private SchoolContext context = new SchoolContext();
private GenericRepository<Department> departmentRepository;
public GenericRepository<Department> DepartmentRepository
{
get
{
if (this.departmentRepository == null)
{
this.departmentRepository = new GenericRepository<Department>(context);
}
return departmentRepository;
}
}
}
Do you think that implementation is good enough because every time I add/remove entities I need to change my Unit of work class. I believe that Unit of work should not be dependent on entities. Because in my application based on Client feedback we are going to frequently add/remove entities.
I may sound stupid but let me know your views on that.
The Unit of Work pattern is already implemented in Entity Framework.
The DbContext is your Unit of Work.
Each IDbSet is a Repository.
using (var context = new SchoolContext()) // instantiate our Unit of Work
{
var department = context.Departments.Find(id);
}
There are a few flavors of the UnitOfWorkPattern. The one you are describing is a show everything, there is a hide everything approach as well. In the hide approach the unit of work references the DbContext.SaveChanges() method and nothing else; sounds like what you want.
public YourContext : DbContext, IContext{}
public interface IUnitOfWork{
void Commit();
}
public UnitOfWork : IUnitOfWork{
private readonly IContext _context;
//IOC should always inject the same instance of this, register it accordingly
public UnitOfWork(IContext context){
_context = context;
}
void Commit(){
// try catch the validation exception if you want to return the validations this
// way if your confident you've already validated you can put a void here or
// return the intfrom save changes make sure you handle the disposing properly,
// not going into that here you also may be doing other stuff here, have multiple
// "contexts" to save in a single transaction or we have contextProcessors that
// do stuff based on items in the context
_context.SaveChanges();
}
}
This leaves the issue of how you get your repositories into the classes that need them if you are not taking them from the UnitOfWork. This is best handled by an IOC framework. Again here there are a couple options. Once is to register the UnitOfWork as a single instance per request and have it injected into your custom Repository class.
public interface IRepository<T>
{
IQueryable<T> Records();
//other methods go here
}
public Repository : IRepository<T>
{
private IContext _context;
// same instance of context injected into the unit of work, this why when you Commit
// everything will save, this can get tricky if you start adding Add, Update and stuff
// but EF does have the support needed.
public Repository(IContext context)
{
_context = context;
}
public Records()
{
return _context.Set<T>();
}
}
public class SomeService : ISomeService{
private readonly _myObjectRepository;
public SomeService(IRepository<MyObject> myObjectRepository){
_myObjectRepository = myObjectRepository;
}
}
Personally I consider the IDbSet an sufficient abstraction so I no longer create repositories. In
order to inject the IDbSets from the context though you need to register them as instances that you
extract from the context in your IOC setup. This can be complex and depending on your skills you
could find yourself in the situation where you have to register each IDbSet which I know you are trying to avoid.
What's nice about using the IDbSet is you have access to simple methods like Add and can avoid some of the more complex parts of working with Entity and DbEntity in a generic sense.
public class SomeService : ISomeService {
private readonly _myObjectSet;
// requires specialized IOC configurations because you have to pull this instance from
// the instance of the context, personally don't know how to do this with a single
// registration so this has the same problem as having to add each new repository to the
// unit of work. In this case each new Entity I add to the context requires I add an IOC
// registration for the type.
public SomeService(IDbSet<MyObject> myObjectSet){
_myObjectSet= myObjectSet;
}
}
Try passing the SchoolContext to the GenericRepository:
public GenericRepository<T>
{
private SchoolContext _context;
public GenericRepository(SchoolContext context)
{
_context = context;
}
public Get(int id)
{
return _context.Set<T>().Find(id);
}
}
And use:
using(var context = new SchoolContext())
{
var departmentRepository = new GenericRepository<Department>(context);
var department = departmentRepository.Get(1);
}

how to unit test for session variable in controller in mvc

I am unit-testing my controller.
In one of my controller methods I am setting Session variables:
public void Index()
{ Session["foo"] = "bar";
return View();
}
How can I unit-test this? The problem is that the Session property is null when testing. Injecting is not possible because the Session property is readonly.
I don't want to use any third-party tool or mocking.
Simply dont use things like Session["foo"] in your controller methods. Best practice is keep action methods unaware of any context-like global objects. Everything your action method needs should be given to her in form of arguments. Note that built-in mechanism of model binding works exactly like that - you dont use Request.Form[], you let "somebody behind the scene" pass it to your action as argument.
Now for the session you can do the same - write you very simple ValueProvider which will know how to recognize arguments you want to fill from session, and you are done. In production your actions will work with session, in test you cant simply pass them any values you want as arguments.
For inspiration look at this http://www.prideparrot.com/blog/archive/2012/7/how_to_create_a_custom_session_value_provider
Injecting is not possible because the Session property is readonly.
This means you cannot use setter injection, but could you use constructor injection, ie add a constructor for your controller that is something like:
MyController(Session session)
{
m_session = session;
// then call your main constructor
}
Session getSession()
{
return m_session;
}
You can then use this separate constructor during testing.
I agree with #rouen. do not directly use Session["foo"]. But I think having ValueProvider ans might not be a practical solution, as we only store very few variables, and these values may be and most likely not ur full model.
So my approach is something similar to what Vic Smith suggests but a much more IOC (and Mock) friendly.
I would create a provider (i.e a service) to retrieve the session variables
public class SessionVariableProvider : ISessionVariableProvider
{
public object GetSessionValue(string key)
{
if (!HttpContext.Current.Session.IsNewSession
&& HttpContext.Current.Session[key] != null)
{
return HttpContext.Current.Session[key];
}
throw new ArgumentNullException(key);
}
public void SetSessionValue(string key, object value)
{
HttpContext.Current.Session[key] = value;
}
}
public interface ISessionVariableProvider
{
object GetSessionValue(string key);
void SetSessionValue(string key, object value);
}
Modify your Controller expect ISessionVariableProvider as a parameter.
public class TestController: Controller
{
protected readonly ISessionVariableProvider _sessionVariableProvider;
protected InowiaControllerBase(ISessionVariableProvider sessionVariableProvider)
{
Guard.ArgumentNotNull(sessionVariableProvider, "sessionVariableProvider");
this._sessionVariableProvider = sessionVariableProvider;
}
public ActionResult Index()
{
_sessionVariableProvider.SetSessionValue("foo", "bar");
var foo2 = (string)_sessionVariableProvider.GetSessionValue("foo2");
return View();
}
}
when testing create your own test implementation of ISessionVariableProvider and pass it to the controller.

MVC3 - How to correctly inject dependencies with MVC3 and Ninject?

I am attempting to redesign an existing application using dependency injection with Ninject in MVC3. Here is a portion of the legacy behavior I'm having difficulty with (and yes I know its bad, that's why I'm trying to refactor it):
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
MyUserSession userSession = filterContext.HttpContext.Session[SESSIONKEY_USER] as MyUserSession;
// if session empty, rebuild user information
if (userSession == null)
{
string userName = HttpContext.User.Identity.Name;
userSession = new MyUserSession();
using (ADSearcher ad = new ADSearcher(ldapPath, excludeOUString.Split(',')))
{
// get basic user information from Active Directory
ADUserInfo aduser = MyActiveDirectorySearcher.GetUserRecord(userName);
// ... set several properties queries from AD...
userSession.propertyXYZ = aduser.propXYZ
}
// if user can proxy as another indivudual, set property
using (EDMContainer db = new EDMContainer())
{
if (db.Proxies.Any(p => p.ProxyLogin == userSession.userLogin))
userSession.CanProxy == true;
}
// save new user object to session
filterContext.HttpContext.Session[SESSIONKEY_USER] = userSession;
if(userSession.canProxy)
filterContext.Result = RedirectToAction("Proxy", "Home");
return;
}
}
So currently, the controller users several objects directly: Session, ActiveDirectorySearch, EF Database. I understand it would be better to create a class that exposes a single method "GetUser" masking all the complexity but I'm struggling with how to inject the dependencies.
If I create a class SomeUserProvider, it will also need access to the Session to check for existing user information, and then ActiveDirectorySearcher and Database to rebuild the user properties if session was empty.
My confusion is over the fact that the controller itself will need access to ActiveDirectorySearcher in other action methods and then other classes will also use the same database. Do I inject an IActiveDirSearchrer into the controller's constructor and then pass it down into the ISomeUserProvider? What about IMyDatabase? Is it also injected in controller constructor and passed down?
And last but not lease, ISessionWrapper? I know session is controversial, but I need to track who the current user is and who they are proxied as during each request (GETs and POSTs). So, does that get injected as well?
If the answer is yes to each of those, is it bad to have 3+ injected contstuctor parameters?
I realize my question may be vague, so please ask for clarification where needed. I am open to any and all suggestions and recommendations. My goal is to learn how to do it correctly.
Thanks.
I'm not certain if this is exactly what you're looking for, but this should get you started down the path of refactoring your app for DI
public class YourController : Controller
{
private readonly ISessionWrapper _sessionWrapper;
private readonly IActiveDirSearcher _adSearcher;
private readonly IMyDatabase _database;
public YourController(ISessionWrapper sessionWrapper,
IActiveDirSearcher adSearcher, IMyDatabase database)
{
this._sessionWrapper = sessionWrapper;
this._adSearcher = adSearcher;
this._database = database;
}
// now all actions in this controller have a _sessionWrapper,
// _adSearcher and _database
}
Then you have to bind your injections the Ninject way. Subclass your application from NinjectHttpApplication and override OnApplicationStarted and CreateKernel
public class MvcApplication : NinjectHttpApplication
{
// ...
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<ISessionWrapper>().To<YourSessionWrapperImplementation>();
kernel.Bind<IActiveDirSearcher>().To<YourADImplementation>();
kernel.Bind<IMyDataBase>().To<YourEDMContainerIThink>();
return kernel;
}
}
The implementations of these appear to be described in your question. However, you mentioned other actions (and other classes) depend on these implementations. Good news--the bindings in CreateKernel will take care of any missing dependencies elsewhere in your app. e.g.
public class MyActiveDirImplementation : IActiveDirSearcher
{
private readonly IMyDatabase _database;
// injected automagically WOOHOO!
public MyActiveDirImplementation(IMyDatabase database)
{
this._database = database;
}
public ADUserInfo GetUserRecord(string username)
{
return _database.GetSomeUserRecord(username);
}
}
You could, of course, similarly implement your ISessionWrapper or IMyDatabase

Session variables in ASP.NET MVC

I am writing a web application that will allow a user to browse to multiple web pages within the website making certain requests. All information that the user inputs will be stored in an object that I created. The problem is that I need this object to be accessed from any part of the website and I don't really know the best way to accomplish this. I know that one solution is to use session variables but I don't know how to use them in asp .net MVC. And where would I declare a session variable? Is there any other way?
I would think you'll want to think about if things really belong in a session state. This is something I find myself doing every now and then and it's a nice strongly typed approach to the whole thing but you should be careful when putting things in the session context. Not everything should be there just because it belongs to some user.
in global.asax hook the OnSessionStart event
void OnSessionStart(...)
{
HttpContext.Current.Session.Add("__MySessionObject", new MySessionObject());
}
From anywhere in code where the HttpContext.Current property != null you can retrive that object. I do this with an extension method.
public static MySessionObject GetMySessionObject(this HttpContext current)
{
return current != null ? (MySessionObject)current.Session["__MySessionObject"] : null;
}
This way you can in code
void OnLoad(...)
{
var sessionObj = HttpContext.Current.GetMySessionObject();
// do something with 'sessionObj'
}
The answer here is correct, I however struggled to implement it in an ASP.NET MVC 3 app. I wanted to access a Session object in a controller and couldn't figure out why I kept on getting a "Instance not set to an instance of an Object error". What I noticed is that in a controller when I tried to access the session by doing the following, I kept on getting that error. This is due to the fact that this.HttpContext is part of the Controller object.
this.Session["blah"]
// or
this.HttpContext.Session["blah"]
However, what I wanted was the HttpContext that's part of the System.Web namespace because this is the one the Answer above suggests to use in Global.asax.cs. So I had to explicitly do the following:
System.Web.HttpContext.Current.Session["blah"]
this helped me, not sure if I did anything that isn't M.O. around here, but I hope it helps someone!
Because I dislike seeing "HTTPContext.Current.Session" about the place, I use a singleton pattern to access session variables, it gives you an easy to access strongly typed bag of data.
[Serializable]
public sealed class SessionSingleton
{
#region Singleton
private const string SESSION_SINGLETON_NAME = "Singleton_502E69E5-668B-E011-951F-00155DF26207";
private SessionSingleton()
{
}
public static SessionSingleton Current
{
get
{
if ( HttpContext.Current.Session[SESSION_SINGLETON_NAME] == null )
{
HttpContext.Current.Session[SESSION_SINGLETON_NAME] = new SessionSingleton();
}
return HttpContext.Current.Session[SESSION_SINGLETON_NAME] as SessionSingleton;
}
}
#endregion
public string SessionVariable { get; set; }
public string SessionVariable2 { get; set; }
// ...
then you can access your data from anywhere:
SessionSingleton.Current.SessionVariable = "Hello, World!";
Well, IMHO..
never reference a Session inside your view/master page
minimize your useage of Session. MVC provides TempData obj for this, which is basically a Session that lives for a single trip to the server.
With regards to #1, I have a strongly typed Master View which has a property to access whatever the Session object represents....in my instance the stongly typed Master View is generic which gives me some flexibility with regards to strongly typed View Pages
ViewMasterPage<AdminViewModel>
AdminViewModel
{
SomeImportantObjectThatWasInSession ImportantObject
}
AdminViewModel<TModel> : AdminViewModel where TModel : class
{
TModel Content
}
and then...
ViewPage<AdminViewModel<U>>
If you are using asp.net mvc, here is a simple way to access the session.
From a Controller:
{Controller}.ControllerContext.HttpContext.Session["{name}"]
From a View:
<%=Session["{name}"] %>
This is definitely not the best way to access your session variables, but it is a direct route. So use it with caution (preferably during rapid prototyping), and use a Wrapper/Container and OnSessionStart when it becomes appropriate.
HTH
Although I don't know about asp.net mvc, but this is what we should do in a normal .net website. It should work for asp.net mvc also.
YourSessionClass obj=Session["key"] as YourSessionClass;
if(obj==null){
obj=new YourSessionClass();
Session["key"]=obj;
}
You would put this inside a method for easy access.
HTH
There are 3 ways to do it.
You can directly access HttpContext.Current.Session
You can Mock HttpContextBase
Create a extension method for HttpContextBase
I prefer 3rd way.This link is good reference.
Get/Set HttpContext Session Methods in BaseController vs Mocking HttpContextBase to create Get/Set methods
My way of accessing sessions is to write a helper class which encapsulates the various field names and their types. I hope this example helps:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.SessionState;
namespace dmkp
{
/// <summary>
/// Encapsulates the session state
/// </summary>
public sealed class LoginInfo
{
private HttpSessionState _session;
public LoginInfo(HttpSessionState session)
{
this._session = session;
}
public string Username
{
get { return (this._session["Username"] ?? string.Empty).ToString(); }
set { this._session["Username"] = value; }
}
public string FullName
{
get { return (this._session["FullName"] ?? string.Empty).ToString(); }
set { this._session["FullName"] = value; }
}
public int ID
{
get { return Convert.ToInt32((this._session["UID"] ?? -1)); }
set { this._session["UID"] = value; }
}
public UserAccess AccessLevel
{
get { return (UserAccess)(this._session["AccessLevel"]); }
set { this._session["AccessLevel"] = value; }
}
}
}
Great answers from the guys but I would caution you against always relying on the Session. It is quick and easy to do so, and of course would work but would not be great in all cicrumstances.
For example if you run into a scenario where your hosting doesn't allow session use, or if you are on a web farm, or in the example of a shared SharePoint application.
If you wanted a different solution you could look at using an IOC Container such as Castle Windsor, creating a provider class as a wrapper and then keeping one instance of your class using the per request or session lifestyle depending on your requirements.
The IOC would ensure that the same instance is returned each time.
More complicated yes, if you need a simple solution just use the session.
Here are some implementation examples below out of interest.
Using this method you could create a provider class along the lines of:
public class CustomClassProvider : ICustomClassProvider
{
public CustomClassProvider(CustomClass customClass)
{
CustomClass = customClass;
}
public string CustomClass { get; private set; }
}
And register it something like:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ICustomClassProvider>().UsingFactoryMethod(
() => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
}
You can use ViewModelBase as base class for all models , this class will take care of pulling data from session
class ViewModelBase
{
public User CurrentUser
{
get { return System.Web.HttpContext.Current.Session["user"] as User };
set
{
System.Web.HttpContext.Current.Session["user"]=value;
}
}
}
You can write a extention method on HttpContextBase to deal with session data
T FromSession<T>(this HttpContextBase context ,string key,Action<T> getFromSource=null)
{
if(context.Session[key]!=null)
{
return (T) context.Session[key];
}
else if(getFromSource!=null)
{
var value = getFromSource();
context.Session[key]=value;
return value;
}
else
return null;
}
Use this like below in controller
User userData = HttpContext.FromSession<User>("userdata",()=> { return user object from service/db });
The second argument is optional it will be used fill session data for that key when value is not present in session.

Resources