asp.net-coreentity-framework-coreasp.net-core-mvcscaffolding

EF Core CRUD Scaffold, show primary key in view?


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.


Solution

  • 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:

    enter image description here