Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery Validator.showErrors MVC ViewModel ModelState

Basically I'm having trouble showing modelstate errors returned from the controller (WebApi). Using MVC4,jQuery and knockout. Hopefully you can see what I am trying to achieve from the below - thanks in advance.

View:-

<div class="editor-field">
        @Html.TextBoxFor(model => model.CostCode,
                new
                {
                    placeholder = "cost/budget code",
                    data_bind = "value: CostCode"                        
                })            
    </div>
    <div>
        @Html.ValidationMessageFor(model => model.CostCode)
    </div>

knockout viewmodel doing the post/submit:-

if (validator.valid())
    {
        console.log('is valid');
        $.ajax({
            url: '/api/Booking/CompleteBooking',
            type: 'POST',
            dataType: 'json',
            data: ko.mapping.toJS(self),
            error: function (jqXHR) { 
                extractErrors(jqXHR, validator);                                      
            },
            success: function (data) {                   
                console.log(data);
            }
        });
    }

function extractErrors(jqXhr, validator)
{
    var data = $.parseJSON(jqXhr.responseText),
    errors = { };   

    $.each(data.ModelState, function (i, item) {
       errors[i] = item;
    });   

    console.log(errors);
    validator.showErrors(errors); 
}

Controller:-

 [ModelValidationFilter]
    public HttpResponseMessage CompleteBooking(AdditionalBookingInfoViewModel model)
    {
        return new HttpResponseMessage(HttpStatusCode.OK);

    }  

ActionFilterAttribute (note the modelstate being sent back)

public class ModelValidationFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            actionContext.Response = 
                actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
        }
    }
}

Rendered markup:-

enter image description here

Firebug response:-

enter image description here

Now, I know the validator will try and find an element with the name 'model.CostCode' not just 'CostCode' as it appears in the markup, but I've tried setting the Id & name to 'model.CostCode' to match but it doesn't make any difference. I think there is a problem with my extractErrors function.

If I hardcode an error message the validator works ok

validator.showErrors({
    "CostCode" : "Test test test!"
 }); 

enter image description here

By the way, is this an acceptable way of showing server side validation messages or am I barking up the wrong tree with all this? Any pointers/comments very welcome thank you.

like image 649
renz Avatar asked Jul 17 '13 09:07

renz


Video Answer


1 Answers

At a guess, as you haven't shown us the output from console.log(errors), you are producing an array of the error items, but in the working example, you just have a hashtable that is keyed on the field name.

{
    0: { 'model.CostCode': ['Please enter a valid cost code.'] }
}

vs

{
    "CostCode" : "Test test test!"
}

So your error message is an array, whereas the working example isn't. So you need to change your extractErrors method to parse the data, rather than just copying it over:

for(var key in data.ModelState)
{
    errors[key.replace('model.', '')] = data.ModelState[key][0];    
}

That's a little hacky, but it should get you on the right path!

like image 117
Paul Manzotti Avatar answered Sep 23 '22 00:09

Paul Manzotti