0

I am porting some code from Asp.net 4.7 to Asp.Net 5 Core. The code is using a foreach statement to loop through records. It is using the legacy "DisplayTemplates" functionality that matches types in the DisplayTemplates folder to polymorphically display different HTML for each item depending on the model. All classes are derived from the same base class.

In order to get it to work correctly in Asp.Net 5 Core, I had to change the code from:

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

to:

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

... passing in the name of the type.

No problems problems and working correctly on my local machine.

The problem is when I publish the project to a remote server, the template used always defaults to the base class template.

Strangely enough, if I output the string returned by token.GetType().Name to the page, it matches the derived type name not the base type name.

Is this is a bug in .Net Core 5? If there is not a workaround, is there a better way to handle this in .Net 5?

WillC
  • 1,761
  • 17
  • 37
  • SUGGESTION: 1) Add a `[Display(Name="xyz")]` annotation to your model, 2) use `@Html.DisplayFor(model => model.MyField)` to display the record's value, and 3) use `@Html.DisplayNameFor(model => model.MyField)` to display the name of the field – paulsm4 Apr 12 '21 at 20:47
  • This is actually using a template that is called polymorphically depending on the subtype using a technique similar to the answer: https://stackoverflow.com/questions/58224973/how-to-use-displaytemplates-in-asp-net-core-razor-pages-with-model-inheritance The strangeness is that it does not work when Pulished to a remote site. – WillC Apr 12 '21 at 20:52
  • Sigh... The point is: Q: Are you trying to display an object member's *VALUE*, or its *NAME*? Q: If the latter, have you considered using `@Html.DisplayNameFor(model => model.MyField)` without any 2nd argument, and without ".GetType().Name"? – paulsm4 Apr 12 '21 at 21:32
  • Hi @WillC, where you publish your application, could you tell us more information about the remote server environment? I also check your code in .net core 5 application, and the code works well on IIS express, so, might be the issue relates the remote side, please check the .core version in remote side and if there have any error in the F12 console tools. – Zhi Lv Apr 13 '21 at 06:03

1 Answers1

1

The issue ended up being in the .csproj file. Somehow, either from the initial conversion from the old legacy project, or from moving the files around afterwards.

Simply removing these entries below fixed the issue as .Net Core generally uses the entries to excludes files (or modify how they are compiled), unlike legacy .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>

As an aside, I realized that it is possible to switch out the @Html.Display() call and use a dynamically named partial as below.

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

The only change was that files had to be moved up to the top level of the Shared directory for them to be found. This can be managed better by setting a custom location in the Startup file, like so.

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

This would seem to be more in line with standard CORE and .Net 5, now that Html Helpers are on the way out.

WillC
  • 1,761
  • 17
  • 37
  • Thanks man.... you rocked me... It was mind scratching for me whole night.... you saved me... I just did exclude the cshtml file and then include then it worked.... but it all with your hint... thanks a lot – Madhusudhan V Indian Apr 08 '23 at 00:49