简体   繁体   中英

@Html.ValidationSummary works on wrong page

Using asp.net core razor. My current if statement is wrong, but it is the only way to get the error messages to show up. The current if statement is if the ModelState is not valid return to view. On the new view it shows the error messages. However, what I want is if the ModleState is not valid redirect to the Index.cshtml page and show the errors their. When I flipped around my if condition the error messages do not show up in the Index.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(Home model)
        {
            if(!ModelState.IsValid)
            {
                return View();
            }
        //continue your code to save
        return RedirectToAction("Index");
        }    
    }
}

Here is my Index.cshtml

@model quotingDojo.Models.Home
<h1>Welcome to the Quoting Dojo</h1>
@using(Html.BeginForm("Quotes","Home"))
{
    <p>@Html.ValidationSummary()</p>
    <p>
        <label>Your Name</label>
        @Html.TextBoxFor(s=>s.Name)
        @Html.ValidationMessageFor(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>

Here is my Quotes.cshtml where the error messages currently show up.

<h1>Test</h1>
 <p>@Html.ValidationSummary()</p>

Here is my models page using System.ComponentModel.DataAnnotations;

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

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

Your issue is here:

return View();

That will return a view named "Quotes" since your action method is named Quotes (this is MVC convention). You also do not pass a model to it so even if the view existed, it will not know of the errors.

Two ways to fix your issue:

1.

You have to pass the model to your Index view so you need to explicitly return the Index view.

if(!ModelState.IsValid)
{
    return View("Index", model);
}

2.

I personally prefer this method. Name your first action which serves the original form the same as the one your are posting to and then you can do this (note: you will also need to rename the view):

// GET: /Home/
[HttpGet]
[Route( "" )]
public IActionResult Quotes() {
   return View();
}

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

This way both of them return the view named Quotes so you do not have to explicitly mention it.

The standard practice is, If model state is not valid, you return the same view (which user submitted) where you will show the validation error messages. You just need to change your Quotes action method to Index action method.

[HttpPost]
[Route("quotes")]
public IActionResult Index(Home model)
{
   if (!ModelState.IsValid)
        return View(); 
   // to do :continue saving
}

Make sure to update your form to post to this action.

Not sure why you want to redirect to another page where you want to show the errros.

If you absolutely want to show the error messages in another view which was loaded via RedirectToAction method call (hence a totally new GET call), You need to use TempData to transfer the errors.

 public ActionResult Quotes(Home model)
 {
     if (!ModelState.IsValid)
     {
        List<string> errors = new List<string>();
        foreach (var modelStateVal in ViewData.ModelState.Values)
        {
            foreach (var error in modelStateVal.Errors)
            {
                errors.Add(error.ErrorMessage);
            }
        }
        TempData["errors"] = errors;
        return RedirectToAction("Index");
      }
        //continue your code to save

 }

And in your index view,

@if (TempData["errors"] != null)
{
    var errors = (List<string>) TempData["errors"];
    foreach (var error in errors)
    {
      <span class="alert warning">@error</span>
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM