ASP.NET显示ModelState.AddModelError

时间:2016-04-04 13:59:51

标签: asp.net

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

<?php
$conn=mysqli_connect("localhost", "root", "", "winkcage");
if(isset($_POST["cmessage"])){
$messages=$_POST["cmessage"];
$sender=$_SESSION["unamsession"];
$receiver="vinaykumar";
$timedate=date("Y-m-d h:i:sa");
$time=date_default_timezone_set("Asia/Calcutta");
$sendquery="INSERT INTO messages(sender, receiver, message, time) VALUES('$sender', '$receiver', '$messages', '$time')";
$sendqueryrun=mysqli_query($conn, $sendquery);
}
?>

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

2 个答案:

答案 0 :(得分:1)

... how would I display the ModelError to my View Index.cshtml?

Showing Error message

I initially made the assumption that you wanted to redirect to the home page (HomeController action Index) based on your call to return RedirectToAction("Index", "Home"); at the bottom of the Login action. Now I am thinking maybe this is a mistake in your flow and you are actually trying to show the error message to the user without redirecting and that you only want to redirect if everything succeeds. IF this is the case then just read this part and skip the rest about how to persist model state across RedirectToAction calls. All you need to do is call View instead of RedirectToAction if there is a failure.

[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 include the following somewhere

@Html.ValidationSummary()

Working with RedirectToAction

The reason it is not working is the ViewData, which includes the validation messages, is lost when you execute the RedirectToAction. There are a couple of options for a solution.

  1. Keep either persist the ViewData across the RedirectToAction and then restore it.
  2. Only persist the ModelState and then merge it with the ModelState once the new action specified in the RedirectToAction has executed.

Persist ViewData

In most scenarios this works just fine but could cause problems if your redirected to action (in this case Index on the HomeController) has its own ViewData that it depends on.

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()

Merge the ModelState

This is would be my recommended approach because you define how you want this to happen once on a custom ActionFilter attribute and then apply where you want it to occur. You could also put this code directly into your controller but that would violate the DRY principle as soon as you need to do this on multiple controllers.

The approach here is to write the model state to the TempData if the TempData does not already contain a "ModelState" key. If there is already a key present that means that the current request has just written to it and we can read from it and merge that with our existing model state. This will prevent the code from unintentionally overwriting the ViewState or the ModelState as the ModelState is now merged. I can only see this going wrong if there are multiple RedirectToActions that all choose to write to the ModelState but I do not think this is a likely scenario.

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()

References

Here are some references that also detail some of these approaches. I also relied on some of the input from these previous answers for my answer above.

答案 1 :(得分:0)

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

@Html.ValidationSummary();

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

此外,将模型传递回您的视图:

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