在MVC流利的验证:指定规则集客户端验证 [英] Fluent Validation in MVC: specify RuleSet for Client-Side validation
问题描述
在我的ASP.NET MVC 4项目我已经验证了我的看法的机型,包含规则规则集定义之一。中邮动作中使用修改
规则集,当所有客户端验证通过。 网址
和电子邮件
规则集修改
规则集使用规则(你可以看到它下面),并在确认只有电子邮件和特殊阿贾克斯行动只会相应的URL。
我的问题是,视图不知道它应该使用客户端HTML设置<code>修改规则属性生成,并使用默认
规则集,里面是空的。 我怎么能告诉视图用于输入设置修改
规则属性代?
型号:
公共类ShopInfoViewModel
{
众长ShopId {搞定;组; } 公共字符串名称{;组; } 公共字符串网址{搞定;组; } 公共字符串描述{搞定;组; } 公共字符串电子邮件{获得;组; }
}
验证:
公共类ShopInfoViewModelValidator:AbstractValidator&LT; ShopInfoViewModel&GT;
{
公共ShopInfoViewModelValidator()
{
VAR shopManagementService = ServiceLocator.Instance.GetService&LT; IShopService&GT;(); 规则集(编辑,()=&GT;
{
RuleFor(X =&GT; x.Name)
.NotEmpty()。WithMessage(输入名称。)
。长度(0,255).WithMessage(姓名长度不能超过255个字符。); RuleFor(X =&GT; x.Description)
.NotEmpty()。WithMessage(输入名称。)
。长度(0,10000).WithMessage(姓名长度不能超过10000个字符。); ApplyUrlRule(shopManagementService);
ApplyEmailRule(shopManagementService);
}); 规则集(URL,()=&GT; ApplyUrlRule(shopManagementService));
规则集(电子邮件,()=&GT; ApplyEmailRule(shopManagementService));
} 私人无效ApplyUrlRule(IShopService shopService)
{
RuleFor(X =&GT; x.Url)
.NotEmpty()。WithMessage(输入网址。)
。长度(4,30).WithMessage(字符长度和30之间4)。
.Matches(@[A-Z \\ - \\ D])WithMessage(不正确的格式。)。
。必须((型号,URL)=&GT; shopService.Available(URL,model.ShopId))。WithMessage(店这个网址已经存在。);
} 私人无效ApplyEmailRule(IShopService shopService)
{
//类似URL规则:不为空,长度,正则表达式,必须检查是否有独特
}
}
验证操作实例:
公众的ActionResult ValidateShopInfoUrl([CustomizeValidator(规则集=URL)]
ShopInfoViewModel infoViewModel)
{
返回验证(ModelState中);
}
获取和发布动作 ShopInfoViewModel
:
[HTTPGET]
公众的ActionResult ShopInfo()
{
VAR视图模型= OwnedShop.ToViewModel();
返回PartialView(_ ShopInfo视图模型);
}[HttpPost]
公众的ActionResult ShopInfo(CustomizeValidator(规则集=编辑)] ShopInfoViewModel infoViewModel)
{
VAR成功= FALSE; 如果(ModelState.IsValid)
{
//保存逻辑放在这里
}
}
查看包含下一code:
@ {
Html.EnableClientValidation(真);
Html.EnableUnobtrusiveJavaScript(真);
}
&LT;窗体类=主表行动=@ Url.RouteUrl(ManagementRoutes.ShopInfo)方法=POSTID =masterforminfo&GT;
@ Html.TextBoxFor(X =&GT; x.Name)
@ Html.TextBoxFor(X =&GT; x.Url,新{validationUrl = Url.RouteUrl(ManagementRoutes.ValidateShopInfoUrl)})
@ Html.TextAreaFor(X =&GT; x.Description)
@ Html.TextBoxFor(X =&GT; x.Email,新{validationUrl = Url.RouteUrl(ManagementRoutes.ValidateShopInfoEmail)})
&LT;输入类型=提交名称=asdfasfdVALUE =Сохранить的风格=显示:无&GT;
&LT; /表及GT;
结果HTML输入(无需任何客户端验证属性):
&LT;输入名称=名称TYPE =文本值=超级店/&GT;
在FluentValidation来源挖后,我发现解决方案。告诉您要使用特定的规则集来看,装点你的动作,即返回视图, RuleSetForClientSideMessagesAttribute
:
[HTTPGET]
[RuleSetForClientSideMessages(编辑)]
公众的ActionResult ShopInfo()
{
VAR视图模型= OwnedShop.ToViewModel();
返回PartialView(_ ShopInfo视图模型);
}
如果你需要指定多个规则集 - 使用另一个构造函数重载和独立的规则集用逗号:
[RuleSetForClientSideMessages(编辑,电子邮件,URL)]
公众的ActionResult ShopInfo()
{
VAR视图模型= OwnedShop.ToViewModel();
返回PartialView(_ ShopInfo视图模型);
}
如果您需要决定哪些规则集将被直接用于操作 - 您可以通过将在HttpContext的下一个方式阵列( RuleSetForClientSideMessagesAttribute
当前未设计为破解FluentValidation被覆盖的):
公众的ActionResult ShopInfo(validateOnlyEmail)
{
VAR emailRuleSet =新[] {电子邮件};
VAR allRuleSet =新[] {编辑,地址,电子邮件}; VAR actualRuleSet = validateOnlyEmail? emailRuleSet:allRuleSet;
filterContext.HttpContext.Items [_ FV_ClientSideRuleSet] = actualRuleSet; 返回PartialView(_ ShopInfo视图模型);
}
不幸的是,大约有官方文档在此属性没有资料。
In my ASP.NET MVC 4 project I have validator for one of my view models, that contain rules definition for RuleSets. Edit
ruleset used in Post action, when all client validation passed. Url
and Email
rule sets rules used in Edit
ruleset (you can see it below) and in special ajax actions that validate only Email and only Url accordingly.
My problem is that view doesn't know that it should use Edit
rule set for client html attributes generation, and use default
rule set, which is empty. How can I tell view to use Edit
rule set for input attributes generation?
Model:
public class ShopInfoViewModel
{
public long ShopId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Description { get; set; }
public string Email { get; set; }
}
Validator:
public class ShopInfoViewModelValidator : AbstractValidator<ShopInfoViewModel>
{
public ShopInfoViewModelValidator()
{
var shopManagementService = ServiceLocator.Instance.GetService<IShopService>();
RuleSet("Edit", () =>
{
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Enter name.")
.Length(0, 255).WithMessage("Name length should not exceed 255 chars.");
RuleFor(x => x.Description)
.NotEmpty().WithMessage("Enter name.")
.Length(0, 10000).WithMessage("Name length should not exceed 10000 chars.");
ApplyUrlRule(shopManagementService);
ApplyEmailRule(shopManagementService);
});
RuleSet("Url", () => ApplyUrlRule(shopManagementService));
RuleSet("Email", () => ApplyEmailRule(shopManagementService));
}
private void ApplyUrlRule(IShopService shopService)
{
RuleFor(x => x.Url)
.NotEmpty().WithMessage("Enter url.")
.Length(4, 30).WithMessage("Length between 4 and 30 chars.")
.Matches(@"[a-z\-\d]").WithMessage("Incorrect format.")
.Must((model, url) => shopService.Available(url, model.ShopId)).WithMessage("Shop with this url already exists.");
}
private void ApplyEmailRule(IShopService shopService)
{
// similar to url rule: not empty, length, regex and must check for unique
}
}
Validation action example:
public ActionResult ValidateShopInfoUrl([CustomizeValidator(RuleSet = "Url")]
ShopInfoViewModel infoViewModel)
{
return Validation(ModelState);
}
Get and Post actions for ShopInfoViewModel
:
[HttpGet]
public ActionResult ShopInfo()
{
var viewModel = OwnedShop.ToViewModel();
return PartialView("_ShopInfo", viewModel);
}
[HttpPost]
public ActionResult ShopInfo(CustomizeValidator(RuleSet = "Edit")]ShopInfoViewModel infoViewModel)
{
var success = false;
if (ModelState.IsValid)
{
// save logic goes here
}
}
View contains next code:
@{
Html.EnableClientValidation(true);
Html.EnableUnobtrusiveJavaScript(true);
}
<form class="master-form" action="@Url.RouteUrl(ManagementRoutes.ShopInfo)" method="POST" id="masterforminfo">
@Html.TextBoxFor(x => x.Name)
@Html.TextBoxFor(x => x.Url, new { validationUrl = Url.RouteUrl(ManagementRoutes.ValidateShopInfoUrl) })
@Html.TextAreaFor(x => x.Description)
@Html.TextBoxFor(x => x.Email, new { validationUrl = Url.RouteUrl(ManagementRoutes.ValidateShopInfoEmail) })
<input type="submit" name="asdfasfd" value="Сохранить" style="display: none">
</form>
Result html input (without any client validation attributes):
<input name="Name" type="text" value="Super Shop"/>
After digging in FluentValidation sources I found solution. To tell view that you want to use specific ruleset, decorate your action, that returns view, with RuleSetForClientSideMessagesAttribute
:
[HttpGet]
[RuleSetForClientSideMessages("Edit")]
public ActionResult ShopInfo()
{
var viewModel = OwnedShop.ToViewModel();
return PartialView("_ShopInfo", viewModel);
}
If you need to specify more than one ruleset — use another constructor overload and separate rulesets with commas:
[RuleSetForClientSideMessages("Edit", "Email", "Url")]
public ActionResult ShopInfo()
{
var viewModel = OwnedShop.ToViewModel();
return PartialView("_ShopInfo", viewModel);
}
If you need to decide about which ruleset would be used directly in action — you can hack FluentValidation by putting array in HttpContext next way (RuleSetForClientSideMessagesAttribute
currently is not designed to be overriden):
public ActionResult ShopInfo(validateOnlyEmail)
{
var emailRuleSet = new[]{"Email"};
var allRuleSet = new[]{"Edit", "Url", "Email"};
var actualRuleSet = validateOnlyEmail ? emailRuleSet : allRuleSet;
filterContext.HttpContext.Items["_FV_ClientSideRuleSet"] = actualRuleSet;
return PartialView("_ShopInfo", viewModel);
}
Unfortunately, there are no info about this attribute in official documentation.
这篇关于在MVC流利的验证:指定规则集客户端验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!