Knockout + mvc 3 + Validation

2019-01-16 18:18发布

问题:

In the controller I would like to be able to get to the client validation rules of the model. I've attached some attributes using data annotations and would like to be able to pass something back to the client via the ajax call so I can then build the jquery validate options automatically.

Normally this is done for free with the unobtrusive stuff, but I'm trying to leverage knockout binding, while still not having to replicate the validation rules on both the server and client.

Without using reflection on the model server side I'm a little unsure on how to achieve this.

回答1:

In my Mvc Controls Toolkit I developed Helpers based on the knockout library. These helpers not only help in writing the knockout code, but enhance the knockout library with Unobtrusive validation and globalization. Moreover, the binding mechanism is enhanced to include complex controls such as a DatetimePicker, and other "complex" (made by different html parts) controls.

Finally, knockout templates can be defined through Razor helpers.

See the documentation here, here, here and here. I also have some tutorials that show how to implement advanced features with my helpers:

Low BandWidth Transfers with The Client Side Templates of the Mvc Controls Toolkit

Handling Big Amounts of Data with Client-Side Templates

Handling Big Amounts of Data with Client-Side Templates 2



回答2:

Depeneding on what you exactly need to do, Breeze js can be the best solution. particularly, if you're using EF, you can replicate most of the functionality of the server EF's DbContext on the client side, including, of course, the validation, but also change tracking, .saveChanges, a simple syntax that resembles LINQ queries, caching, serializing and deserializing to allow working offline, and many other things.

The basic steps to work with Breeze js are:

  • create an EF model in the server
  • add a NuGet Package on the server to create Web API Services that expose the model to the client side. This is done with a surpringly low number of C# code. One of the things that this does is exposing the metadata: definition of objects, relations, and extra information, like data annotations validation info
  • add a js Nuget Package for the client side which will be used to replicate the EF behavior on the client side.

Of course, not all of the functionality on the server will be replicated on the client, but you can do a lot of things:

  • create new entities on the client side
  • make queries on the client side, which will be executed on the server and returned to the client
  • modify entities on the client: create, modify, delete...
  • create relations on the client side: for example create new chlid entities in a parent object
  • call saveChanges on the client side, which will transfer all the tracked changes to the server so that the backend is updated
  • of course, while you do this, you'll get automatic client validation, and also additional server validation whenever you call .saveChanges

Finally, you can extend and modify the server code to include some business logic, so that you can do much more than simply exposing the EF model to the client.



回答3:

That's quite a task. You want to be able to convert your C# code into Javascript with respective data type conversions etc. You'll be better off writing down two separate sets of validation at server and client side both. It would be a lot more easier to maintain that than to write your own conversion framework all by yourself and maintaining it



回答4:

On the model use attributes validation that you like:

 public class ModelWithValidation
 {
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }
 }

In mvc forms

@using( Html.BeginForm())
{    
     @Html.TextBoxFor(m => m.Name, new {data_bind = "value: name"})
     @Html.ValidationMessageFor(m => m.Name)
}

In jQuery test if form is valid onSubmit or in knockout save function call the next code to validate input. You must include jQuery.unobtrusive* and jQuery.validate* libraries. Don't forget to validate input on server side also!

var form = $("form");
form.removeData('validator');
form.removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse(form);

$("form").valid() //true false