当参数名称需要不同时,如何重用远程验证方法?

Gla*_*zed 5 asp.net-mvc asp.net-mvc-3 remote-validation

我有两个类,我用作两个不同视图的模型.您可以看到第二个类包含第一个类的实例.第一个包含远程验证属性.

[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; }
}
Run Code Online (Sandbox Code Playgroud)

当这些验证在浏览器中触发时,将根据视图使用的类生成两个不同的请求.您可以看到查询字符串参数名称不同:

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

http://localhost:55327/EmailRecipient/ValidateEmailRecipientNameUniqueness?EmailRecipient.Name=sdhsdgh
Run Code Online (Sandbox Code Playgroud)

以下是我的操作方法的当前版本,它不适用于第二个URL:

public JsonResult ValidateEmailRecipientNameUniqueness( string name )
{
    var isValid = !_emailRecipientRepo.NameExists( name );

    return Json( isValid, JsonRequestBehavior.AllowGet );
}
Run Code Online (Sandbox Code Playgroud)

使用第二个URL时,name参数将为null.我已经读过我应该能够为该参数添加一个Bind属性并添加一个前缀,但这也不起作用.我甚至尝试设置前缀EmailRecipient.,以防它需要点.为了以防万一,我还在名字中用大写N试了一下.不行.添加它也会破坏其他URL!

public JsonResult ValidateEmailRecipientNameUniqueness( [Bind( Prefix = "EmailRecipient")] string name )
Run Code Online (Sandbox Code Playgroud)

可能的解决方案

我能有方法采取EmailRecipientViewModel的一个实例,并为它创建一个IModelBinder中,我可以寻找任何命名约定,并将其分配给实例.这看起来比应该做的更多.

我可以使用重载@Html.EditorFor()并告诉它使用"名称"为htmlFieldName,也使用@Html.ValidationMessage( "Name" )而不是ValidationMessageFor.唯一的缺点是潜在的命名冲突,但这并不是什么大不了的事.我只需要为所使用的类的所有实例使用唯一的名称.更新:实际上,如果我这样做,因为我更改了名称,因此在发布表单时会出现问题.那不好.

...

我只是想通了我可以让方法不带参数,并手动访问查询字符串.这是一个非常简单的解决方案,但我没有得到好的参数.

string name = Request.QueryString[ "Name" ] ?? Request.QueryString[ "EmailRecipient.Name" ];
Run Code Online (Sandbox Code Playgroud)

这很容易,我可能只是想用它.但是,既然我已经打开了这个问题,我会问,是否有更优雅的解决方案?

Joe*_*ano 1

如果不滚动您自己的验证或模型绑定器,就没有真正干净的方法来做到这一点。将其视为模型绑定,模型绑定器需要知道传入内容的名称,对于远程验证也是如此。您可以采取的一种方法是在控制器中创建两个单独的远程验证方法,最终调用实际执行所有验证工作的一个方法。