简体   繁体   中英

Get Data From Database From MVC Shared View

I have a shared _Layout.cshtml where I call the following @Html.Partial("TopMenu");
in TopMenu.cshtml I have an markup for website top menu.

<ul class="menu">
         <li class="menu-item"><a href="#">menu item 1</a></li>
         <li class="menu-item"><a href="#">menu item 2</a></li>
         <li class="menu-item"><a href="#">menu item 3</a></li>
         <li class="menu-item"><a href="#">menu item 4</a></li>
</ul>

I want to bind that menu from database. I'm new to MVC. Should I create controller for that view?

This menu should be present in all of my pages. Give me an idea, how it's implemented in mvc. I'm from asp.net web forms country.

FUNCTION

public IEnumerable<Category> GetCategories(Guid? id)
{
    return context.Categories.Where(c => c.CategoryID == id || !id.HasValue).ToList();
}

UPDATE

public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }


        public PartialViewResult TopMenu()
        {
            using (var ctx = new eventzEntities())
            {
                CategoryManager catMan = new CategoryManager(ctx);
                var listOfCat = catMan.GetCategories(null);

                return PartialView(listOfCat);
            }
        }
    }

AND

@Html.Action("TopMenu","Home")
<div class="secondary-navigation">
    <nav id="navigation">
        <ul id="menu-main-navigation" class="menu sf-js-enabled">
            @foreach (var cat in Model)
            {
                <li class="menu-item menu-item-type-taxonomy menu-item-object-category ">
                    <a href="#">@cat.CategoryName</a>
                </li>
            }

...

Since all your views/pages will require this I suggest you create a base controller which will fetch the menu structure from the database and then provided it to all of your inheriting controllers. So for example you will make a base controller like this:

public class BaseController : Controller
{
    public MenuModel Menu { get; set; }

    protected override void Initialize(RequestContext requestContext)
    {
        // This get's your menu structure from the database via some service layer you need to create yourself.
        // Keep in mind that this call will happen on every postback so if performance is an issue you might want to cache the menu in some way, maybe per user.
        Menu = _menuServiceLogic.GetMenuItems();
        ViewBag.Menu = Menu;
    }

Once you have this then all your controller which generate views that contain the menu need to inherit from this base controller:

 public class HomeController : BaseController
 {
     // Controller logic in here...
 }

so now you have access to the menu on all of your controllers so all that is left is to pass it on to the view in some good way. I suggest you look into how to make a custom razor view class. There is a great article by Phil Haacked on this topic:

http://haacked.com/archive/2011/02/21/changing-base-type-of-a-razor-view.aspx

But in short every Razor view by default inherits from the System.Web.Mvc.WebViewPage. We are going to replace that class with our own implementation:

namespace YourApp.Website.Views
{
   public abstract class CustomWebViewPage : WebViewPage
   {
      private MenuModel _menu;

      public MenuModel Menu
      {
         get
         {
            try
            {
                _menu = (MenuModel)ViewBag.Menu;
            }
            catch (Exception)
            {
                _menu = null;
            }
            return _menu;
         }
      }
   }

   public abstract class CustomWebViewPage<TModel> : WebViewPage<TModel> where TModel : class
   {
      private MenuModel _menu;

      public MenuModel Menu
      {
         get
         {
            try
            {
                _menu = (MenuModel)ViewBag.Menu;
            }
            catch (Exception)
            {
                _menu = null;
            }
            return _menu;
         }
      }
   }
}

Now all you need to do is modify this line in your web.config:

<pages pageBaseType="System.Web.Mvc.WebViewPage">

to this:

<pages pageBaseType="YourApp.Website.Views.CustomWebViewPage">

and you can now do the following in your views in order to reference your menu:

@Menu

The Menu variable is strongly typed (in my example it's of type MenuModel) and you can access all the properties of your menu on every controller actions/views that inherits from your base controller.

You can do this by passing strongly typed model to the partial view _TopMenu

@model IEnumerable<Category>

<ul class="menu">
@foreach(var category in Model)
{
   <li class="menu-item"><a href="#">@category.Category.Name</a></li>
}
</ul>

How to pass?

You will simply do it as below:

  @Html.Action("TopMenu","ControllerName")

Here, controllerName is the name of the controller where you have defined this method. I recommend you keeping this controller away from other controllers. You can simply call it as a PageController or something.

Have no idea how it should work?

You will define a controller method that returns the partial view with strongly typed model as below:

public ActionResult TopMenu()
{
   return PartialView(db.Categories.ToList());
}

You need to make sure the menu is a partial view then call

@Html.Partial("location/to/view", modeL)

and then in the view code it should be

@model someDataModel.Models.Thing
<ul class="menu">
         <li class="menu-item"><a href="#">@Model.item1</a></li>
         <li class="menu-item"><a href="#">@Model.item2</a></li>
         <l

i class="menu-item">@Model.item3 @Model.item4

A good tutorial for this can be found here http://mvc4beginner.com/Tutorial/MVC-Partial-Views.html

You do not need a controller necessarily for a partial view.

If you want that TopMenu to be a view then you need to get a controller made for that

You can store your menu items in a ViewBag and access it in your view.

So in your controller you will have this :

ViewBag.Menus = ...

And in your TopMenu.cshtml

<ul class="menu">
    @foreach(string menu in ViewBag.Menus){
         <li class="menu-item"><a href="#">@menu</a></li>
    }
</ul>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM