ASP.NET MVC: Validation messages set in TryUpdateModel not showing ValidationSummary

I tried to follow the verification instructions and examples on the Internet, for example, David Hayden Blog and the official ASP.Net MVC Tutorials , but I can not get the code below to display the actual verification errors. If I have a view that looks something like this:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.Parent>" %> <%-- ... content stuff ... --%> <%= Html.ValidationSummary("Edit was unsuccessful. Correct errors and retry.") %> <% using (Html.BeginForm()) {%> <%-- ... "Parent" editor form stuff... --%> <p> <label for="Age">Age:</label> <%= Html.TextBox("Age", Model.Age)%> <%= Html.ValidationMessage("Age", "*")%> </p> <%-- etc... --%> 

For a model class that looks like this:

 public class Parent { public String FirstName { get; set; } public String LastName { get; set; } public int Age { get; set; } public int Id { get; set; } } 

Whenever I enter an invalid age (since Age is declared as int), for example, "xxx" (not an integer), the view correctly displays the message "Edit was unsuccessful. Correct errors and try again" at the top of the screen, and also highlighting the text box " Age "and placing a red star next to it, indicating an error. However, using ValidationSummary, a list of error messages is not displayed. When I do my own check (for example: for LastName below), the message is displayed correctly, but the TryUpdateModel built-in check does not seem to display the message when the field has an illegal value.

Here is the action called in my controller code:

  [AcceptVerbs(HttpVerbs.Post)] public ActionResult EditParent(int id, FormCollection collection) { // Get an updated version of the Parent from the repository: Parent currentParent = theParentService.Read(id); // Exclude database "Id" from the update: TryUpdateModel(currentParent, null, null, new string[]{"Id"}); if (String.IsNullOrEmpty(currentParent.LastName)) ModelState.AddModelError("LastName", "Last name can't be empty."); if (!ModelState.IsValid) return View(currentParent); theParentService.Update(currentParent); return View(currentParent); } 

What did I miss?

+2
source share
1 answer

I downloaded and looked at the source code of ASP.NET MVC v1.0 from Microsoft and found that either by accident or by design, there is no way to do what I want to do, at least by default. Apparently, during an call to UpdateModel or TryUpdateModel, if an integer integrity check (for example) is not performed, ErrorMessage is not explicitly set in the ModelError associated with ModelState for a bad value, but the Exception property is set instead. According to the code from MVC ValidationExtensions, the following code is used to retrieve the error text:

 string errorText = GetUserErrorMessageOrDefault(htmlHelper.ViewContext.HttpContext, modelError, null /* modelState */); 

Notice that the null parameter passed to modelState. The GetUserErrorMEssageOrDefault method starts as follows:

 private static string GetUserErrorMessageOrDefault(HttpContextBase httpContext, ModelError error, ModelState modelState) { if (!String.IsNullOrEmpty(error.ErrorMessage)) { return error.ErrorMessage; } if (modelState == null) { return null; } // Remaining code to fetch displayed string value... } 

So, if the ModelError.ErrorMessage property is empty (I checked that when trying to set a non-integer value to the declared int) MVC continues to check the ModelState, which we already found, is null, so null is returned for any ModelError Exception. So, at the moment, my two best ideas in this area are:

  • Create a custom validation extension that correctly returns the appropriate message when ErrorMessage is not specified but an Exception is selected.
  • Create a preprocess function that is called in the controller if ModelState.IsValid returns false. The preprocessing function will look up values ​​in ModelState, where ErrorMessage is not set, but an exception is thrown, and then the corresponding message is displayed using ModelState.Value.AttemptedValue.

Any other ideas?

+2
source

Source: https://habr.com/ru/post/919683/


All Articles