Унаследованное свойство интерфейса не найдено привязкой модели в MVC3, но отлично работает в MVC2 - PullRequest
10 голосов
/ 09 декабря 2011

ОБНОВЛЕНИЕ: Проблема решена.

Ответ Дарина Димитрова содержит ссылку на другой связанный вопрос. Одно из предложенных решений на этой странице сработало для нас.


Оригинальный вопрос

Пример кода ниже работает в MVC 2, но вызывает исключение в MVC 3. Кто-нибудь знает, почему MVC 3 ввел это критическое изменение? Есть ли способ заставить это работать в MVC 3, в то же время позволяя мне описать модель представления как Интерфейс из представления?

Есть еще один связанный вопрос о StackOverflow, но он не дает мне никакой информации о том, почему существует разница между MVC 2 и MVC 3.

Модель

public interface IPerson {
    string Name { get; set; }
}

public interface ISpy : IPerson {
    string CodeName { get; set; }
}

public class Spy : ISpy {
    public string Name { get; set; }
    public string CodeName { get; set; }
}

Действие контроллера

public ActionResult Index() {
    var model = new Spy { Name = "James Bond", CodeName = "007" };
    return View(model);
}

MVC2 View (отлично работает)

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcApp.Models.ISpy>" %>
<p>CodeName: <%: Html.TextBoxFor(x => x.CodeName) %></p>
<p>Name: <%: Html.TextBoxFor(x => x.Name) %></p>

MVC3 View (исключение Throws)

@model MvcApp.Models.ISpy
<p>Name: @Html.TextBoxFor(x => x.Name)</p>
<p>CodeName: @Html.TextBoxFor(x => x.CodeName)</p>

Информация об исключении MVC3

Я показываю соответствующую информацию об исключении ниже, но вы можете просмотреть весь вывод страницы ошибки здесь: https://gist.github.com/1443750.

Runtime Exception
System.ArgumentException: The property **`MvcApp.Models.ISpy.Name`** could not be found.

Source Error:

Line 1:  @model MvcApp.Models.ISpy
Line 2:  <p>CodeName: @Html.TextBoxFor(x => x.CodeName)</p>
Line 3:  <p>Name: @Html.TextBoxFor(x => x.Name)</p>


Stack Trace:

[ArgumentException: The property MvcApp.Models.ISpy.Name could not be found.]
   System.Web.Mvc.AssociatedMetadataProvider.GetMetadataForProperty(Func`1 modelAccessor, Type containerType, String propertyName) +502169
   System.Web.Mvc.ModelMetadata.GetMetadataFromProvider(Func`1 modelAccessor, Type modelType, String propertyName, Type containerType) +101
   System.Web.Mvc.ModelMetadata.FromLambdaExpression(Expression`1 expression, ViewDataDictionary`1 viewData) +421
   System.Web.Mvc.Html.InputExtensions.TextBoxFor(HtmlHelper`1 htmlHelper, Expression`1 expression, IDictionary`2 htmlAttributes) +58
   System.Web.Mvc.Html.InputExtensions.TextBoxFor(HtmlHelper`1 htmlHelper, Expression`1 expression) +50
   ASP._Page_Views_Home_Index_cshtml.Execute() in c:\Projects\MvcApplication1\MvcApplication1\Views\Home\Index.cshtml:3

Помогите нам, Дарин Димитров, вы наша единственная надежда.

Ответы [ 3 ]

9 голосов
/ 10 декабря 2011

Я уже довел эту проблему до сведения Microsoft. К сожалению, я получил ответ: извините, это по замыслу Лично из такого ответа я делаю вывод, что команда MVC разрабатывает продукт с ошибками, если он разработан. И их нельзя обвинять в том, что они приняли такое дизайнерское решение, они обвиняют в том, что они нигде не упоминаются в разделе критических изменений документа с примечаниями к выпуску. Если бы они упомянули об этом, то это была бы наша вина, когда мы приняли решение о миграции, даже если бы мы сознательно знали о критических изменениях.

В любом случае, вот связанный вопрос .

И вот ответ от команды MVC:

К сожалению, код фактически использовал ошибку, которая была исправлена, где контейнер выражения для целей ModelMetadata был непреднамеренно установить декларирующий тип вместо содержащего тип. Эта ошибка должна была быть исправлена ​​из-за потребностей виртуального свойства и проверка / метаданные модели.

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

0 голосов
/ 06 октября 2015

Я нашел жалкий обходной путь, который позволяет использовать эту модель:

@model MvcApp.Models.IPerson
<p>Name: @Html.TextBoxFor(x => x.Name)</p>
@Html.Partial('_SpyBox')

И в _SpyBox.cshtml

@model MvcApp.Models.ISpy
<p>CodeName: @Html.TextBoxFor(x => x.CodeName)</p>

Мех.

0 голосов
/ 09 декабря 2011

Изменить эту строку:

@model MvcApp.Models.ISpy

Для

@model MvcApp.Models.Spy
...