Remote Validation for List of Models

Remote Validation for LIST of MODELs

You have not posted your code for the model or controller, but assuming you have a RemoteAttribute applied to property Username, for example

public class MyModel
{
[Remote("IsValidUserName", "Person")]
public string Username { get; set; }
}

with a method in PersonController

public JsonResult IsValidUserName(string Username)
{
....
}

and the view

@model List<Person>
...
@for (var i = 0; i < Model.Count; i++)
{
@Html.EditorFor(m => m[i].Username)
}

This will generate html such as

<input name="[0].UserName" ... />
<input name="[1].UserName" ... />

Unfortunately the remote method in jquery-validate posts back the name and value of the element so that the ajax call looks like

$.ajax({
url: '/Person/IsValidUserName',
data: { [0].UserName: 'someone@somewhere.com' },
...

which will not bind.

I have reported this as an issue at Codeplex with a possible solution. In the meantime you can modify the remote method in jquery-validate.js file as follows

remote: function(value, element, param) {
....
var data = {};
// data[element.name] = value;
data[element.name.substr(element.name.lastIndexOf(".") + 1)] = value; // add this

This will strip the prefix so that the posted data is

 data: { UserName: 'someone@somewhere.com' },

and will correctly bind to the method.

ASP.NET MVC Binding with Remote Validation

I found a solution without inheritance (and without view models) that solves my binding problem with just little change to my code.

There's two ways of binding for remote validation, you can either just pass the member that has to be remote checked

public ActionResult isValid(string toBeRemoteChecked) { ... }

or you can pass the instance of the class of that member.

public ActionResult isValid(ModelA modelA) { ... }

Inside the second variant, of course, you have to replace toBeRemoteChecked with modelA.toBeRemoteChecked. On this second version the binding works in both cases - when editing and also when creating my instance of ModelA in the context above. In order to make the binding work, it's crucial that the parameter name of the remote validation method matches the member name in the CreateModelA, i.e. modelA in my case.

In case you have a very complex model, you can just initialize the parameter modelA with the members you want to use by using bind/include, i.e. in my case I'd use

public ActionResult isValid([Bind(Include = "toBeRemoteChecked")] ModelA modelA) { ... }

By default (without Include), all other members will remain null or have a default value - so you need to use Include only if you need other members for validation as well - in my case, I would have the same when omitting the Include)

Remote ViewModel validation of nested objects not working

The issue with the validation of the PasswordConfigurmation property against the User.Password property is caused by a bug in in the 'jquery.validate.unobtrusive.js' file.

Originally, the jquery 'equalTo' function is:

adapters.add("equalto", ["other"], function (options) {
var prefix = getModelPrefix(options.element.name),
other = options.params.other,
fullOtherName = appendModelPrefix(other, prefix),
element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];

setValidationValues(options, "equalTo", element);
});

You just need to modify this line:

element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];

to:

element = $(options.form).find(":input[name='" + fullOtherName + "']")[0];

Note the addition on the single quotes around the 'fullOtherName' selector. Once you've made this change, the client side validation works as expected.

Asp.net MVC: Additional fields are not binding for Remote validation

I have taken idea from this post and fixed it by modifying the remote method in jquery-validate.js file as below:

remote: function(value, element, param) {
....
param = typeof param === "string" && {url:param} || param;
....

for (var property in param.data) {
if (param.data.hasOwnProperty(property)) {
param.data[property.substr(property.lastIndexOf(".") + 1)] = param.data[property];
}
}
//ajax call


Related Topics



Leave a reply



Submit