C# howto:嵌套扩展方法调用

C# howto:嵌套扩展方法调用,c#,asp.net-mvc,asp.net-mvc-3,C#,Asp.net Mvc,Asp.net Mvc 3,在我的cshtml中,我有以下行: @Html.TextBoxFor(m => m.EmailAddress, new { @class = "field size4", placeholder = LogOnUIMessages.EmailFieldLabel, id = "LoginEmailAddress", name="LoginEmail", autofocus = "", required=""}) 由于字段'required'已定义为数据注释,因此添加该属性是为了进行eas

在我的cshtml中,我有以下行:

@Html.TextBoxFor(m => m.EmailAddress, new { @class = "field size4",
placeholder = LogOnUIMessages.EmailFieldLabel, id = "LoginEmailAddress",
name="LoginEmail", autofocus = "", required=""})
由于字段'required'已定义为数据注释,因此添加该属性是为了进行easy&clean JS验证,因此我想编写一个新的TextBoxFor实现,其中包括基于数据注释的'required':

[Required(ErrorMessageResourceType = typeof(LogOnUIMessages), ErrorMessageResourceName = LogOnResourceKeys.ErrorEmailIsRequired)]
[StringLength(UserNameMaxLength, ErrorMessageResourceType = typeof(LogOnUIMessages), ErrorMessageResourceName = LogOnResourceKeys.ErrorUserNameMaxLenghtExceeded)]
[RegularExpression(RegEx.CorrectEmailRegExp, ErrorMessageResourceType = typeof(ProfileUIMessages), ErrorMessageResourceName = LogOnResourceKeys.ErrorEmailIsNotValid)]
[DataType(DataType.EmailAddress)]
public String EmailAddress { get; set; }
给出了更多的注释,只是显示了最重要的注释,作为概念证明,我编写了一个扩展方法和一个助手方法:

public static MvcHtmlString CustomTextBoxFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        object htmlAttributes
    )
{
    return htmlHelper.TextBoxFor(expression, htmlAttributes);
}

他们都返回:

<input autofocus="" class="field size4" id="LoginEmailAddress" 
name="EmailAddress" placeholder="vul je e-mail adres in" 
required="" type="text" value="">
返回一个空集合

编辑2 我已经找到了问题的原因,但还没有一个干净的解决方案。问题在于GetUnobtrusiveValidationAttributes函数,该函数在GetTextBoxFor函数中调用。 这不会到达我的对象上的数据注释,因为调用函数时使用的名称应该具有[CLASS].[PROPERTY]结构,而GetTextBoxFor中使用的ExpressionHelper.GetExpressionText函数只生成[PROPERTY]名称

现在我想知道,这是一个bug还是设计的

我成功地建立了一个POC:

public static MvcHtmlString CustomTextBoxFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    object htmlAttributes
)
{
    var elementName = ExpressionHelper.GetExpressionText(expression);
    var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

    var dataAnnotationAttributeDictionary = htmlHelper.GetUnobtrusiveValidationAttributes
(
    String.Format("{0}.{1}", metadata.ContainerType.FullName, elementName),
    metadata
);
var providedAttributeDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

return htmlHelper.TextBoxFor(expression, providedAttributeDictionary.Concat(dataAnnotationAttributeDictionary).ToDictionary(pair => pair.Key, pair => pair.Value));
    }

现在我的问题是:如何才能做得更好?

在我的助手类中,当我添加数据并传递给底层MVC 3助手时,我使用以下方法:

return InputExtensions.TextBoxFor(htmlHelper, expression, htmlAttributes);

我还没有检查这个问题的MVC 3源代码,但我希望通过htmlHelper调用是您问题的原因。

使用正则表达式;我没有看到任何读取属性的代码,所以你认为这应该如何工作?@Daniel:我从我自己的扩展名CustomTextBoxFor中调用函数TextBoxFor来执行属性插入。就我所知,这与直接从cshtml调用它是一样的。因此,我希望原始方法TextBoxFor将根据注释插入所有属性。我的代码只是包装一个扩展方法的简单测试。你期望的字符串-你从哪里得到它?当您使用@Html.TextBoxFor而不是@Html.CustomTextBoxFor时,是否返回了它?我在问,因为预期的输出与您显示的属性不匹配…也尝试了:return InputExtensions.TextBoxForhtmlHelper,expression,IDictionary HtmlHelper.AnonymousObjectToHtmlAttributeshtmlAttributes;没什么区别。
<input autofocus="" class="field size4" id="LoginEmailAddress" 
name="EmailAddress" placeholder="vul je e-mail adres in" 
required="" type="text" value="">
<input autofocus="" class="field size4" data-val="true" 
data-val-length="Het opgegeven emailadres is te lang." 
data-val-length-max="128" data-val-regex="Het opgegeven adres is niet geldig" 
data-val-regex-pattern="[A-Za-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-
9!#$%&amp;'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])
?\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?" 
data-val-required="Dit veld is verplicht." id="LoginEmailAddress" 
name="EmailAddress" placeholder="vul je e-mail adres in" 
required="" type="text" value="">
IEnumerable<ModelValidator> modelValidators=metadata.GetValidators(htmlHelper.ViewContext); 
htmlHelper.GetUnobtrusiveValidationAttributes(elementName, metadata);
public static MvcHtmlString CustomTextBoxFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    object htmlAttributes
)
{
    var elementName = ExpressionHelper.GetExpressionText(expression);
    var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

    var dataAnnotationAttributeDictionary = htmlHelper.GetUnobtrusiveValidationAttributes
(
    String.Format("{0}.{1}", metadata.ContainerType.FullName, elementName),
    metadata
);
var providedAttributeDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

return htmlHelper.TextBoxFor(expression, providedAttributeDictionary.Concat(dataAnnotationAttributeDictionary).ToDictionary(pair => pair.Key, pair => pair.Value));
    }
return InputExtensions.TextBoxFor(htmlHelper, expression, htmlAttributes);