MVC3增加了使用[SessionState(SessionStateBehavior.Disabled)]
属性制作无会话控制器的好机会。这很好但不灵活,因为你不能为每个控制器方法设置会话状态,也不能按条件启用它。
是否可以仅为经过身份验证的用户启用会话状态,还是通过其他自定义条件启用会话状态?
即PHP有一个很棒的功能。
if (!isset($_SESSION)) session_start();
找到类似的东西会很高兴
答案 0 :(得分:4)
您可以覆盖默认控制器工厂,更具体地说是GetControllerSessionBehavior方法:
public class MyControllerFactory : DefaultControllerFactory
{
protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
return SessionStateBehavior.Default;
}
if (requestContext.HttpContext.User.Identity.IsAuthenticated)
{
// enable session if there's an authenticated user
return SessionStateBehavior.Required;
}
return SessionStateBehavior.Disabled;
}
}
并在Application_Start
中使用自定义控制器工厂替换默认控制器工厂:
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
答案 1 :(得分:2)
如何禁用每个控制器方法的会话状态。 它甚至适用于这种流程:
启用会话的请求方法 - 保留值(我不明白为什么,但确实如此)
/// <summary>
/// Enable session if there's an authenticated user or method in controller is marked with <see cref="SessionAttribute" /> or controller class is marked within <see cref="SessionAttribute" /> or <see cref="SessionStateAttribute" />
/// </summary>
public class AuthSessionControllerFactory : DefaultControllerFactory
{
protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
{
if ( controllerType == null ) return SessionStateBehavior.Default;
return requestContext.HttpContext.User.Identity.IsAuthenticated
? SessionStateBehavior.Required
: GetDefaultSessionBehavior( requestContext, controllerType );
}
private static readonly ConcurrentDictionary<string, SessionStateBehavior> _sessionStateCache = new ConcurrentDictionary<string, SessionStateBehavior>();
protected SessionStateBehavior GetDefaultSessionBehavior(RequestContext requestContext, Type controllerType)
{
if ( !requestContext.RouteData.Values.Keys.Contains( "action" ) ) return SessionStateBehavior.Required;
var act = requestContext.RouteData.Values["action"].ToString();
return _sessionStateCache.GetOrAdd( controllerType + act,
(type => {
var typeCopy = controllerType;
//get current action
var methods = typeCopy.GetMethods().Where( m => m.Name == act ).ToArray();
foreach (var method in methods) {
//look for SessionAttribute on the method
var attr = Attribute.GetCustomAttribute( method, typeof( SessionAttribute ), false );
if ( attr != null ) return (( SessionAttribute )attr).Behavior;
//support default SessionState behavior
var controllerattr = typeCopy.GetCustomAttributes( typeof( SessionStateAttribute ), true )
.OfType<SessionStateAttribute>().FirstOrDefault();
if ( controllerattr == null )
{
var controllerattrCustom = typeCopy.GetCustomAttributes( typeof( SessionAttribute ), true )
.OfType<SessionAttribute>().FirstOrDefault();
if ( controllerattrCustom != null ) return controllerattrCustom.Behavior;
} else
return controllerattr.Behavior;
}
return SessionStateBehavior.Disabled;
}) );
}
}
在Global.asax
中的Application_Start()
方法中注册
ControllerBuilder.Current.SetControllerFactory( new AuthUserSessionControllerFactory() );
这是一个SessionAttribute类 - 它看起来像来自MS的SessionStateAttribute - 唯一的区别是这个方法允许使用方法
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true )]
public sealed class SessionAttribute : Attribute
{
public SessionAttribute(SessionStateBehavior behavior)
{
Behavior = behavior;
}
public SessionStateBehavior Behavior { get; private set; }
}