locked
Getting data from DB in Layout Pages RRS feed

  • Question

  • User1153554953 posted

    Hello,

    I have a web app in asp.net core mvc, I want to add data generated from database to the sidebar and footer of the website which is available in the shared layout pages, the thing that is confusing me is how can I implement this? How will be the controller implemented? Kindly give me a hint about this. Thanks

    Wednesday, October 14, 2020 5:07 PM

Answers

  • User1312693872 posted

    Hi,najum98

    I want to add data generated from database to the sidebar and footer of the website which is available in the shared layout pages

    I recommend you use ViewComponent. As Creating a view Component  said, create a class whose suffix is ViewComponent, then you can write your logic such as get data from database in it. And the component's view in some paths like   '/Views/Shared/Components/{View Component Name}/{View Name} ' (you can change it depends on your needs, ways are in the tutorial).

    After creating the cs and the view, you can call the ViewComponent in _Layout.cshtml by adding the following code in _Layout.cshtml:

    ......
    @await Component.InvokeAsync("ShowDB") @*this is my component's name ,I used it as the title*@
    ......  

    Following is my demo:

    My 'ViewComponent' cs:

    public class ShowDB : ViewComponent
        {
            private readonly MyDbContext db;
    
            public ShowDB(MyDbContext context)
            {
                db = context;
            }
    
            public async Task<IViewComponentResult> InvokeAsync()
            {
                var items =db.MyModels
                    .ToList();
                return View("Default",items);
            }
        }

    ViewComponent View (named 'Default'):

    @model IEnumerable<MyModel>
    
    @foreach (var item in Model)
    {
        @item.Name
    }

    File structure:

    Result:

    Best Regards,

    Jerry Cai

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, October 15, 2020 6:41 AM

