C# howto:嵌套扩展方法调用
在我的cshtml中,我有以下行: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
@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!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-
9!#$%&'*+/=?^_`{|}~-]+)*@(?:[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);