IRouteConstraint MVC4上的HttpContextBase.Session和HttpContext.Current.Session都为null

时间:2013-09-14 12:50:14

标签: c# asp.net-mvc session asp.net-mvc-4

我无法在我的自定义RootConstraint类上访问Session,它被设置为null。我搜索过但无法找到解决方案。

public class AdminRootConstraint : IRouteConstraint
{
    public bool Match
        (
            HttpContextBase httpContext,
            Route route,
            string parameterName,
            RouteValueDictionary values,
            RouteDirection routeDirection
        )
    {
        if ((string) values["controller"] == "Login")
            return true;

        return HttpContext.Current.Session != null && (bool)HttpContext.Current.Session["IsAuthorized"];
    }
}

修改

以下是httpContext参数在即时窗口中的外观。可以提出一个想法。

httpContext
{System.Web.HttpContextWrapper}
    [System.Web.HttpContextWrapper]: {System.Web.HttpContextWrapper}
    AllErrors: null
    AllowAsyncDuringSyncStages: false
    Application: {System.Web.HttpApplicationStateWrapper}
    ApplicationInstance: {ASP.global_asax}
    AsyncPreloadMode: None
    Cache: {System.Web.Caching.Cache}
    CurrentHandler: null
    CurrentNotification: ResolveRequestCache
    Error: null
    Handler: null
    IsCustomErrorEnabled: false
    IsDebuggingEnabled: true
    IsPostNotification: true
    IsWebSocketRequest: false
    IsWebSocketRequestUpgrading: false
    Items: Count = 0x00000000
    PageInstrumentation: {System.Web.Instrumentation.PageInstrumentationService}
    PreviousHandler: null
    Profile: null
    Request: {System.Web.HttpRequestWrapper}
    Response: {System.Web.HttpResponseWrapper}
    Server: {System.Web.HttpServerUtilityWrapper}
    Session: null
    SkipAuthorization: false
    ThreadAbortOnTimeout: true
    Timestamp: {14.09.2013 16:52:53}
    Trace: {System.Web.TraceContext}
    User: {System.Security.Principal.WindowsPrincipal}
    WebSocketNegotiatedProtocol: null
    WebSocketRequestedProtocols: null

修改2

我在同一区域的动作中使用RedirectToAction方法,Match方法在跟踪时执行两次。在第一次执行中,routeDirection参数设置为System.Web.Routing.RouteDirection.UrlGeneration,而Session的时间不为空。但是当第二次执行出现时,routeDirection参数设置为System.Web.Routing.RouteDirection.IncomingRequest,会话为空。为什么呢?

2 个答案:

答案 0 :(得分:2)

首次调用Match是因为MVC正在构建URL,它将导航用户的浏览器(通过发送HTTP 302)。这次你只是因为它存在于那一刻而意外地进行了会议。

第二次调用Match是当请求到达浏览器时。此会话不存在,因为在加载会话之前执行路由逻辑。例如。路由可能会呈现根本不需要会话的页面。

总而言之,在IRouteConstraint中无法访问会话,因此不应使用。

答案 1 :(得分:0)

通常您应该有权访问会话。但是在ASP.NET MVC应用程序中避免使用HttpContext.Current静态属性。请改用提供给您的HttpContextBase抽象:

public class AdminRootConstraint : IRouteConstraint
{
    public bool Match
    (
        HttpContextBase httpContext,
        Route route,
        string parameterName,
        RouteValueDictionary values,
        RouteDirection routeDirection
    )
    {
        if ((string) values["controller"] == "Login")
        {
            return true;
        }

        object isAuthorized = httpContext.Session["IsAuthorized"];
        return (isAuthorized != null && (bool)isAuthorized);
    }
}

在此示例中,httpContext.Session不会为null。如果您从未在会话中为此键设置值,那么httpContext.Session["IsAuthorized"]可能是正常的。