我开发了用于管理单选按钮的自定义htmlhelper。从我的自定义帮助程序生成基本html标记没有问题。但是我在html标记中注入(inject)验证属性存在问题(客户端非侵入式验证)。我使用htmlHelper.GetUnobtrusiveValidationAttributes(prefix)从模型(数据注释)中检索验证属性,但不适用于我的自定义RequiredAttribute。

这是我的 View 模型的一部分:

public class MaterialEditNewViewModel
{
    public int RequestId { get; set; }

    [CustomRequired]
    Public bool ADR { get; set; }
    ...
}

这是我的CustomRequired:
public class CustomRequiredAttribute : RequiredAttribute
{
    public override string FormatErrorMessage(string name)
    {
        string translatedFieldName = UserResource.ResourceManager.GetString(name);
        if (string.IsNullOrWhiteSpace(translatedFieldName))
            translatedFieldName = name;
        return string.Format(UserResource.FieldRequired, translatedFieldName);
    }
}

这是我的自定义html帮助器:
public static IHtmlString RadioButtonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, string labelText)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        string prefix = ExpressionHelper.GetExpressionText(expression);

        var validationAttributes = htmlHelper.GetUnobtrusiveValidationAttributes(prefix);

        object currentValue = metadata.Model;
        string property = metadata.PropertyName;

        // Build the radio button html tag
        var htmlRadio = new TagBuilder("input");
        htmlRadio.GenerateId(property + value);
        htmlRadio.Attributes["type"] = "radio";
        htmlRadio.Attributes["name"] = property;
        htmlRadio.Attributes["value"] = Convert.ToString(value);

        foreach (KeyValuePair<string, object> pair in validationAttributes)
        {
            htmlRadio.MergeAttribute(pair.Key, pair.Value.ToString());
        }

        if (object.Equals(currentValue, value))
        {
            htmlRadio.Attributes["checked"] = "checked";
        }

        // Build the label html tag
        var label = new TagBuilder("label");
        label.Attributes["for"] = htmlRadio.Attributes["id"];
        label.SetInnerText(labelText);

        // Return the concatenation of both tags
        return new HtmlString(htmlRadio.ToString(TagRenderMode.SelfClosing) + label.ToString()
        );
    }
  • 您必须知道我的CustomRequired数据注释适用于@ Html.RadioButtonFor(model => model.ADR)之类的基本帮助程序,但是在自定义htmlhelper上使用时无效。
  • 我知道当我在模型中使用像[Required]这样的“经典”数据注释时,使用CustomRequiredAttribute时,GetUnobtrusiveValidationAttributes不会返回任何检索验证属性的问题!

  • 知道为什么吗?如果我不清楚,请不要犹豫,让我澄清一下。

    我忘了说我将MVC3与Entity Framework Code First一起使用。

    谢谢。

    最佳答案

    由于RequiredAttribute未实现IClientValidatable接口(interface),因此必须为自定义属性注册一个自定义适配器。您可以通过在Application_Start中添加以下行来做到这一点:

    DataAnnotationsModelValidatorProvider.RegisterAdapter(
        typeof(CustomRequiredAttribute),
        typeof(RequiredAttributeAdapter)
    );
    

    有两种方法可以实现客户端验证属性:
  • 让您的自定义验证属性实现IClientValidatable接口(interface)
  • 注册自定义适配器
  • RequiredAttribute使用第二种方法。它将RequiredAttributeAdapter与所有必需的属性相关联。但是由于您是从RequiredAttribute派生的,因此您的自定义属性不再具有适配器。因此,您需要在Application_Start中注册它。

    10-05 20:43
    查看更多