MVC3 - 回发后保留“returnUrl”

本文关键字:returnUrl 保留 MVC3 | 更新日期: 2023-09-27 18:31:41

我正在为我的网站编写登录功能。当用户请求受 my [CustomAuthorize] 属性限制的视图时,用户会被正确地重定向到追加了查询字符串 (?ReturnUrl=%2fRestricted%2fView) 的/Login/Index视图。

但问题是...

当用户尝试登录时,出现验证错误。发布请求会导致回发 (duh),并且追加的查询字符串将从 URL 中消失。

  • 如何在回发后保留查询字符串?

自定义授权.cs:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext.User.Identity.IsAuthenticated)
            {
                var customIdentity = (CustomIdentity)httpContext.User.Identity;
                var customPrincipal = new CustomPrincipal(customIdentity);
                if (customIdentity.IsAdmin)
                {
                    httpContext.User = customPrincipal;
                    Thread.CurrentPrincipal = customPrincipal;
                }
            }
            return base.AuthorizeCore(httpContext);
        }
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            var urlRequested = filterContext.HttpContext.Request.Path;
            //urlRequested contains "/Restricted/View"
            //Do something with 'urlRequested' here, or?
            base.HandleUnauthorizedRequest(filterContext);
        }
}

登录/索引视图:

<body>
        @using (Html.BeginForm("Index", "Login"))
        {
            <div>
                @Html.LabelFor(model => model.UserName)
            </div>
            <div>
                @Html.EditorFor(model => model.UserName)
                @Html.ValidationMessageFor(model => model.UserName)
            </div>
            <div>
                @Html.LabelFor(model => model.Password)
            </div>
            <div>
                @Html.EditorFor(model => model.Password)
                @Html.ValidationMessageFor(model => model.Password)
            </div>
            <div>
                @Html.LabelFor(model => model.RememberMe)
            </div>
            <div>
                @Html.EditorFor(model => model.RememberMe)
                @Html.ValidationMessageFor(model => model.RememberMe)
            </div>
            <p>
                <input type="submit" value="Login!" />
            </p>
            @Html.ValidationSummary(true)
        }
</body>

登录/索引控制器操作:

[HttpPost]
public ActionResult Index(LoginModelBinding login, string returnUrl)
{
            if (ModelState.IsValid)
            {
                if (Service.CheckUser(login.UserName, login.Password))
                {
                    String loginError;
                    CustomAuthorization.Login(login.UserName, login.Password, out loginError);
                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("/''"))
                    {
                        return Redirect(returnUrl);
                    }
                    return RedirectToAction("Index", "MitTeam");
                }
                ModelState.AddModelError("", "The entered user name or password is incorrect");
            }
            return View(login);
}

溶液:根据 Naveen 的回答,我像这样修改了代码:

public static void SaveReturnUrl(this Controller controller, string returnUrl, bool showAfterRedirect = true)
{
            if (showAfterRedirect)
            {
                controller.TempData["returnUrl"] = returnUrl;
            }
            else
            {
                controller.ViewData["returnUrl"] = returnUrl;
            }
}
public static string RetrieveReturnUrl(this Controller controller)
{
            var message = controller.ViewData.ContainsKey("returnUrl") ? controller.ViewData["returnUrl"] : controller.TempData.ContainsKey("returnUrl") ? controller.TempData["returnUrl"] : null;
            return message as string;
}

使用这两种扩展方法,我可以在我的登录控制器方法/操作中保存和检索返回网址。

登录发布方法:

var previousReturnUrl = this.RetrieveReturnUrl();
if(!ModelState.IsValid)
{
    if(string.IsNullOrEmpty(previousReturnUrl))
    {
        this.SaveReturnUrl(returnUrl);
    }
    return View(login);
}

如果 modelstate 有效,我只需调用 this.RetrieveReturnUrl 并对其进行解码,这样我就可以在成功登录时重定向用户。

MVC3 - 回发后保留“returnUrl”

您可以使用 Martijn Boland 开发的代码模块 - 让您的用户了解情况。它可用于存储任何对象并在重定向后将其取回。它专门用于在重定向后操作后显示操作的消息或状态。这也适用于 AJAX 类型的请求。

在进行重定向后,您可以使用相同的方式将返回 URL 与消息一起存储(以防身份验证失败)。

您可以将视图中的返回URL存储在隐藏字段中。只要您在 ist 回发到服务器的形式中包含该隐藏字段,您的 POST-Action 就可以根据操作的结果访问和使用它(登录成功 ->重定向到 url,登录不成功 ->再次返回带有隐藏字段的登录视图)。