Подтвердить что ты не робот

Почему метод расширения не найден в MVC4 Razor View?

Учитывая следующий метод расширения строки

namespace JHS.ExtensionMethods
{
  public static class StringExtensions
  {
    public static string ToUSAPhone(this String str)
    {
      return String.Format("{0:(###) ###-####}", Double.Parse(str));
    }
  }
}

В представлении MVC4 Razor добавлен оператор @using

@using JHS.ExtensionMethods;

и следующее строковое значение вызывает метод расширения

@Model.producer.phone.ToUSAPhone()

что приводит к следующей ошибке

'string' does not contain a definition for 'ToUSAPhone'

Я также попытался поместить пространство имен в файл web.config из папки /Views и получить ту же ошибку.

<pages pageBaseType="System.Web.Mvc.WebViewPage">
  <namespaces>
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Optimization"/>
    <add namespace="System.Web.Routing" />
    <add namespace="JHS.ExtensionMethods"/>
  </namespaces>
</pages>

Я проверил, что метод расширения работает, помещая тот же вызов в класс С#

string test=producer.phone.ToUSAPhone();

Кажется, ссылка на метод расширения недоступна в представлении Razor MVC4, но я не могу понять, почему?

4b9b3361

Ответ 1

Это происходит, если тип, который вы пытаетесь использовать метод расширения, на самом деле равен dynamic. Проверьте, генерируется ли исключение CSharp RuntimeBinder. Если это так, вы можете использовать этот метод как обычный или садовый статический метод:

@StringExtensions.ToUSAPhone(Model.producer.phone)

Или вы можете передать значение в строку:

@(((string)Model.producer.phone).ToUSAPhone())

По словам Эрика Липперта (ранее MSFT):

Причина того, что динамика не поддерживает расширение типы - это потому, что в обычных, нединамических методах расширения кода работают выполнив полный поиск всех классов, известных компилятору для статический класс, который имеет метод расширения, который соответствует. Поиск идет в порядке, основанном на вложенности пространства имен и доступном "использовании", директивы в каждом пространстве имен.

Это означает, что для того, чтобы получить вызов динамического расширения правильно разрешено, так или иначе DLR должна знать во время выполнения, что все вложенные пространства имен и "используемые" директивы были в вашем источнике код. Для кодирования всей этой информации нет механизма на сайт вызова.

Ответ 2

Это не только если тип, вызываемый методом расширения, является динамическим, но если что-либо в выражении динамическое и не выполняется.

например, это явно динамично:

@ViewBag.ToJSON()

Но я сначала подумал, что ответ Майка не относится ко мне, потому что я делал это:

@(ViewBag.UserProfile.GetJSONProfile().ToJSON())

где ToJSON() - мой метод расширения, а GetJSONProfile() просто возвращает object.

Я просто расходился и был глупым, но хотел упомянуть об этом.

Ответ 3

Создайте свой проект, прежде чем добавлять собственное пространство имен для расширений вашего представления.