Introduction
The SessionState Attribute helps us to control the session state behavior in ASP.NET MVC. We can disable the session state / read-only / required for the controller using this attribute. This is a class-level attribute, so we can only apply this attribute at the controller level. Some of the action methods of a controller might have a different behavior than the controller session state behavior. In this case, the following solution is very useful. So, we can apply a session state behavior per action in ASP.NET MVC.
Problem Statement
We can control session state behavior using the SessionState attribute, but this can only be applied at the controller level. This means that all action method controllers have the same session state behavior. Now, if some of the action methods of the controller do not use a session and some of the action methods do use the session, then what is the solution?
Solution
In this scenario, we can create a different controller and move all the action methods that have the same session state behavior in the same controller class. This is not a good solution. Instead of doing this, we can create a custom action attribute that overwrites the behavior of the session state for the specific action method.
Use the following procedure to create a custom action attribute that overrides the behavior of the session state.
Step 1. Create a custom attribute.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class ActionSessionStateAttribute : Attribute
{
public SessionStateBehavior Behavior { get; private set; }
public ActionSessionStateAttribute(SessionStateBehavior behavior)
{
this.Behavior = behavior;
}
}
Step 2. Create a custom controller factory.
public class CustomControllerFactory : DefaultControllerFactory
{
protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
return SessionStateBehavior.Default;
}
var actionName = requestContext.RouteData.Values["action"].ToString();
MethodInfo actionMethodInfo;
actionMethodInfo = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (actionMethodInfo != null)
{
var actionSessionStateAttr = actionMethodInfo.GetCustomAttributes(typeof(ActionSessionStateAttribute), false)
.OfType<ActionSessionStateAttribute>()
.FirstOrDefault();
if (actionSessionStateAttr != null)
{
return actionSessionStateAttr.Behavior;
}
}
return base.GetControllerSessionBehavior(requestContext, controllerType);
}
}
Step 3. Register custom controller factory in Global. asax.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));
}
Step 4. Attribute usage.
[SessionState(System.Web.SessionState.SessionStateBehavior.Disabled)]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
TempData["test"] = "session less controller test";
return View();
}
[ActionSessionState(System.Web.SessionState.SessionStateBehavior.Required)]
public ActionResult About()
{
Session["test"] = "session less controller test";
return View();
}
}
The following is the output when the “Index” action method is called.
The following is the output when the “About” is called.
Conclusion
We can use the ActionSessionStateAttribute in combination with the controller-level attribute SessionStateAttribute. In this case, use the ActionSessionStateAttribute to overwrite the controller attribute on the actions to which it applies.