216

I am checking my database in Create(FooViewModel fvm){...} to see if the fvm.prop1 and fvm.prop2 already exist in that combination; if so, I want to add an error to the modelstate, then return the whole view. I tried:

public ActionResult Create(FooViewModel fvm){
    if (ThatComboAlreadyExists(fvm)) {
      ModelState.AddModelError("Model", "There is already one like that");
      return View(fvm);
    }
}

...but I get no display of errors in the Html.ValidationSummary, which is where I assume they would appear. I have the suspicion that "Model" is not the right key, but I haven't been able to find anything a la Google.

Scott Baker
  • 10,013
  • 17
  • 56
  • 102

4 Answers4

375

I eventually stumbled upon an example of the usage I was looking for - to assign an error to the Model in general, rather than one of it's properties, as usual you call:

ModelState.AddModelError(string key, string errorMessage);

but use an empty string for the key:

ModelState.AddModelError(string.Empty, "There is something wrong with Foo.");

The error message will present itself in the <%: Html.ValidationSummary() %> as you'd expect.

Scott Baker
  • 10,013
  • 17
  • 56
  • 102
  • 35
    This case makes me think: Why there is not a method like `ModelState.AddError(errorMessage)` or `ModelState.AddGlobalError(errorMessage)`... it would be intuitive and easier to find out how to add an error message not related to any model's properties. – Rubens Mariuzzo Feb 26 '13 at 15:04
  • 3
    @Rubens : True, but you can easily add such a method with extension methods. – Johnny5 Oct 24 '13 at 19:45
  • 4
    You can also display the error using `@Html.ValidationMessage(string.Empty)` – Ben Foster Mar 10 '15 at 11:37
  • 1
    key being the property of your model bound to the view - that has the error - just to be clear. – niico Oct 19 '16 at 16:32
  • 3
    The `ValidationSummaryErrors(bool excludePropertyErrors)` overload will display all the validation errors if its argument is false or only non-property-specific (key = "") errors if its argument is true. – Suncat2000 Jan 04 '17 at 15:04
  • Thank god (you), I was searching for this for the past hour! – VPetrovic Jul 21 '19 at 20:11
28

You can add the model error on any property of your model, I suggest if there is nothing related to create a new property.

As an exemple we check if the email is already in use in DB and add the error to the Email property in the action so when I return the view, they know that there's an error and how to show it up by using

<%: Html.ValidationSummary(true)%>
<%: Html.ValidationMessageFor(model => model.Email) %>

and

ModelState.AddModelError("Email", Resources.EmailInUse);
VinnyG
  • 6,883
  • 7
  • 58
  • 76
  • 1
    This seems counterintuitive in my case - I'm checking to see if a particular combination of col1 & col2 already exists in the database, so it doesn't seem right to have the IsDuplicateOfAnotherRow property on my ViewModel. Turns out, you can add an error to your model - see my answer. – Scott Baker Apr 22 '11 at 23:06
  • 1
    Is there a way to get the string "Email" for AddModelError without using a fragile literal string? Like `(m=>m.email).SomeMagicToString()`? – Snekse May 23 '14 at 13:41
  • I don't think so, you have to go with magic string... not the best but still a good solution – VinnyG May 23 '14 at 14:53
  • 6
    The `nameof` operator coming in C# 6.0 solves this magic string problem. http://msdn.microsoft.com/en-us/magazine/dn802602.aspx – RJ Cuthbertson Nov 21 '14 at 19:22
4

Putting the model dot property in strings worked for me: ModelState.AddModelError("Item1.Month", "This is not a valid date");

Chris
  • 165
  • 1
  • 5
  • 3
    That would indeed show an invalid Month in your UI, but it doesn't solve the original problem. – Scott Baker Mar 10 '15 at 15:29
  • 3
    The original problem stems from not understanding what "key" represents in the method. This sheds some light on how "key" functions, so it's good to know that key doesn't have to be just a property name, but can also refer to nested properties or the special value String.Empty. – Triynko Oct 06 '15 at 21:08
2

Try Using Below Answer for consistent Output Format :- new ValidationProblemDetails()

if (!ModelState.IsValid) { 
ModelState.AddModelError("ErrorKey", "ErrorValue");
return BadRequest(new ValidationProblemDetails(this.ModelState));
}

Output Format:

{
    "errors": {
        "ErrorKey": [
            "ErrorValue"
        ]
    },
    "title": "One or more validation errors occurred.",
    "status": 400,
}
  • I don't think this answers the original question, but was actually the information I was looking for. – pettys May 16 '23 at 14:25