Ошибка публикации Asp.Net 5 Core DisplayFor()

Я переношу некоторый код из Asp.net 4.7 в Asp.Net 5 Core. Код использует оператор foreach для перебора записей. Он использует устаревшую функциональность DisplayTemplates, которая сопоставляет типы в папке DisplayTemplates для полиморфного отображения разных HTML-кодов для каждого элемента в зависимости от модели. Все классы являются производными от одного и того же базового класса.

Чтобы заставить его работать правильно в Asp.Net 5 Core, мне пришлось изменить код:

 @foreach (var token in Model.TokenGraph)
 {
    @Html.DisplayFor(t => token)
 }

to:

 @foreach (var token in Model.TokenGraph)
 {
    @Html.DisplayFor(t => token, token.GetType().Name)
 }

... передавая имя типа.

Никаких проблем, проблем и корректной работы на моей локальной машине.

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

Как ни странно, если я вывожу на страницу строку, возвращаемую token.GetType().Name, она соответствует имени производного типа, а не имени базового типа.

Это ошибка в .Net Core 5? Если нет обходного пути, есть ли лучший способ справиться с этим в .Net 5?


person WillC    schedule 12.04.2021    source источник
comment
ПРЕДЛОЖЕНИЕ: 1) Добавьте аннотацию [Display(Name="xyz")] к вашей модели, 2) используйте @Html.DisplayFor(model => model.MyField) для отображения значения записи и 3) используйте @Html.DisplayNameFor(model => model.MyField) для отображения имени поля   -  person paulsm4    schedule 12.04.2021
comment
На самом деле это использует шаблон, который вызывается полиморфно в зависимости от подтипа с использованием метода, аналогичного ответу: stackoverflow.com/questions/58224973/ Странность в том, что это не работает при отправке на удаленный сайт.   -  person WillC    schedule 12.04.2021
comment
Эх... Суть в следующем: В: Вы пытаетесь отобразить VALUE члена объекта или его NAME? В: Если последнее, рассматривали ли вы возможность использования @Html.DisplayNameFor(model => model.MyField) без второго аргумента и без .GetType().Name?   -  person paulsm4    schedule 13.04.2021
comment
Привет @WillC, где вы публикуете свое приложение, не могли бы вы рассказать нам больше информации о среде удаленного сервера? Я также проверяю ваш код в приложении .net core 5, и код хорошо работает в IIS Express, поэтому, возможно, проблема связана с удаленной стороной, пожалуйста, проверьте версию .core на удаленной стороне и если есть какая-либо ошибка в F12 инструменты консоли.   -  person Zhi Lv    schedule 13.04.2021


Ответы (1)


Проблема оказалась в файле .csproj. Каким-то образом, либо из-за первоначального преобразования из старого устаревшего проекта, либо из-за последующего перемещения файлов.

Простое удаление этих записей ниже устранило проблему, поскольку .Net Core обычно использует записи для исключения файлов (или изменения способа их компиляции), в отличие от устаревшей .Net.

  <ItemGroup>
    <Compile Remove="Pages\Shared\DisplayTemplates\**" />
    <Content Remove="Pages\Shared\DisplayTemplates\**" />
    <EmbeddedResource Remove="Pages\Shared\DisplayTemplates\**" />
    <None Remove="Pages\Shared\DisplayTemplates\**" />
  </ItemGroup>

  <ItemGroup>
    <Content Include="Pages\Shared\DisplayTemplates\Token.cshtml">
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
  </ItemGroup>

  <ItemGroup>
    <None Include="Pages\Shared\DisplayTemplates\TextToken.cshtml" />
    ....
  </ItemGroup>

Кроме того, я понял, что можно отключить вызов @Html.Display() и использовать частичное с динамическим именем, как показано ниже.

 @foreach (var token in Model.TokenGraph)
 {
    <partial name="@token.GetType().Name" model="token" />
 }

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

services.AddMvc().AddRazorOptions(options =>
{
    options.PageViewLocationFormats.Add("/Pages/DisplayTemplates/{0}.cshtml");
});

Казалось бы, это больше соответствует стандарту CORE и .Net 5, теперь, когда помощники Html уходят.

person WillC    schedule 13.04.2021