在 ASP.NET MVC 应用程序中设置会话持续时间在 web.config 中不起作用

Setting session duration in ASP.NET MVC application doesn't work in web.config

定义问题

我发现在 ASP.NET MVC 应用程序中有两种设置会话持续时间的方法:

  1. 正在为 web.config 文件的 <sessionState> 字段中的 timeout 属性设置值。
  2. Global.asax.cs 文件的 Session_Start() 方法中设置 Session.Timeout 属性。

web.config 文件如下实现时,第一种方法不起作用,如 the document 中所述,我得到 HTTP 404 错误:

<configuration>
    <system.web>
        <sessionState mode="InProc" cookieless="true" timeout="60" />
    </system.web>
</configuration>

但是,第二种方法在 Global.asax.cs 文件中实现时有效,如下所示:

public class ApplicationName : System.Web.HttpApplication
{
    protected void Session_Start(object sender, EventArgs e)
    {
        /* Sets the session duration to 60 minutes. */
        Session.Timeout = 60;
    }
}

错误代码通知

当我使用第一种方法时,在 /Login/Index 页面上单击 “登录” 按钮时出现 HTTP 404 错误。因为虽然输入了正确的用户名和密码,但是页面被重定向到/{token}/Login/LoginControl页面,而页面应该被重定向到/Profile页面。我不知道这种行为是如何发生的。

相关源代码

LoginController.cs文件中的相关方法和Login/Index.cshtml文件中定义的脚本如下:

public class LoginController : PublicController
{
    private readonly IUserService _userService;
    private readonly IUnitOfWork _uow;
    private SessionContext _sessionContext;

    public LoginController(IUnitOfWork uow, IUserService userService) : base(uow)
    {
        _uow = uow;
        _userService = userService;
        _sessionContext = new SessionContext();
    }

    [HttpPost]
    public ActionResult LoginControl(ELoginDTO login)
    {
        var result = _userService.GetUserByUserName(login.UserName, login.Password);

        if (result != null)
        {
            AutoMapper.Mapper.DynamicMap(result, _sessionContext);
            Session["SessionContext"] = _sessionContext;

            return Json("/Profile", JsonRequestBehavior.AllowGet);
        }
        else
        {
            return Json("", JsonRequestBehavior.AllowGet);
        }
    }
}

单击 “登录” 按钮会触发 FUNCTION_LoginControl() 脚本:

function FUNCTION_LoginControl()
{
    var model = { UserName: $("#inputUserName").val(), Password: $("#inputPassword").val() };

    if (model.UserName.trim() != "" && model.Password.trim() != "") 
    {
        $.ajax({
            url: "/Login/LoginControl",
            type: "POST",
            data: model,
            success: function (e) {
                if (e != "") 
                {
                    window.location = e;
                }
            }
        });
    }
}

我发现当ASP.NET框架的<sessionState>字段中的cookieless属性设置为true时,一个唯一的ID被添加到 URL。因此,我意识到当我点击 "LOGIN" 按钮时,我得到了一个错误,因为 post 去了 /{unique-id}/Login/LoginController 而它应该去了 /Login/LoginController.

解决这个问题的方法是将Web.config文件中sessionState中的cookieless字段设置为false:

<!-- HttpPost request if "false" is added to the "cookieless" attribute -->
<!-- HttpPost Request: "/Login/LoginController"                         -->
<sessionState mode="InProc" cookieless="false" timeout="60" />

<!-- HttpPost request if "true" is added to the "cookieless" attribute  -->
<!-- HttpPost Request: "/{unique-id}/Login/LoginController"             -->
<sessionState mode="InProc" cookieless="true" timeout="60" />