Asp.net MVC Without SessionState
When writing my first real MVC application, I instinctively turned off SessionState in the web.config.
<sessionState mode="Off" />
When I started the application I received this error:
The SessionStateTempDataProvider requires SessionState to be enabled.
I crawled into it further and MVC by default requires SessionState for one type of ActionResult. There is the concept of TempData in MVC where you can load some data, perform a redirect, and the temp data will be there on the next request. Using TempData across web requests is a solution for keeping data across the stateless nature of the web.
The application I’m writing will be hosted in a Farm. I know there are solutions for using session state across the farm, primarily through SqlStateServer or setting sticky sessions on the load balancer machines. However, even sticky sessions won’t work for me because I like the ability to take a server out of rotation and it not affect my users.
The workaround is simply to create your own ITempDataProvider and attach it to your controller. The ITempDataProvider has two methods: LoadTempData and SaveTempData. Here is my implementation of ITempDataProvider I use now.
public class NoTempDataProvider : ITempDataProvider
{
public IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
{
return new Dictionary<string, object>();
}
public void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
if ( values.Count != 0 )
throw new NotImplementedException("Can not set tempdata, no session state available");
}
}
The Load method just returns an empty collection. The Save method won’t do anything either. However, you’ll notice the save method checks to make sure the framework doesn't try to persist any state. If so, it will blow up, letting your developers know this isn’t supported.
Of course you can just create your own base Controller that you can use
in your application; this sample is using the MVC Sample Application,
AccountController. Now you have to wire this new provider to the controller, line 5:
1: public AccountController(IFormsAuthentication formsAuth, IMembershipService service)
2: {
3: FormsAuth = formsAuth ?? new FormsAuthenticationService();
4: MembershipService = service ?? new AccountMembershipService();
5: this.TempDataProvider = new NoTempDataProvider();
6: }
If you decide you need some sort of TempData storage you can just process the data in the Load/Save methods and use your own custom data storage. I’m hoping to not need this as I move forward in this application.