我这里有这个方法,这是一个登录方法,如果用户名和密码不正确,就会添加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?
答案 0 :(得分:1)
... how would I display the ModelError to my View Index.cshtml?
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()
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.
ViewData
across the RedirectToAction
and then restore it.ModelState
and then merge it with the ModelState
once the new action specified in the RedirectToAction
has executed.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()
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()
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);