I\'ve been playing with the new MVC3 Json Model Binding and it\'s quite nice.
Currently, I can post JSON to controller and bind it. Model Validation occurs nicely too.
Thanks for this solution. I improved on it a bit by passing a dictionary so that you can use the unobtrusive javascript to put the validation on the individual fields instead of a summary by referencing the key of the dictionary.
private Dictionary<string, string> GetModelStateErrorsAsString(ModelStateDictionary state)
{
Dictionary<string, string> errors = new Dictionary<string, string>();
foreach (var key in ModelState.Keys)
{
var error = ModelState[key].Errors.FirstOrDefault();
if (error != null)
{
errors.Add(key, error.ErrorMessage);
}
}
return errors;
}
@Junto and @Jamey777, you both pass the ModelState to your error function but then you use the global variable instead of the parameter.
and why dont you just use a little linq like
private Dictionary<string, string> GetModelStateErrorsAsString()
{
return ModelState.Where(x=> x.Value.Errors.Any())
.ToDictionary(x => x.Key, x => x.Value.Errors.First().ErrorMessage);
}
The following example works for me when using unobtrusive JavaScript in MVC3. I'm doing something very similar. Given the following JsonResponse
class:
public enum Status
{
Ok,
Error
}
public class JsonResponse
{
public Status Status { get; set; }
public string Message { get; set; }
public List<string> Errors { get; set; }
}
My controller can have a method thus:
[HttpPost]
public ActionResult Login(UserLoginModel model)
{
JsonResponse res = new JsonResponse();
if (!ModelState.IsValid)
{
res.Status = Status.Error;
res.Errors = GetModelStateErrorsAsString(this.ModelState);
res.Message = "Oh dear, what have you done. Check the list of errors dude!";
}
else
{
// Save it here...
// Return success
res.Status = Status.Ok;
res.Message = "Everything was hunky dory";
}
return Json(res);
}
And the ModelStateDictionary can be enumerated for the errors as so:
private List<string> GetModelStateErrorsAsString(ModelStateDictionary state)
{
List<string> errors = new List<string>();
foreach (var key in ModelState.Keys)
{
var error = ModelState[key].Errors.FirstOrDefault();
if (error != null)
{
errors.Add(error.ErrorMessage);
}
}
return errors;
}
Then in my view I can have the following JSON POST:
<script type="text/javascript">
$("form").submit(function (evt) {
// validate
$('form').valid();
// extract values to submit
var form = $(this),
username = form.find("[name=Username]").val(),
password = form.find("[name=Password]").val(),
json = JSON.stringify({
Username: username,
Password: password
});
$.ajax({
url: form.attr("action"),
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: json,
success: function (result) {
alert(result.Message);
}
});
// stop form submitting
evt.preventDefault();
});
</script>
I'm using jQuery.tmpl
to display the errors. I have excluded that from this example though.