Display error message on the view from controller

2019-03-24 05:15发布

问题:

I am new to web development and trying to learn ASP.Net MVC 5. I am looking for one record in database if the record is not found then I want to display an error message to the user. Below is my attempt:

Controller

    [HttpGet]
    public ActionResult Search()
    {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Search(ForgotPasswordMV viewModel)
    {
        if (Temp.Check(viewModel.Email))
            return RedirectToAction("VerifyToken", new { query = viewModel.Email });
        else
        {
            ViewBag.ErrorMessage = "Email not found or matched";
            return View();
        }
    }

View:

<p>@ViewBag.ErrorMessage</p>

ViewModel

public class ForgotPasswordMV
{
    [Display(Name = "Enter your email"), Required]
    public string Email { get; set; }
}

But I read somewhere that I should put one property in my view model and set the error message on that property. I am confused now, how to achieve that and how to display the error in View then? And which one is the recommended/best practice?

回答1:

But I read somewhere that I should put one property in my view model and set the error message on that property. I am confused now, how to achieve that and how to display the error in View then? And which one is the recommended/best practice?

The best practice is to alter the ModelState dictionary property of your controller like this:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Search(ForgotPasswordMV viewModel)
{
    // ... 
    else
    {
        ModelState.AddModelError("Email", "Email not found or matched");
        return View(viewModel);
    }
}

Then in your view add the line below next to your email field;

@Html.ValidationMessageFor(m => m.Email)


回答2:

But I read somewhere that I should put one property in my view model and set the error message on that property.

That's correct. You could add the error message to your view model:

public class ForgotPasswordMV
{
    [Display(Name = "Enter your email"), Required]
    public string Email { get; set; }

    public string ErrorMessage { get; set; }
}

and then set this property on your view model and pass the view model to the view:

...
else
{
    viewModel.ErrorMessage = "Email not found or matched";
    return View(viewModel);
}

and finally in your strongly typed view use the property on your model:

@model ForgotPasswordMV
...
<p>@Model.ErrorMessage</p>

So basically here we are replacing the use of ViewBag with a strongly typed view model.



回答3:

As for me accepted anwser is not the best practice. We can handle all errors in annotations.
In our ViewModel we specify ErrorMessages for our properites.

public class UserLoginViewModel
{
    [Required(ErrorMessage = "User name is required")]
    [Display(Name = "User name")]
    [StringLength(500, ErrorMessage = "User name is too short", MinimumLength = 3)]
    public string Login { get; set; }

    [Required(ErrorMessage = "Password is required")]
    [Display(Name = "Password")]
    public string Password { get; set; }
}

In our controller

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(UserLoginViewModel model)
{
    if (!this.ModelState.IsValid)
    {
        return this.View();
    }
    ...
}

And our view

@Html.ValidationMessageFor(model => model.Login)
@Html.EditorFor(model => model.Login)
@Html.ValidationMessageFor(model => model.Password)
@Html.EditorFor(model => model.Password)