开发者

How can I reuse a remote validation method when the parameter name needs to be different?

开发者 https://www.devze.com 2023-02-25 14:06 出处:网络
I have two classes I\'m using as the model of two different views. You can see that the second class contains an instance of the first. The first contains Remote validation attributes.

I have two classes I'm using as the model of two different views. You can see that the second class contains an instance of the first. The first contains Remote validation attributes.

[MetadataType( typeof( ExceptionLogModel.EmailRecipientMetadata ) )]
public class EmailRecipientViewModel
{
    public int EmailRecipientID { get; set; }

    [Remote( "ValidateEmailRecipientNameUniqueness", "EmailRecipient", ErrorMessage = "Name is not unique." )]
    public string Name { get; set; }

    [Remote( "ValidateEmailRecipientEmailUniqueness", "EmailRecipient", ErrorMessage = "Email is not unique." )]
    public string Email { get; set; }
}

public class EmailRecipientChoices
{
    public List<EmailRecipient> UnselectedEmailRecipients { get; set; }
    public List<EmailRecipient> SelectedEmailRecipients { get; set; }
    public EmailRecipientViewModel EmailRecipient { get; set; }
}

When these validations trigger in the browser, two different requests are made depending on which class the view used. You can see that the query string parameter names are different:

http://localhost:55327/EmailRecipient/ValidateEmailRecipientNameUniqueness?Name=sdhsdgh

http://localhost:55327/EmailRecipient/ValidateEmailRecipientNameUniqueness?EmailRecipient.Name=sdhsdgh

Here is the current version of my action method which does not work with the second URL:

public JsonResult ValidateEmailRecipie开发者_Go百科ntNameUniqueness( string name )
{
    var isValid = !_emailRecipientRepo.NameExists( name );

    return Json( isValid, JsonRequestBehavior.AllowGet );
}

When the second URL is used, the name parameter will be null. I've read that I should be able to add a Bind attribute to that parameter and add a prefix, but this is not working either. I even tried setting the prefix to EmailRecipient. just in case it needed the dot. I also tried it with a capital N in Name just in case. No go. Adding this also breaks it for the other URL!

public JsonResult ValidateEmailRecipientNameUniqueness( [Bind( Prefix = "EmailRecipient")] string name )

Possible solutions

I could have the method take an instance of EmailRecipientViewModel and create an IModelBinder for it in which I could look for either naming convention and assign it to the instance. This seems like more work than it should be.

I could use the overload for @Html.EditorFor() and tell it to use "Name" for htmlFieldName, and also use @Html.ValidationMessage( "Name" ) rather than ValidationMessageFor. The only downside to this is potential naming conflicts, but that's not too big of a deal. I'd just have to use a unique name for all instances of this class being used. Update: Actually, if I do this, is breaks things when I post the form because I changed the names. That's no good.

...

I just figured out that I could have the method take no parameters, and access the Query String manually. This is a pretty simple solution, but I don't get the nice parameter.

string name = Request.QueryString[ "Name" ] ?? Request.QueryString[ "EmailRecipient.Name" ];

This is easy enough that I'm probably just going to use this. However, since I already have this question typed up, I'll ask, Is there a more elegant solution?


Well, I know this is late but there is a more elegant solution:

public JsonResult ValidateEmailRecipientNameUniqueness (EmailRecipient recipient)
{
    string name = recipient.Name;
    var isValid = !_emailRecipientRepo.NameExists(name);
    return Json(isValid, JsonRequestBehavior.AllowGet);
}

In other words, use the model itself. It will correctly bind the name property and you only need this value.


There isn't really a clean way to do this without rolling your own validation or model binder. Think of it like model binding, the model binder needs to know the name of what is coming in, same for remote validation. One approach that you could take is to create two separate remote validation methods in your controller that end up calling the one method that actually does all of the validation work.

0

精彩评论

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