c# MVC5 What is the right place to load menu items

asp.net-mvc c# entity-framework-6 razor

Question

I have a little problem, could you explain me what is the best practice to load menu items from DB using MVC5 and Entity Framework6. The menu and localization object must be loaded only once, and then just used from some globally available collection. They are not going to change alot after website launch, so I just goung to implement some Update() method and I'll call it when necessary...

1
1
4/29/2015 5:56:46 PM

Accepted Answer

As i have already sad, I have thinked about Global.asax So there is currently 2 ways how I can do it with Global.asax:

Update using this method is bad idea, use the second one instead

public static ICollection<MenuItem> MenuItems {
    get
    {
        if (Application["MenuItems"] != null)
            return (ICollection<MenuItems>)Application["MenuItems"];
        else
            return new ICollection<MenuItems>();
    }
    set
    {
        Application["MenuItems"] = value;    
    }
}

private void LoadMenuItems()
{
    MyContext mc = new MyContext();
    this.MenuItems = ms.MenuItems.Include("SubCategories").AsNotTacking().where(x => x.SubCategory == null).ToArray();
} 

protected void Application_Start(object sender, EventArgs e)
{
    this.MenuItems = LoadMenuItems();
}

And another way (The second one):

public static ICollection<MenuItem> MenuItems { get; set; }

private void LoadMenuItems()
{
    MyContext mc = new MyContext();
    this.MenuItems = ms.MenuItems.Include("SubCategories").AsNotTacking().where(x => x.SubCategory == null).ToArray();
} 

protected void Application_Start(object sender, EventArgs e)
{
    this.MenuItems = LoadMenuItems();
}

And same thing for Localization...

Actually i dont know which one is better, need to run some tests.

Almost forgot: All the things, are contained in the "CustomHttpApplication" class, which is derrived from "HttpApplication" class. and Global.asax shoul be derived from "CustomHttpApplication" class. This way the Global.asax file will be cean and readable, but the business logic will be located one level down...

So the complete code could look like so:

CustomHttpApplication.cs

public class CustomHttpApplication : HttpApplication
{
    public static ICollection<MenuItem> MenuItems { get; set; }

    private void LoadMenuItems()
    {
        MyContext mc = new MyContext();
        this.MenuItems = ms.MenuItems.Include("SubCategories").AsNotTacking().where(x => x.SubCategory == null).ToArray();
    } 
}

Global.asax.cs

public class MvcApplication : CustomHttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        MenuItems = this.LoadMenuItems();
    }
}

And one more edit, if you/me convert the "LoadMenuItems" method to be a "static" one, than you/me will be able to update MenuItems and/or Localization item collections when needed.

1
4/30/2015 9:13:52 AM

Popular Answer

Use child actions.

public class FooController : Controller
{
    ...

    [ChildActionOnly]
    public ActionResult SiteMenu()
    {
        // load menu items however you need to

        return PartialView("_SiteMenu", menuModel);
    }
}

/Views/Shared/_SiteMenu.cshtml

@model Namespace.To.MenuModel

<!-- render your menu here -->

/Views/Shared/_Layout.cshtml

<!-- wherever you want the menu to display -->
@Html.Action("SiteMenu", "Foo")

If you want to cache the result, so the menu doesn't have to be pulled from the DB each request, then you can use the OutputCache attribute on the child action like any other action.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow