How to get all Errors from ASP.Net MVC modelState?
foreach (ModelState modelState in ViewData.ModelState.Values) {
foreach (ModelError error in modelState.Errors) {
DoSomethingWith(error);
}
}
See also How do I get the collection of Model State Errors in ASP.NET MVC?.
How do I get the collection of Model State Errors in ASP.NET MVC?
<% ViewData.ModelState.IsValid %>
or
<% ViewData.ModelState.Values.Any(x => x.Errors.Count >= 1) %>
and for a specific property...
<% ViewData.ModelState["Property"].Errors %> // Note this returns a collection
How do you get errors in the ModelState, for a particular property?
Assuming you want the error(s) for proeprty Name
string propertyName = "Name";
To get the first error (which is what will be displayed when using @Html.ValidationSummary()
, you can use
string error = ViewData.ModelState.Keys.Where(k => k == propertyName)
.Select(k => ModelState[k].Errors[0].ErrorMessage).First();
or to get all errors for a property
IEnumerable<string> errors = ModelState.Keys.Where(k => k == propertyName)
.Select(k => ModelState[k].Errors).First().Select(e => e.ErrorMessage);
and use your foreach
as noted in the question
Display Model state Errors in View?
You can Access ModelState class in view with the key :
Controller : ModelState.AddModelError("ProductSRDate", "Date must be current date or in the past.");
View : @Html.ValidationMessage("ProductSRDate")
But you're code logical error because you add an error to your ModelState
if IsValid
.
if (!ModelState.IsValid || updatedProduct.ProductSRDate.Value > DateTime.Now)
{
if (updatedProduct.ProductSRDate.Value > DateTime.Now)
{
ModelState.AddModelError("ProductSRDate", " Date must be current date or in the past.");
}
//return BadRequest(ModelState.Values.SelectMany(v => v.Errors).Select(error => error.ErrorMessage));
return View(editMode); // You should return a view and handle Invalid ModelState in view.
}
else
{
var PrjEditMode = await ProductService.GetProductsbyId(id);
var editMode = Mapper.Map<ProductDetails>(PrjEditMode);
return View(editMode);
}
How to check if ModelState contains errors which are not properties
Ok i think i have working solution
@if (ViewData.ModelState.Keys.Contains(string.Empty))
{
@Html.ValidationSummary(true)
}
Get all ModelState Errors on view
You can access it through ViewData.ModelState
.
If you need more control with errors on your view you can use
ViewData.ModelState.IsValidField("name_of_input")
or get a list of inputs with errors like this:
var errors = ViewData.ModelState.Where(n => n.Value.Errors.Count > 0).ToList();
how to get ALL errors from viewdata.modelstate
I found out why this wasn't working for me. As usual it was me being silly. Because the model has multiple layers / levels to it, I.e. model.someobject.someotherobject.someproperty, when I called tryValidateModel it would validate the top level but not the inner layers.
The solution to this was to ensure they are all called:
TryValidateModel(mp);
TryValidateModel(mp.ContactInformation.PrimarySiteAddress);
TryValidateModel(mp.ContactInformation.RegisteredOfficeAddress);
So my solution is to either create a method to call try validate on each object level or create a refelctive method to do it for me.
Get error message if ModelState.IsValid fails?
You can do this in your view without doing anything special in your action by using Html.ValidationSummary() to show all error messages, or Html.ValidationMessageFor() to show a message for a specific property of the model.
If you still need to see the errors from within your action or controller, see the ModelState.Errors property
Is there a way to clear modelstate errors on the client?
It makes no sense to attempt to attempt to clear ModelState
errors from the client. ModelState
is only set within the controller method (by the DefaultModelBinder
) when you make a request to the method. In any case, your issues are not related to ModelState
being valid or invalid in the controller method.
There are a number of changes you need to make to your code:
You should delete your EditorTemplate
for decimal?
It means that any property of that type is going to use that template. Instead replace your
@Html.EditorFor(m => Model.Options[i].Value, ...)
with
@(Html.Kendo().CurrencyTextBoxFor(m => m.Options[i].Value)....
in the main view.
If you really do want to use a template, then make it a named template (which is called using @Html.EditorFor(m => Model.Options[i].Value, "yourTemplateName")
, but in any case, you need to remove the code relating to attemptedValue
and modelStateForValue
(including the if
block) - the EditorFor()
methods will always correctly use values from ModelState
if they exist.
Next, your RequiredIfAttribute
does not implement IClientValidatable
so you will not get client side validation. You could use the foolproof library, or if you want to write your own, refer this answer for the full implementation of a RequiredIfAttribute
, including the scripts for client side validation.
Next, you need to delete the IValidatableObject
implementation (the Validate()
method) from your model. That is just repeating the validation that the [RequiredIf]
attribute is doing, and you should avoid mixing ValidationAttribute
's with IValidatableObject
(refer The Complete Guide To Validation In ASP.NET MVC 3 - Part 2 for more detailed information).
Finally, the Kendo().CurrencyTextBoxFor()
method hides the input and renders its own html. By default, hidden inputs are not validated, so you need to reconfigure the validator. In the main view, add the following script (after the jquery-{version}.js
, jquery.validate.js
and jquery.validate.unobtrusive.js
scripts
<script>
$.validator.setDefaults({
ignore: []
});
.... // other scripts as required
<script>
How to figure out which key of ModelState has error
You can check the ViewData.ModelState.Values
collection and see what are the Errors.
[Httpost]
public ActionResult Create(User model)
{
if(ModelState.IsValid)
{
//Save and redirect
}
else
{
foreach (var modelStateVal in ViewData.ModelState.Values)
{
foreach (var error in modelStateVal.Errors)
{
var errorMessage = error.ErrorMessage;
var exception = error.Exception;
// You may log the errors if you want
}
}
}
return View(model);
}
}
If you really want the Keys(the property name), You can iterate through the ModelState.Keys
foreach (var modelStateKey in ViewData.ModelState.Keys)
{
var modelStateVal = ViewData.ModelState[modelStateKey];
foreach (var error in modelStateVal.Errors)
{
var key = modelStateKey;
var errorMessage = error.ErrorMessage;
var exception = error.Exception;
// You may log the errors if you want
}
}
Related Topics
How to Change the Opacity (Alpha, Transparency) of an Element in a Canvas Element
Image Scaling Causes Poor Quality in Firefox/Internet Explorer But Not Chrome
How to Apply a Color to a Svg Text Element
How to Nest Button Inside Another Button
Denoting a Preferred Place for a Line Break
What Are the CSS Properties That Get Elements Out of the Normal Flow
How to Convert Input Value to Uppercase in Angular 2 (Value Passing to Ngcontrol)
Html5 Email Input Pattern Attribute
Do I Need a "/" at the End of an <Img> or <Br> Tag, etc.
How to Vertically Center a <Span> Inside a Div
How to Rename HTML "Browse" Button of an Input Type=File
Equal Sized Table Cells to Fill the Entire Width of the Containing Table
CSS Object-Fit: Contain; Is Keeping Original Image Width in Layout
Css: How to Set Image Size Relative to Parent Height
CSS - Relative Positioned Parent Div Not Stretching to Absolute Child Div Height