开发者

Remote Validation seems buggy

开发者 https://www.devze.com 2023-03-01 03:28 出处:网络
imagine this situation: SetUp in the default MVC3 project, create a new complex type in the AccountModels.cs

imagine this situation:

SetUp

in the default MVC3 project, create a new complex type in the AccountModels.cs

public class GlobalAccount
{
    public GlobalAccount()
    {
        this.LogOn = new LogOnModel();
        this.Register = new RegisterModel();
    }

    public LogOnModel LogOn { get; set; }
    public RegisterModel Register { get; set; }
}

In the RegisterModel change the UserName to:

[Required]
[Remote("UserNameExists", "Validation", "", ErrorMessage = "Username is already taken.")]
[RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed.")]
[Display(Name = "Username (spaces will be stripped, must be at least 6 characters long)")]
public string UserName { get; set; }

The UserNameExists method in a Validation controller is as follow:

public class ValidationController : Controller
{
    public JsonResult UserNameExists(string UserName)
    {
        string user = null;
        if (!String.IsNullOrWhiteSpace(UserName) && UserName.Length >= 6)
            user = UserName == "abcdef" ? "ok" : null;

        return user == null ?
            Json(true, JsonRequestBehavior.AllowGet) :
            Json(string.Format("{0} is not available.", UserName), JsonRequestBehavior.AllowGet);
    }
}

Now in the Register View, use the GlobalAccount Model instead of the RegisterModel

the username input box will be like:

@model Your.NameSpace.Models.GlobalAccount

and

 <div class="field fade-label">
    @Html.LabelFor(model => model.Register.UserName, new { @class = "text" })
    @Html.TextBoxFor(m开发者_C百科odel => model.Register.UserName, new { spellcheck = "false", size = "30" })
</div>

this will result in something like this, in the HTML

<div class="field fade-label">
    <label class="text" for="Register_UserName"><span>Username (spaces will be stripped, must be at least 6 characters long)</span></label>
    <input data-val="true" data-val-regex="White space is not allowed." data-val-regex-pattern="(\S)+" data-val-remote="Username is already taken." data-val-remote-additionalfields="*.UserName" data-val-remote-url="/beta/Validation/UserNameExists" data-val-required="The Username (spaces will be stripped, must be at least 6 characters long) field is required." id="Register_UserName" name="Register.UserName" size="30" spellcheck="false" type="text" value="">
</div>

Debug

If you use FireBug to check what's going on ... the Remote Validation is sending the attribute name instead of the attribute id to the Validation method (the UserNameExists one) as:

Register.UserName instead of Register_UserName

So I can't fetch this value ... ever :(

Is this really a bug or is something that someone already found and I couldn't get from Googling it?

Here is a simple image of the actual problem:

Remote Validation seems buggy


How about:

public ActionResult UserNameExists(
    [Bind(Include = "UserName")]RegisterModel register
)
{
    string user = null;
    if (!String.IsNullOrWhiteSpace(register.UserName) && register.UserName.Length >= 6)
        user = register.UserName == "abcdef" ? "ok" : null;

    return user == null ?
        Json(true, JsonRequestBehavior.AllowGet) :
        Json(string.Format("{0} is not available.", register.UserName), JsonRequestBehavior.AllowGet);
}

Another possibility is to define a special view model:

public class UserNameExistsViewModel
{
    public string UserName { get; set; }
}

and then:

public ActionResult UserNameExists(UserNameExistsViewModel register)
{
    string user = null;
    if (!String.IsNullOrWhiteSpace(register.UserName) && register.UserName.Length >= 6)
        user = register.UserName == "abcdef" ? "ok" : null;

    return user == null ?
        Json(true, JsonRequestBehavior.AllowGet) :
        Json(string.Format("{0} is not available.", register.UserName), JsonRequestBehavior.AllowGet);
}

What is annoying is that the following doesn't work:

public ActionResult UserNameExists(
    [Bind(Prefix = "Register")]string UserName
)

Go figure :-) I would probably go with a custom view model. It looks cleanest.


I know this is marked as answered, but as I'm having the same issue I thought I would contribute another variation that is working for me.

The class in my case is "Food" and the field I'm attempting to remote validate is "Name". The textbox is being created by an EditorFor control:

@Html.EditorFor(model => model.Name)

Remote validation is set on the Food class field:

[Remote("FoodNameExists")]
public string Name { get; set; }

And this calls a method:

public ActionResult FoodNameExists(string Name) {

As per the original question, rather than this being passed to the FoodNameExists method as "Name", or even "Food_Name", which is the Id value created by the EditorFor helper, it is getting passed as the name attribute which is "Food.Name"... which of course is not something I can set as an input parameter.

So, my hack is simply to ignore the input parameters and look in the QueryString:

var name = Request.QueryString["Food.Name"];

...this returns the correct value, which I validate against and I'm off to the races.


This is the simpliest way I found to do it, just adding data-val-- attributes in HtmlAttributes of DropDownListFor, inside the view. The following method works with RemoteValidation too, if you do not need remote validation, simply remove the elements containing data-val-remote-*:

        @Html.DropDownListFor(m => m.yourlistID, (IEnumerable<SelectListItem>)ViewBag.YourListID, String.Empty, 
        new Dictionary<string, object>() { { "data-val", "true" }, 
        { "data-val-remote-url", "/Validation/yourremoteval" }, 
        { "data-val-remote-type", "POST" }, { "data-val-remote-additionalfield", "youradditionalfieldtovalidate" } })

I hope it may help. Best Regards!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号