gpt4 book ai didi

c# - ASP MVC 中的动态验证

转载 作者:行者123 更新时间:2023-11-30 17:12:38 24 4
gpt4 key购买 nike

对于工作中的项目,我正在尝试创建一个流程,让用户动态创建一个表单,然后其他用户可以为其填写值。不过,我无法弄清楚如何通过 ASP MVC 3 使它与内置模型绑定(bind)和验证很好地配合使用。

我们的 View 模型是这样设置的。请注意,我过度简化了示例代码:

public class Form 
{
public FieldValue[] FieldValues { get; set; }
}

public class Field
{
public bool IsRequired { get; set; }
}

public class FieldValue
{
public Field Field { get; set; }
public string Value { get; set; }
}

我们的 View 看起来像这样:

@model Form
@using (Html.BeginForm("Create", "Form", FormMethod.Post))
{
@for(var i = 0; i < Model.Fields.Count(); i++)
{
@Html.TextBoxFor(_ => @Model.Fields[i].Value)
}
<input type="submit" value="Save" name="Submit" />
}

我希望我们能够创建一个自定义的 ModelValidatorProvider 或 ModelMetadataProvider 类,它们能够分析 FieldValue 实例,确定其 Field.IsRequired 属性是否为真,然后将 RequiredFieldValidator 添加到该特定实例的验证器.不过,我没有运气。似乎使用 ModelValidatorProvider(和 ModelMetadataProvider)您无法访问父容器的值(即:将为 FieldValue.Value 调用 GetValidators(),但无法从那里获取 FieldValue 对象)。

我尝试过的事情:

  • 在 ModelValidatorProvider 中,我尝试使用ControllerContext.Controller.ViewData.Model,但如果你有嵌套类型。如果我想找出验证器Form.FieldValues[3],我不知道要使用哪个 FieldValue。

  • 我尝试使用一个自定义的 ModelMetadata,它试图使用内部modelAccessor 的 Target 属性来获取父级,但这也如果您有嵌套类型,则不起作用。在 MVC 内部的某个地方,一个像我示例中的那样的表达式将导致 Target 成为模型的类型(表单),而不是 FieldValue。所以我遇到了同样的问题在上面我不知道要比较哪个 FieldValue 实例反对。

  • 我可以放在 FieldValue 上的类级验证属性类本身,但这只在服务器验证期间被调用。我也需要客户端验证。

我尝试做的事情在 MVC 中是否可行?还是我完全遗漏了什么?

最佳答案

一种可能性是使用自定义验证属性。

但在开始实现之前,我想指出您的场景中的一个潜在缺陷。 IsRequired 属性是模型的一部分。这意味着当提交表单时,它的值必须是已知的,以便我们有条件地将所需规则应用于相应的属性。但是要在提交表单时知道此值,这意味着它必须是表单的一部分(作为隐藏或标准输入字段)或者必须从某个地方(数据存储,...)检索。第一种方法的问题很明显 => 隐藏字段意味着用户可以设置他喜欢的任何值,因此它不再是真正的验证,因为由用户决定需要哪个字段。

说到这个警告,让我们假设您信任您的用户并决定采用隐藏字段方法来存储 IsRequired 值。让我们看看示例实现如何:

型号:

public class Form
{
public FieldValue[] Fields { get; set; }
}

public class FieldValue
{
public Field Field { get; set; }

[ConditionalRequired("Field")]
public string Value { get; set; }
}

public class Field
{
public bool IsRequired { get; set; }
}

Controller :

public class HomeController : Controller
{
public ActionResult Index()
{
var model = new Form
{
Fields = new[]
{
new FieldValue { Field = new Field { IsRequired = true }, Value = "" },
new FieldValue { Field = new Field { IsRequired = true }, Value = "" },
new FieldValue { Field = new Field { IsRequired = false }, Value = "value 3" },
}
};
return View(model);
}

[HttpPost]
public ActionResult Index(Form model)
{
return View(model);
}
}

查看:

@model Form
@using (Html.BeginForm())
{
@Html.EditorFor(x => x.Fields)
<input type="submit" value="Save" name="Submit" />
}

条件要求属性:

public class ConditionalRequiredAttribute : ValidationAttribute, IClientValidatable
{
private RequiredAttribute _innerAttribute = new RequiredAttribute();

private readonly string _fieldProperty;

public ConditionalRequiredAttribute(string fieldProperty)
{
_fieldProperty = fieldProperty;
}

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var containerType = validationContext.ObjectInstance.GetType();
var field = containerType.GetProperty(_fieldProperty);
if (field == null)
{
return new ValidationResult(string.Format("Unknown property {0}", _fieldProperty));
}

var fieldValue = (Field)field.GetValue(validationContext.ObjectInstance, null);
if (fieldValue == null)
{
return new ValidationResult(string.Format("The property {0} was null", _fieldProperty));
}

if (fieldValue.IsRequired && !_innerAttribute.IsValid(value))
{
return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
}

return ValidationResult.Success;
}


public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule()
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "conditionalrequired",
};

rule.ValidationParameters.Add("iserquiredproperty", _fieldProperty + ".IsRequired");

yield return rule;
}
}

关联的不显眼的适配器:

(function ($) {
$.validator.unobtrusive.adapters.add('conditionalrequired', ['iserquiredproperty'], function (options) {
options.rules['conditionalrequired'] = options.params;
if (options.message) {
options.messages['conditionalrequired'] = options.message;
}
});

$.validator.addMethod('conditionalrequired', function (value, element, parameters) {
var name = $(element).attr('name'),
prefix = name.substr(0, name.lastIndexOf('.') + 1),
isRequiredFiledName = prefix + parameters.iserquiredproperty,
requiredElement = $(':hidden[name="' + isRequiredFiledName + '"]'),
isRequired = requiredElement.val().toLowerCase() === 'true';

if (!isRequired) {
return true;
}

return value && value !== '';
});

})(jQuery);

关于c# - ASP MVC 中的动态验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10522655/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com