mvc中使用一个action对多个不同名字段做remote验证
MVC中可以在model的属性上使用Remote这个attribute来生成客户端的远程验证
[Remote("ForbiddenWord", "RemoteValidation")] public string Title { get; set; }
比如这样,当客户端触发验证事件时,会访问Remotevalidation/ForbiddenWord这个controller/action,他传递参数(文本框中填写的值)使用的参数名就是这个文本框的name属性,如果是通过Html.EditorFor生成的,自然就是这个model中的属性名。
默认的参数名是由jquery.validate生成的。
假设我们现在的action是这样的形式
public ActionResult ForbiddenWord(string title)
这样没问题,通过title参数,就可以获取到传来值,然后在action中对此值做具体验证
在model中还有另外一个属性,也需要做同样的验证,如
[Remote("ForbiddenWord", "RemoteValidation")] public string Body { get; set; }
他生成的验证地址是RemoteValidation/ForbiddenWord?Body=???这样的url形式,action中title参数是获取不到值的。
我不知道有没有什么办法用routes来解决这种问题,我是通过filter来解决的。
如果说AdditionalFields能解决同一个model的问题,那对不同model,model中属性不同名的情况AdditionalFields就不行了
既然url的参数与action的参数名对应不上,我们写action的时候就不管他了,随便起个名就OK,如
public ActionResult ForbiddenWord(string word)
同样,model中若干字段都需要做同样的验证,如
[Remote("ForbiddenWord", "RemoteValidation")] public string Title { get; set; } [Remote("ForbiddenWord", "RemoteValidation")] public string Body { get; set; } [Remote("ForbiddenWord", "RemoteValidation")] public string Intro { get; set; }
我们需要把url实际的参数,如title,body,intro的值,赋给action的参数word
在action上加一个filter,OnActionExecuting中做这部分工作
[RemoteValidationActionParamFix("word", "body", "title", "intro")] public ActionResult ForbiddenWord(string word)
filter的参数:第一个为action要fix的参数名,后面为连接可能使用的具体名称
以下是filter的全部代码
1: public class RemoteValidationActionParamFixAttribute : ActionFilterAttribute
2: {
3: string paramName;
4: string[] toFix;
5:
6: public RemoteValidationActionParamFixAttribute(string paramname, params string[] tofix)
7: {
8: paramName = paramname;
9: toFix = tofix;
10: }
11:
12: public override void OnActionExecuting(ActionExecutingContext filterContext)
13: {
14: if (toFix == null || toFix.Length < 1)
15: {
16: return;
17: }
18: foreach (string str in toFix)
19: {
20: try
21: {
22: filterContext.ActionParameters[paramName] = filterContext.Controller.ValueProvider.GetValue(str).AttemptedValue;
23: break;
24: }
25: catch
26: {
27: continue;
28: }
29: }
30: }
31: }
虽然url传递使用了不同的参数名,但都验证成功了。
在若干model中对不同名的属性做同样的验证,也可行。
更进一步,对可能使用到的参数名,不写在attribute构造里,而通过一个配置文件设置,这样可以避免修改代码。
如果不使用filter,使用modelbinder也可以实现同样的效果
使用modelbinder还可以在提交时对整个表单做统一验证,而不是ajax对每个字段验证。这样可以减少客户端与服务器端之间的数据传输。不过就是要post之后错误才能显示出来,具体使用什么看情况而定。