3

I'm using the MVC Validation nuget package called MVC Foolproof Validation.

I'm using it on my model to set a required to true if another model property was empty. The validation part works, as the ModelState is correctly set to invalid when the Id field and Location field are left empty. Inspecting the errors on the ModelState array I can see its working.

My problem is that the client side validation summary does not display. Here is how I've set things up. Can anyone spot my problem?

    [DisplayName("Image Id")]
    public string Id{ get; set; }

    [DisplayName("Location Id")]
    [RequiredIfEmpty("Id", ErrorMessage = "You must..etc"]
    public string LocationId{ get; set; }

In my view I'm setting up the validation summary and inputs as follows

<div class="form-horizontal">
    <hr/>
    @Html.ValidationSummary(true, "", new {@class = "text-danger"})

    <div class="form-group">
        @Html.LabelFor(model => model.SearchCriteria.Id, htmlAttributes: new {@class = "control-label col-md-2"})
        <div class="col-md-10">
            @Html.EditorFor(model => model.SearchCriteria.Id, new {htmlAttributes = new {@class = "form-control"}})
            @Html.ValidationMessageFor(model => model.SearchCriteria.Id, "", new {@class = "text-danger"})
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.SearchCriteria.LocationId, htmlAttributes: new {@class = "control-label col-md-2"})
        <div class="col-md-10">
            @Html.EditorFor(model => model.SearchCriteria.LocationId, new {htmlAttributes = new {@class = "form-control"}})
            @Html.ValidationMessageFor(model => model.SearchCriteria.LocationId,"", new {@class = "text-danger"})
        </div>
    </div>

In my controller action I'm checking the Model state. Do I need to call ModelState.AddModelError(..). I've tried that but perhaps there is a way I need to call it.

    [HttpPost]
    public ActionResult Search(SearchCriteria searchCriteria)
    {
        var searchViewModel = new SearchViewModel
        {
            SearchCriteria = searchCriteria
        };

        if (ModelState.IsValid)
        {
            ...
        }
        //ModelState.AddModelError("LocationId", "test");
        return View(searchViewModel);
    }
user48408
  • 3,234
  • 11
  • 39
  • 59
  • `@Html.ValidationSummary(true, ..)` means it excludes property level errors. But you already have `@Html.ValidationMessageFor(model => model.SearchCriteria.LocationId, ...)` which will display the error mesage at that location if `Id` is `null` and you do not provide a value for `LocationId`. And if you have set this up correctly, the error message will be dsplayed and you form will not even be able to be submitted if its invalid so the fact you hitting the controller method suggest other problems –  Aug 15 '17 at 01:10
  • And the fact that the parameter in the method is `SearchCriteria` when the model in your view does not appear to be `@model SearchCriteria` suggest even more problems –  Aug 15 '17 at 01:13

3 Answers3

3

Change the boolean parameter (excludePropertyErrors) in the ValidationSummary helper line to false:

@Html.ValidationSummary(false, "", new {@class = "text-danger"})

See https://msdn.microsoft.com/de-de/library/ee839464(v=vs.118).aspx

Philipp Grathwohl
  • 2,726
  • 3
  • 27
  • 38
  • That didn't make any difference. I should state that aswell as the validation summary not showing, neither is the validation error message below the control itself showing either... – user48408 Aug 14 '17 at 14:24
  • It may have something to do with inconsistent usage of your view model class. You use `model.SearchCriteria.LocationId` in your view and your controller gets a `SearchCriteria` parameter. That seems odd. Can you try and use only `SearchCriteria` in your view and controller? – Philipp Grathwohl Aug 14 '17 at 14:40
  • I don't follow. Seems standard, the view has a model with some properties on it and each on of those properties has its own validation criteria specified on the data annotations, ..I must be missing what you are saying? – user48408 Aug 14 '17 at 17:38
  • I just tried a sample project with the case you described and it worked fine. But you didn't post your whole classes and view .. maybe there is another issue in there that we are not seeing... – Philipp Grathwohl Aug 15 '17 at 07:07
  • Hi Phillip, thanks for the update. Yes you are correct the default behaviour would work,but i was making my request in an ajax request and preventing the postback (no wonder!). I'm going to update – user48408 Aug 15 '17 at 16:30
1

In my case I solved it changing from 'ModelOnly' to 'All':

From:

<div asp-validation-summary="ModelOnly" class="text-danger"></div>

To:

<div asp-validation-summary="All" class="text-danger"></div>
  • 2
    `ValidationSummary.All` displays both property and model level validations. `ValidationSummary.ModelOnly` displays only validation messages that apply to the model level. [Source](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1) – Fellipe Borges Sep 11 '20 at 21:22
0

My problem was that my call to my action was being done through ajax. I really should have specified, people who helped here would have diagnosed the problem immediately. When the modelstate was invalid i was returning a new View(searchViewModel) but I had to update that to return the errors in json.

    [HttpPost]
    public ActionResult Search(SearchCriteria searchCriteria)
    {
        if (ModelState.IsValid)
        {
            var searchResults = _searchProvider.GetData(searchCriteria);

            return Json(new
            {
                searchResults
            }, JsonRequestBehavior.AllowGet);
        }

        string errorMessages = string.Join(" <br /> ", this.ModelState.Values
            .SelectMany(v => v.Errors)
            .Select(e => e.ErrorMessage));

        return this.Json(new { HasError = true, ErrorMessages = errorMessages });
    }
user48408
  • 3,234
  • 11
  • 39
  • 59