Search code examples
asp.net-corerazorrazor-pages

Razor Pages: how can I pass my database data to a partial view/ to the _Layout.cshtml?


Is there a way to add something like a PageModel to a partial view. i want to have a dropdown that shows my active projects like so:

<li class="nav-item dropdown">
                            <a class="nav-link dropdown-toggle" href="#" id="navbardrop" data-toggle="dropdown">
                                Projects
                            </a>
                            <div class="dropdown-menu">
                            @foreach(var p in Model.UserProjects)
                            {
                                    <a class="dropdown-item text-dark" asp-area="" asp-page="/Category Display/Index" asp-route-projectId="@p.Id">@p.productName</a>
                            }
                            </div>
                            
                        </li>

But _Layout.cshtml lacks a model or something similar.


Trying to add my class:

public class LayoutModel : PageModel
    {

        private readonly ApplicationDbContext _db;

        public List<UserProject> UserProjects { get; set; }

        public LayoutModel(ApplicationDbContext db)
        {
            _db = db;
        }

        public async Task OnGet(int categoryId)
        {


            UserProjects = await _db.UserProject.ToListAsync();

        }


    }

By adding @model LayoutModel to the top of the layout file results in an error:

InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'Scratch.Pages.IndexModel', but this ViewDataDictionary instance requires a model item of type 'Scratch.Pages.Shared.LayoutModel'.

How do I go about this?


Solution

  • I think you can use View Component to achieve it. Please refer to this simple demo:

    Create a component class:

    public class ShowViewComponent : ViewComponent
        {
            //you can inject db into view component
            private readonly ApplicationDbContext _db;
            
            public List<UserProject> UserProjects { get; set; }
    
            public ShowViewComponent(ApplicationDbContext db)
            {
               _db = db;
    
            }
            public IViewComponentResult Invoke()
            {
               
                //UserProjects = await _db.UserProject.ToListAsync();
                //return View(UserProjects );
                //for testing, I just hard code here.
    
                   List<string> list = new List<string>();
                list.Add("AAA");
                list.Add("BBB");
                list.Add("ccc");
    
                
                return View(list);
            }
        }
    

    Then you need to create a component view, Please note that the path of component view should be :

    Pages\Shared\Components\{your view component's name}\Default.cshtml
    

    So here my path is :

    Pages\Shared\Components\Show\Default.cshtml
    

    View

    @model List<string>
    
    <table class="table table-bordered">
        @foreach (var item in Model)
        {
            <h1>@item</h1>
        }
    </table>
    

    Finally, I need to use this view component in _Layout.cshtml:

    <div>
            @await Component.InvokeAsync("Show");
    </div>
    

    Demo:

    enter image description here