Aaron
Aaron

Reputation: 4480

Display errors from ModelState.Values

I am using ASP.net core razor engine. I am trying to display my error in my html. Not sure how to go about fixing my code. How do I display the errors from ModelState.Values in my cshtml page?

Here is my controller

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using quotingDojo.Models;

namespace quotingDojo.Controllers
{
    public class HomeController : Controller
    {
        // GET: /Home/
        [HttpGet]
        [Route("")]
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        [Route("quotes")]
        public IActionResult Quotes(string Name, string Quote)
        {
            Home NewHome = new Home
            {
                Name = Name,
                Quote = Quote
            };

            if(TryValidateModel(NewHome) == false) {
                ViewBag.errors = ModelState.Values;
                System.Console.WriteLine("??????????????"); 
                System.Console.WriteLine(ModelState.ErrorCount);         
                System.Console.WriteLine("??????????????"); 
            }

            return RedirectToAction("Index");
        }
    }
}

ModelState.ErrorCount prints out the correct number of errors.

Here is my model

using System.ComponentModel.DataAnnotations;


namespace quotingDojo.Models
{
    public class Home
    {
        [Required(ErrorMessage ="Please enter your name")]
        [Display(Name="*username")]
        [DataType(DataType.Text)]
        [MinLength(3)]
        public string Name {get; set;}

        [Required]
        [MinLength(5)]
        public string Quote{get; set;}
    }
}

Here is my cshtml page

<div id="wrapper">  
    <h1>Welcome to the Quoting Dojo</h1>
    <form action="quotes" method="post">
        <p>
            <label>Your Name</label>
            <input type="text" name="Name"/>
        </p>
        <p>
            <label>Your Quote</label>
            <textarea name="Quote" id="quote" cols="30" rows="10"></textarea>
        </p>
        <input type="submit" name="submit" value="Add my quote!"/>
        <form action="quotes" method="get">
            <input type="submit" name="submit" value="Skip to quotes!"/>
        </form>
    </form>

 </div>

<div>
    <p> Test</p>
    @{
        if(ViewBag.errors != null)
        {
            foreach(var error in ViewBag.errors)
            {
                //If there are any errors for a field...
                if(@error.errors.Count > 0)
                {
                    // We show the first error for that field
                    <p>@error.errors[0].ErrorMessage</p>
                }
            }
        }

    }
</div>

I am using Visual Studio Code so anything build into regular Visual Studio I do not have access build in.

Upvotes: 3

Views: 16276

Answers (2)

Mohammed Mohammed
Mohammed Mohammed

Reputation: 43

Explicit Model Validation – This is the traditional way to validate the model data by using IF..Else..IF statement. In this way, you need to check your model property values one by one for your desired result. If model property values are unexpected, inject error messages within ModelState. see example below

public class HomeController : Controller
{
 [HttpPost]
  public ActionResult ExplicitServer(UserViewModel model)
     {
   //Write custom logic to validate UserViewModel
   if (string.IsNullOrEmpty(model.UserName))
   {
     ModelState.AddModelError("UserName", "Please enter your
  name");
 }
  if (!string.IsNullOrEmpty(model.UserName))
  {
    Regex emailRegex = new Regex(".+@.+\\..+");
     if (!emailRegex.IsMatch(model.UserName))

       ModelState.AddModelError("UserName", "Please enter correct
        email address");
   }

   if (ModelState.IsValid) //Check model state
  {
      //TO DO:
   }
  }
  }

Upvotes: 1

Shyju
Shyju

Reputation: 218702

There is no need to pass errors explicitly by using ViewBag. The model state dictionary will have the errors when model validation fails. All you have to do is to execute your code when the model validation passes.

Also, since you already have a class, you can use that as the parameter of your http post action method. The default model binder will be able to map the form values to the properties of this class's object.

[HttpPost]
[Route("quotes")]
public IActionResult Quotes(Home model)
{
  if(!ModelState.IsValid)
  {
    return View(model);
  }
  //continue your code to save
  return RedirectToAction("Index");
}

And in the view you may use the validation helper methods to display the validation errors

@Html.ValidationSummary(false)

Also , i noticed you have nested forms in the view. Nested forms are not valid markup. So i suggest you fix that as well.

<h1>Welcome to the Quoting Dojo</h1>
@using(Html.BeginForm("Quote","Home"))
{
    <p>@Html.ValidationSummary(false)</p>
    <p>
        <label>Your Name</label>
        @Html.TextBoxFor(s=>s.Name)
    </p>
    <p>
        <label>Your Quote</label>
        @Html.TextAreaFor(d=>d.Quote)
    </p>
    <input type="submit" name="submit" value="Add my quote!"/>

}
<form action="quotes" method="get">
    <input type="submit" name="submit" value="Skip to quotes!"/>
</form>

Upvotes: 8

Related Questions