ASPNET MVCの場合、次のことを行いました。
- デフォルトでは、
SessionStateBehavior.ReadOnly
オーバーライドすることですべてのコントローラーのアクションを設定しますDefaultControllerFactory
- セッション状態への書き込みが必要なコントローラーアクションで、属性にマークを付けて設定します
SessionStateBehavior.Required
カスタムControllerFactoryを作成してオーバーライドしますGetControllerSessionBehavior
。
protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
{
var DefaultSessionStateBehaviour = SessionStateBehaviour.ReadOnly;
if (controllerType == null)
return DefaultSessionStateBehaviour;
var isRequireSessionWrite =
controllerType.GetCustomAttributes<AcquireSessionLock>(inherit: true).FirstOrDefault() != null;
if (isRequireSessionWrite)
return SessionStateBehavior.Required;
var actionName = requestContext.RouteData.Values["action"].ToString();
MethodInfo actionMethodInfo;
try
{
actionMethodInfo = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
}
catch (AmbiguousMatchException)
{
var httpRequestTypeAttr = GetHttpRequestTypeAttr(requestContext.HttpContext.Request.HttpMethod);
actionMethodInfo =
controllerType.GetMethods().FirstOrDefault(
mi => mi.Name.Equals(actionName, StringComparison.CurrentCultureIgnoreCase) && mi.GetCustomAttributes(httpRequestTypeAttr, false).Length > 0);
}
if (actionMethodInfo == null)
return DefaultSessionStateBehaviour;
isRequireSessionWrite = actionMethodInfo.GetCustomAttributes<AcquireSessionLock>(inherit: false).FirstOrDefault() != null;
return isRequireSessionWrite ? SessionStateBehavior.Required : DefaultSessionStateBehaviour;
}
private static Type GetHttpRequestTypeAttr(string httpMethod)
{
switch (httpMethod)
{
case "GET":
return typeof(HttpGetAttribute);
case "POST":
return typeof(HttpPostAttribute);
case "PUT":
return typeof(HttpPutAttribute);
case "DELETE":
return typeof(HttpDeleteAttribute);
case "HEAD":
return typeof(HttpHeadAttribute);
case "PATCH":
return typeof(HttpPatchAttribute);
case "OPTIONS":
return typeof(HttpOptionsAttribute);
}
throw new NotSupportedException("unable to determine http method");
}
AcquireSessionLockAttribute
[AttributeUsage(AttributeTargets.Method)]
public sealed class AcquireSessionLock : Attribute
{ }
作成したコントローラーファクトリを global.asax.cs
ControllerBuilder.Current.SetControllerFactory(typeof(DefaultReadOnlySessionStateControllerFactory));
これで、1つのに両方read-only
とread-write
セッション状態を含めることができますController
。
public class TestController : Controller
{
[AcquireSessionLock]
public ActionResult WriteSession()
{
var timeNow = DateTimeOffset.UtcNow.ToString();
Session["key"] = timeNow;
return Json(timeNow, JsonRequestBehavior.AllowGet);
}
public ActionResult ReadSession()
{
var timeNow = Session["key"];
return Json(timeNow ?? "empty", JsonRequestBehavior.AllowGet);
}
}
注:ASPNETセッション状態は、読み取り専用モードでもAcquireSessionLock
書き込みが可能であり、いかなる形式の例外もスローしません(一貫性を保証するためにロックされません)。そのため、セッション状態の書き込みを必要とするコントローラーのアクションをマークするように注意する必要があります。