I have this function in my controller.
[HttpPost]
public ActionResult Edit(EmployeesViewModel viewModel)
{
Employee employee = GetEmployee(viewModel.EmployeeId);
TryUpdateModel(employee);
if (ModelState.IsValid)
{
SaveEmployee(employee);
TempData["message"] = "Employee has been saved.";
return RedirectToAction("Details", new { id = employee.EmployeeID });
}
return View(viewModel); // validation error, so redisplay same view
}
It keeps failing, ModelState.IsValid
keeps returning false and redisplaying the view. But I have no idea what the error is.
Is there a way to get the error and redisplay it to the user?
This question is related to
c#
asp.net
asp.net-mvc
Try
ModelState.Values.First().Errors[0].ErrorMessage
I have no idea if this is your problem, but if you add a user and then change the name of your application, that user will remain in the database (of course), but will be invalid (which is correct behavior). However, there will be no error added for this type of failure. The error list is empty, but ModelState.IsValid will return false for the login.
If you're looking to generate a single error message string that contains the ModelState
error messages you can use SelectMany
to flatten the errors into a single list:
if (!ModelState.IsValid)
{
var message = string.Join(" | ", ModelState.Values
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage));
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
}
publicIHttpActionResultPost(Productproduct) {
if (ModelState.IsValid) {
//Dosomethingwiththeproduct(notshown).
returnOk();
} else {
returnBadRequest();
}
}
OR
public HttpResponseMessage Post(Product product)
{
if (ModelState.IsValid)
{
// Do something with the product (not shown).
return new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
If Modal State is not Valid & the error cannot be seen on screen because your control is in collapsed accordion, then you can return the HttpStatusCode so that the actual error message is shown if you do F12. Also you can log this error to ELMAH error log. Below is the code
if (!ModelState.IsValid)
{
var message = string.Join(" | ", ModelState.Values
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage));
//Log This exception to ELMAH:
Exception exception = new Exception(message.ToString());
Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
//Return Status Code:
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
}
But please note that this code will log all validation errors. So this should be used only when such situation arises where you cannot see the errors on screen.
Ok Check and Add to Watch:
Now you can see a list of all SubKey with its validation state at end of value.
So search for the Invalid value.
Try this
if (ModelState.IsValid)
{
//go on as normal
}
else
{
var errors = ModelState.Select(x => x.Value.Errors)
.Where(y=>y.Count>0)
.ToList();
}
errors will be a list of all the errors.
If you want to display the errors to the user, all you have to do is return the model to the view and if you haven't removed the Razor @Html.ValidationFor()
expressions, it will show up.
if (ModelState.IsValid)
{
//go on as normal
}
else
{
return View(model);
}
The view will show any validation errors next to each field and/or in the ValidationSummary if it's present.
It is sample extension
public class GetModelErrors
{
//Usage return Json to View :
//return Json(new { state = false, message = new GetModelErrors(ModelState).MessagesWithKeys() });
public class KeyMessages
{
public string Key { get; set; }
public string Message { get; set; }
}
private readonly ModelStateDictionary _entry;
public GetModelErrors(ModelStateDictionary entry)
{
_entry = entry;
}
public int Count()
{
return _entry.ErrorCount;
}
public string Exceptions(string sp = "\n")
{
return string.Join(sp, _entry.Values
.SelectMany(v => v.Errors)
.Select(e => e.Exception));
}
public string Messages(string sp = "\n")
{
string msg = string.Empty;
foreach (var item in _entry)
{
if (item.Value.ValidationState == ModelValidationState.Invalid)
{
msg += string.Join(sp, string.Join(",", item.Value.Errors.Select(i => i.ErrorMessage)));
}
}
return msg;
}
public List<KeyMessages> MessagesWithKeys(string sp = "<p> ? ")
{
List<KeyMessages> list = new List<KeyMessages>();
foreach (var item in _entry)
{
if (item.Value.ValidationState == ModelValidationState.Invalid)
{
list.Add(new KeyMessages
{
Key = item.Key,
Message = string.Join(null, item.Value.Errors.Select(i => sp + i.ErrorMessage))
});
}
}
return list;
}
}
If anyone is here for WebApi (not MVC) you just return the ModelState
object:
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
ModelState.Values.SelectMany(v => v.Errors).ToList().ForEach(x => _logger.Error($"{x.ErrorMessage}\n"));
Source: Stackoverflow.com