All replies

  • User-474980206 posted

    as every controller action needs to do the lookup, you could use an attribute on the caller or action to specify the lookups required, then you middleware to do the lookup and and to the ViewBag

    Wednesday, October 14, 2020 6:20 PM
  • User1153554953 posted

    as every controller action needs to do the lookup, you could use an attribute on the caller or action to specify the lookups required, then you middleware to do the lookup and and to the ViewBag

    I am really sorry I didn't get you, please be a bit more explicit.

    Wednesday, October 14, 2020 6:24 PM
  • User475983607 posted

    Learn view components.  View components are designed to solve this type of programming problem. 

    https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-3.1

    https://www.learnrazorpages.com/razor-pages/view-components

    Wednesday, October 14, 2020 6:44 PM
  • User1312693872 posted

    Hi,najum98

    I want to add data generated from database to the sidebar and footer of the website which is available in the shared layout pages

    I recommend you use ViewComponent. As Creating a view Component  said, create a class whose suffix is ViewComponent, then you can write your logic such as get data from database in it. And the component's view in some paths like   '/Views/Shared/Components/{View Component Name}/{View Name} ' (you can change it depends on your needs, ways are in the tutorial).

    After creating the cs and the view, you can call the ViewComponent in _Layout.cshtml by adding the following code in _Layout.cshtml:

    ......
    @await Component.InvokeAsync("ShowDB") @*this is my component's name ,I used it as the title*@
    ......  

    Following is my demo:

    My 'ViewComponent' cs:

    public class ShowDB : ViewComponent
        {
            private readonly MyDbContext db;
    
            public ShowDB(MyDbContext context)
            {
                db = context;
            }
    
            public async Task<IViewComponentResult> InvokeAsync()
            {
                var items =db.MyModels
                    .ToList();
                return View("Default",items);
            }
        }

    ViewComponent View (named 'Default'):

    @model IEnumerable<MyModel>
    
    @foreach (var item in Model)
    {
        @item.Name
    }

    File structure:

    Result:

    Best Regards,

    Jerry Cai

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, October 15, 2020 6:41 AM
  • User1153554953 posted

    Hi,najum98

    najum98

    I want to add data generated from database to the sidebar and footer of the website which is available in the shared layout pages

    I recommend you use ViewComponent. As Creating a view Component  said, create a class whose suffix is ViewComponent, then you can write your logic such as get data from database in it. And the component's view in some paths like   '/Views/Shared/Components/{View Component Name}/{View Name} ' (you can change it depends on your needs, ways are in the tutorial).

    After creating the cs and the view, you can call the ViewComponent in _Layout.cshtml by adding the following code in _Layout.cshtml:

    ......
    @await Component.InvokeAsync("ShowDB")    @*this is my component's name ,I used it as the title*@
    ......   

    Following is my demo:

    My 'ViewComponent' cs:

    public class ShowDB : ViewComponent
        {
            private readonly MyDbContext db;
    
            public ShowDB(MyDbContext context)
            {
                db = context;
            }
    
            public async Task<IViewComponentResult> InvokeAsync()
            {
                var items =db.MyModels
                    .ToList();
                return View("Default",items);
            }
        }

    ViewComponent View (named 'Default'):

    @model IEnumerable<MyModel>
    
    @foreach (var item in Model)
    {
        @item.Name
    }

    File structure:

    Result:

    Best Regards,

    Jerry Cai

    Thank you so much Jerry! I am sure that this is the right answer. Will try it soon. Thanks again

    Thursday, October 15, 2020 1:45 PM
  • User1153554953 posted

    Jerry Cai

    Hi,najum98

    najum98

    I want to add data generated from database to the sidebar and footer of the website which is available in the shared layout pages

    I recommend you use ViewComponent. As Creating a view Component  said, create a class whose suffix is ViewComponent, then you can write your logic such as get data from database in it. And the component's view in some paths like   '/Views/Shared/Components/{View Component Name}/{View Name} ' (you can change it depends on your needs, ways are in the tutorial).

    After creating the cs and the view, you can call the ViewComponent in _Layout.cshtml by adding the following code in _Layout.cshtml:

    ......
    @await Component.InvokeAsync("ShowDB")    @*this is my component's name ,I used it as the title*@
    ......   

    Following is my demo:

    My 'ViewComponent' cs:

    public class ShowDB : ViewComponent
        {
            private readonly MyDbContext db;
    
            public ShowDB(MyDbContext context)
            {
                db = context;
            }
    
            public async Task<IViewComponentResult> InvokeAsync()
            {
                var items =db.MyModels
                    .ToList();
                return View("Default",items);
            }
        }

    ViewComponent View (named 'Default'):

    @model IEnumerable<MyModel>
    
    @foreach (var item in Model)
    {
        @item.Name
    }

    File structure:

    Result:

    Best Regards,

    Jerry Cai

    Hello, I have a question, what if I want to add multiple components under single ViewComponent class? I want to invoke different sections of a page, let's say footer and sidebar. Is there any way to use the same class for two different components or render different portions of layout using the same component? Thanks

    Monday, October 19, 2020 4:33 PM
  • User1312693872 posted

    Hi, najum98

    If '_Layout' is your component view, why you call the '@await Component.InvokeAsync("ShowAds")' to show the component view in  your component view '_Layout' again? It will cause the loop. 

    In summary, you can't call '@await Component.InvokeAsync("ShowAds")' in your component view.

    Best Regards,

    Jerry Cai

    Tuesday, October 20, 2020 1:37 AM
  • User1153554953 posted

    Hi, najum98

    If '_Layout' is your component view, why you call the '@await Component.InvokeAsync("ShowAds")' to show the component view in  your component view '_Layout' again? It will cause the loop. 

    In summary, you can't call '@await Component.InvokeAsync("ShowAds")' in your component view.

    Best Regards,

    Jerry Cai

    Sorry it was all my fault, I have edited my last post with another question, kindly check that.

    Tuesday, October 20, 2020 1:46 AM
  • User1312693872 posted

    Hi,najum98

    You can give a parameter to component class like this:

    public async Task<IViewComponentResult> InvokeAsync(int id)
            {
                if (id == 1)
                {
                    var items = db.MyModels
                        .ToList();
                    return View("_Layout", items);
                }
    
                    var items2 = db.MyModels
                        .ToList();
                    return View("Default", items2);
            }

    Then call the class with different parameter:

    @await Component.InvokeAsync("ShowDB", 1)
    @await Component.InvokeAsync("ShowDB")

    Best Regards,

    Jerry Cai

    Tuesday, October 20, 2020 2:04 AM
  • User1153554953 posted

    Hi,najum98

    You can give a parameter to component class like this:

    public async Task<IViewComponentResult> InvokeAsync(int id)
            {
                if (id == 1)
                {
                    var items = db.MyModels
                        .ToList();
                    return View("_Layout", items);
                }
    
                    var items2 = db.MyModels
                        .ToList();
                    return View("Default", items2);
            }

    Then call the class with different parameter:

    @await Component.InvokeAsync("ShowDB", 1)
    @await Component.InvokeAsync("ShowDB")

    Best Regards,

    Jerry Cai

    Oh thank you so much again, you've been very helpful. Kudos to you

    Tuesday, October 20, 2020 2:14 AM