Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net MVC 3 JSON Model Binding and server side model validation mixed with client side validation

Tags:

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.

But what happens if the model is invalid?

I'd like to return JSON and have the client side notify the user (like how you'd perform normal client side validation in mvc)

Does anyone know of some tutorials on how to perform this?

Is this even possible?

Or are there frameworks I can leverage to do this?

like image 917
sf. Avatar asked Jan 14 '11 12:01

sf.


People also ask

What is client side and server side validation in MVC?

Client side validation Vs server side validation The user input validation take place on the Server Side during a post back session is called Server Side Validation and the user input validation take place on the Client Side (web browser) is called Client Side Validation.

What is client side validation in ASP.NET MVC?

ASP.NET MVC client side validation is based on the jQuery validation plugin. It can be said that MVC's client-side validation is an opinionated version of how jQuery validation should work in an ASP.NET MVC project. Despite this, the underlying implementation is fully based on jQuery's.

How does ValidationMessageFor work in MVC?

ASP.NET MVC: ValidationMessageFor The Html. ValidationMessageFor() is a strongly typed extension method. It displays a validation message if an error exists for the specified field in the ModelStateDictionary object. Visit MSDN to know all the overloads of ValidationMessageFor() method.

What is ModelState IsValid in MVC?

ModelState. IsValid indicates if it was possible to bind the incoming values from the request to the model correctly and whether any explicitly specified validation rules were broken during the model binding process. In your example, the model that is being bound is of class type Encaissement .


2 Answers

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.

like image 93
Rebecca Avatar answered Sep 22 '22 15:09

Rebecca


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;
    }
like image 25
Jamey777 Avatar answered Sep 20 '22 15:09

Jamey777