【问题标题】:ASP.NET display ModelState.AddModelErrorASP.NET 显示 ModelState.AddModelError
【发布时间】:2016-04-04 13:59:50
【问题描述】:

我这里有这个方法,它是一种登录方法,如果用户名和密码不正确,则会添加一个 ModelError。

 [HttpPost]
        public ActionResult Login(LoginClass model, string ReturnUrl)
        {

            if (ModelState.IsValid)
            {
                if (Membership.ValidateUser(model.UserName, model.Password))
                {
                    FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                    if (Url.IsLocalUrl(ReturnUrl) && ReturnUrl.Length > 1 && ReturnUrl.StartsWith("/")
                        && !ReturnUrl.StartsWith("//") && !ReturnUrl.StartsWith("/\\"))
                    {
                       return Redirect(ReturnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "The user name or password provided is incorrect");
                }
            }

            return RedirectToAction("Index", "Home");
        }

我的问题是如何将 ModelError 显示到我的 View Index.cshtml 中?

【问题讨论】:

  • 我在下面更新了我的答案。我认为您正在寻找的只是将您的最后一个 return RedirectToAction 替换为 return View(model); 如果我错了,我的其余答案也将起作用。

标签: asp.net


【解决方案1】:

...如何将 ModelError 显示到我的 View Index.cshtml 中?

显示错误信息

根据您在Login 操作底部对return RedirectToAction("Index", "Home"); 的调用,我最初假设您希望重定向到主页(HomeController 操作Index)。现在我在想,这可能是您的流程中的一个错误,您实际上是在尝试向用户显示错误消息而不进行重定向,并且您只想在一切成功时进行重定向。 如果是这种情况,那么只需阅读本部分并跳过有关如何在 RedirectToAction 调用中保持模型状态的其余部分。如果出现故障,您只需拨打View 而不是RedirectToAction

[HttpPost]
public ActionResult Login(LoginClass model, string ReturnUrl)
{
    if (ModelState.IsValid)
    {
        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(ReturnUrl) && ReturnUrl.Length > 1 && ReturnUrl.StartsWith("/")
                && !ReturnUrl.StartsWith("//") && !ReturnUrl.StartsWith("/\\"))
            {
                return Redirect(ReturnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect");
        }
    }

    return View(model); // goes back to the login view with the existing model and validation error
    // return RedirectToAction("Index", "Home");
}

Login.cshtml 在某处包含以下内容

@Html.ValidationSummary()

使用 RedirectToAction

它不起作用的原因是当您执行RedirectToAction 时,包含验证消息的ViewData 丢失了。解决方案有多种选择。

  1. RedirectToAction 中保留ViewData,然后恢复它。
  2. 只保留ModelState,然后在RedirectToAction 中指定的新操作执行后将其与ModelState 合并。

保留视图数据

在大多数情况下,这可以正常工作,但如果您重定向到操作(在这种情况下,HomeController 上的索引)有它自己依赖的 ViewData,则可能会导致问题。 p>

LoginController.cs

// simplified code to just show the relevant parts to reproduce the problem/solution
[HttpPost]
public ActionResult Login(LoginClass model, string ReturnUrl)
{
    // ... some other code
    ModelState.AddModelError("", "The user name or password provided is incorrect");
    // ... some other code

    if (!ModelState.IsValid)
        TempData["ViewData"] = ViewData;

    return RedirectToAction("Index", "Home");
}

HomeController.cs

public ActionResult Index()
{
    if (TempData["ViewData"] != null)
    {
        // restore the ViewData
        ViewData = (ViewDataDictionary)TempData["ViewData"];
    }

    return View();
}

Home\Index.cshtml

@Html.ValidationSummary()

合并模型状态

这将是我推荐的方法,因为您在自定义 ActionFilter 属性上定义了希望这种情况发生一次的方式,然后应用到您希望发生的位置。您也可以将此代码直接放入您的控制器中,但是一旦您需要在多个控制器上执行此操作,这将违反 DRY 原则。

如果TempData 尚未包含"ModelState" 键,则此处的方法是将模型状态写入TempData。如果已经存在密钥,则意味着当前请求刚刚写入它,我们可以从中读取并将其与我们现有的模型状态合并。这将防止代码无意中覆盖 ViewState 或 ModelState,因为 ModelState 现在已合并。 只有当有多个RedirectToActions 都选择写入 ModelState 时,我才能看到这会出错,但我认为这不太可能发生。

ModelStateMergeFilterAttribute.cs

public class ModelStateMergeFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        // write to the temp data if there is modelstate BUT there is no tempdata key
        // this will allow it to be merged later on redirect
        if (filterContext.Controller.TempData["ModelState"] == null && filterContext.Controller.ViewData.ModelState != null)
        {
            filterContext.Controller.TempData["ModelState"] = filterContext.Controller.ViewData.ModelState;
        }
        // if there is tempdata (from the previous action) AND its not the same instance as the current model state THEN merge it with the current model
        else if (filterContext.Controller.TempData["ModelState"] != null && !filterContext.Controller.ViewData.ModelState.Equals(filterContext.Controller.TempData["ModelState"]))
        {
            filterContext.Controller.ViewData.ModelState.Merge((ModelStateDictionary)filterContext.Controller.TempData["ModelState"]);
        }
        base.OnActionExecuted(filterContext);
    }
}

LoginController.cs

// simplified the code to just show the relevant parts
[HttpPost]
[ModelStateMergeFilter]
public ActionResult Login(LoginClass model, string ReturnUrl)
{
    ModelState.AddModelError("", "The user name or password provided is incorrect");
    return RedirectToAction("Index", "Home");
}

HomeController.cs

[ModelStateMergeFilter]
public ActionResult Index()
{
    return View();
}

Home\Index.cshtml

@Html.ValidationSummary()

参考文献

这里有一些参考资料也详细说明了其中一些方法。我还依赖这些先前答案中的一些输入来回答上面的问题。

【讨论】:

    【解决方案2】:

    如果您使用的是 MVC,则可以使用验证摘要。

    @Html.ValidationSummary();
    

    https://msdn.microsoft.com/en-CA/library/dd5c6s6h%28v=vs.71%29.aspx

    另外,将你的模型传回你的视图:

    return RedirectToAction("Index", "Home", model);
    

    【讨论】:

    • 这不起作用...我尝试了ModelState.AddModelError("CustomError", "The user name or password provided is incorrect");,然后在我看来@Html.ValidationMessage("CustomError")
    • @user979331 您没有将模型传递回您的视图。见编辑
    • 即使我这样做了,仍然一无所获。没有错误显示
    • 您的 Index 操作方法是什么样的?
    • public ActionResult Index() { return View(); }
    猜你喜欢
    • 2013-03-08
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 2015-12-30
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    相关资源
    最近更新 更多