When using the EF Core DB first approach, the default views do not display the primary key. How can you control what data is shown in the view?
I searched for templates and code generated. I searched EF Core tutorials and examples.
It uses the templates in folder: C:\Users\{you}\.nuget\packages\microsoft.visualstudio.web.codegenerators.mvc\{version}\Templates\ViewGenerator
to scaffold views
The List Template:
@inherits Microsoft.VisualStudio.Web.CodeGeneration.Templating.RazorTemplateBase
@using Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore
@using System.Collections.Generic
@using System.Linq
@@model @GetEnumerableTypeExpression(Model.ViewDataTypeName)
@{
if (Model.IsPartialView)
{
}
else if (Model.IsLayoutPageSelected)
{
@:@@{
@:ViewData["Title"] = "@Model.ViewName";
if (!string.IsNullOrEmpty(Model.LayoutPageFile))
{
@:Layout = "@Model.LayoutPageFile";
}
@:}
@:
@:<h1>@Model.ViewName</h1>
@:
}
else
{
@:@@{
@:Layout = null;
@:}
@:
@:<!DOCTYPE html>
@:
@:<html>
@:<head>
@:<meta name="viewport" content="width=device-width" />
@:<title>@Model.ViewName</title>
@:</head>
@:<body>
// PushIndent(" ");
}
@:<p>
@:<a asp-action="Create">Create New</a>
@:</p>
@:<table class="table">
@:<thead>
@:<tr>
Dictionary<string, IPropertyMetadata> propertyLookup = ((IModelMetadata)Model.ModelMetadata).Properties.ToDictionary(x => x.PropertyName, x => x);
Dictionary<string, INavigationMetadata> navigationLookup = ((IModelMetadata)Model.ModelMetadata).Navigations.ToDictionary(x => x.AssociationPropertyName, x => x);
foreach (var item in Model.ModelMetadata.ModelType.GetProperties())
{
if (propertyLookup.TryGetValue(item.Name, out IPropertyMetadata property)
&& property.Scaffold && !property.IsForeignKey && !property.IsPrimaryKey)
{
<th>
@@Html.DisplayNameFor(model => model.@GetValueExpression(property))
</th>
}
else if (navigationLookup.TryGetValue(item.Name, out INavigationMetadata navigation))
{
<th>
@@Html.DisplayNameFor(model => model.@GetValueExpression(navigation))
</th>
}
}
@:<th></th>
@:</tr>
@:</thead>
@:<tbody>
@:@@foreach (var item in Model) {
@:<tr>
foreach (var item in Model.ModelMetadata.ModelType.GetProperties())
{
if (propertyLookup.TryGetValue(item.Name, out IPropertyMetadata property)
&& property.Scaffold && !property.IsForeignKey && !property.IsPrimaryKey)
{
<td>
@@Html.DisplayFor(modelItem => item.@GetValueExpression(property))
</td>
}
else if (navigationLookup.TryGetValue(item.Name, out INavigationMetadata navigation))
{
<td>
@@Html.DisplayFor(modelItem => item.@GetValueExpression(navigation).@navigation.DisplayPropertyName)
</td>
}
}
string pkName = GetPrimaryKeyName();
if (pkName != null)
{
@:<td>
@:<a asp-action="Edit" asp-route-id="@@item.@pkName">Edit</a> |
@:<a asp-action="Details" asp-route-id="@@item.@pkName">Details</a> |
@:<a asp-action="Delete" asp-route-id="@@item.@pkName">Delete</a>
@:</td>
}
else
{
<td>
@@Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
@@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
@@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
}
@:</tr>
@:}
@:</tbody>
@:</table>
if(!Model.IsPartialView && !Model.IsLayoutPageSelected)
{
//ClearIndent();
@:</body>
@:</html>
}
}
@functions
{
string GetPrimaryKeyName()
{
return (Model.ModelMetadata.PrimaryKeys != null && Model.ModelMetadata.PrimaryKeys.Length == 1)
? Model.ModelMetadata.PrimaryKeys[0].PropertyName
: null;
}
string GetValueExpression(IPropertyMetadata property)
{
return property.PropertyName;
}
string GetValueExpression(INavigationMetadata navigation)
{
return navigation.AssociationPropertyName;
}
string GetEnumerableTypeExpression(string typeName)
{
return "IEnumerable<" + typeName + ">";
}
}
If you want to scaffold views that show primary key,delete the primary key check in codes above
&& !property.IsPrimaryKey
Result: