Исключение переполнения стека в MVcHtmlString
Я создал свой собственный Html Helper, который добавляет красные звездочки в любое обязательное поле.
Он успешно работает как с
@Html.myLabelFor(model => model.Description)
//and
@Html.myLabelFor(model => model.Description, new { /*stuff*/ })
Тем не менее, некоторые строки кода похожи на следующие
@Html.myLabelFor(model => model.Description, "Deletion Reason", new { /*stuff*/ })
Мой метод не был предназначен для обработки 3 параметров, поэтому я добавил вызывающую функцию, которая будет обрабатывать 3 параметра
public static MvcHtmlString myLabelFor<TModel, TValue>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, string labelText, Object htmlAttributes)
{
return myLabelFor(html, expression, labelText, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
Ниже приведены другие методы, которые работают должным образом (в том числе внутренний, который содержит весь необходимый код и чью структуру я использовал в качестве ссылки)
public static MvcHtmlString myLabelFor<TModel, TValue>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, IDictionary<String, Object> htmlAttributes)
{
return LabelHelper(html, ModelMetadata.FromLambdaExpression(expression, html.ViewData),
ExpressionHelper.GetExpressionText(expression), null, htmlAttributes);
}
public static MvcHtmlString myLabelFor<TModel, TValue>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression)
{
return LabelHelper(html, ModelMetadata.FromLambdaExpression(expression, html.ViewData),
ExpressionHelper.GetExpressionText(expression), null);
}
public static MvcHtmlString myLabelFor<TModel, TValue>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, Object htmlAttributes)
{
return myLabelFor(html, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
//USED ITS STRUCTURE AS A REFERENCE
internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, String htmlFieldName,
String labelText = null, IDictionary<String, Object> htmlAttributes = null)
Логично, что я ожидал, что параметр labelText примет значение "Причина удаления" из строки кода выше. Однако вместо этого он создал исключение StackruException в моем методе с тремя параметрами. Описание Microsoft было расплывчатым, дополнительные объяснения не помогли, и использовалось дополнительное решение.
Expression<Func<TModel, string>> expression instead of my Expression<Func<TModel, TValue>> expression
Я не понимаю, что я делаю не так. На данный момент я могу думать только о "возиться с параметрами, пока он не сработает", но я надеюсь, что есть более элегантное решение этой проблемы.
PS: Пожалуйста, дайте мне знать, поможет ли мой код для внутреннего помощника решить проблему.
1 ответ
Вы получаете исключение при первой перегрузке, потому что метод рекурсивно вызывает себя и продолжает делать это до тех пор, пока стек выполнения не переполнится. Вместо того, чтобы называть себя нужно изменить
return myLabelFor(html,
expression,
labelText,
HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
в
return LabelHelper(html,
ModelMetadata.FromLambdaExpression(expression, html.ViewData),
ExpressionHelper.GetExpressionText(expression),
labelText,
HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
Из ваших комментариев, причина вашего 4-го перегрузки, который использует return myLabelFor(...)
не выдает исключение, потому что это вызывает вашу вторую перегрузку, которая в свою очередь вызывает return LabelHelper(...)
Я рекомендую вам изменить 4-ю перегрузку на вызов LabelHelper()
напрямую, и измените все публичные перегрузки для явного вызова LabelHelper()
, передавая все 4 параметра, что является шаблоном, используемым встроенными методами расширения `HtmlHelper ( исходный код LabelFor() можно посмотреть здесь)