Frage

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.

War es hilfreich?

Lösung

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!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top