Почему метод расширения не найден в 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, но я не могу понять, почему?
Ответы
Ответ 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
Создайте свой проект, прежде чем добавлять собственное пространство имен для расширений вашего представления.