Исключение переполнения стека в 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() можно посмотреть здесь)

Другие вопросы по тегам