howto: вложенные вызовы методов расширения - PullRequest
1 голос
/ 27 октября 2011

В моем cshtml есть следующая строка:

@Html.TextBoxFor(m => m.EmailAddress, new { @class = "field size4",
placeholder = LogOnUIMessages.EmailFieldLabel, id = "LoginEmailAddress",
name="LoginEmail", autofocus = "", required=""})

Поскольку поле 'required' уже определено как аннотация данных (атрибут добавлен для простой и понятной проверки 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);
}

и

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

Но когда вызывается как:

@Html.CustomTextBoxFor(
    m => m.EmailAddress, new { @class = "field size4", placeholder = 
    LogOnUIMessages.EmailFieldLabel, id = "LoginEmailAddress",
    name="LoginEmail", autofocus = "", required=""})

И

@PocExtensions.CustomTextBoxForToo(
    this.Html, m => m.EmailAddress, new { @class = "field size4", 
    placeholder = LogOnUIMessages.EmailFieldLabel, 
    id = "LoginEmailAddress", name="LoginEmail", 
    autofocus = "", required=""})

Они оба возвращаются:

<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="">

Что я делаю не так?

Редактировать # 1, дополнительная информация

IEnumerable<ModelValidator> modelValidators=metadata.GetValidators(htmlHelper.ViewContext); 

возвращает 4 валидатора. В то время как:

htmlHelper.GetUnobtrusiveValidationAttributes(elementName, metadata);

возвращает пустую коллекцию?

Редактировать # 2 Я нашел причину своей проблемы, но пока не нашел чистого решения. Проблема заключается в функции GetUnobtrusiveValidationAttributes, которая вызывается внутри функции GetTextBoxFor. Это не доходит до аннотации данных в моем объекте, потому что имя, используемое при вызове функции, должно иметь структуру [CLASS]. [PROPERTY], в то время как функция ExpressionHelper.GetExpressionText (используемая в GetTextBoxFor) дает только имя [PROPERTY] .

Теперь мне интересно, это ошибка или это задумано?

Мне удалось собрать 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));
    }

Теперь мой вопрос: (как) это можно сделать лучше?

1 Ответ

0 голосов
/ 27 октября 2011

В моих вспомогательных классах, когда я добавляю данные и затем передаю базовым помощникам MVC 3, я использую следующее:

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

Я не зарегистрировался в исходном коде MVC 3 для этой проблемы, но я ожидаю, что причиной вашей проблемы является вызов через htmlHelper.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...