How To Call Controller from Layout Html.Partial

2019-09-06 12:41发布

问题:

I'm working with Asp.net MVC 4, engine razor. I am developing an application and the menu is dynamically created by the user's role

UPDATE In my application I need the user to enter their credentials with these recovered data on user role and build the dynamic menu for the role. My main screen is:

in my _Layout.cshtml I have this code:

@if (Request.IsAuthenticated){
        Html.Partial("Menu");
    } else { 
        <div class="sectiontitle">&nbsp;</div>
    }

I create a base controller:

public class BaseController : Controller
{
    public BaseController(){
        ViewBag.Menu = BuildMenu();
    }

    private IList<Models.AdmMenu> BuildMenu()
    {      
            IList<Models.AdmMenu> mmList = new List<Models.AdmMenu>(){
            new Models.AdmMenu(){ Id = 1, Name = "Home", ParentId = 0, SortOrder = 1} ,
            new Models.AdmMenu(){ Id = 2, Name = "Admin", ParentId = 0, SortOrder = 1},
            new Models.AdmMenu(){ Id = 3, Name = "Account", ParentId = 0, SortOrder = 1},
            .....
            .....

And in my controller raLoginController.cs I have this:

public class raLoginController : BaseController{                
    [HttpPost]
    public ActionResult Login(Models.AdmLogin login){
        if (ModelState.IsValid){
            Servicio.cSeReclamo Servicio = new Servicio.cSeReclamo(login.UserName, login.Password);
            if (Servicio.ValidarUsuario()){
                string Mensaje = "";
                Models.AdmUsuario oAdmUsuario = new Models.AdmUsuario();
                oAdmUsuario.Au_codusuario = login.UserName;
                Servicio.RetornaEntidad<Models.AdmUsuario>(ref Mensaje, "admsis.adm_usuario", oAdmUsuario.getPk(), oAdmUsuario);                                      
                FormsAuthentication.SetAuthCookie(login.UserName, false);  

                var ticket = new FormsAuthenticationTicket(1,
                    login.UserName,
                    DateTime.Now,
                    DateTime.Now.AddMinutes(30),
                    false,
                    LoadData(oAdmUsuario,Servicio.Pais(ref Mensaje))
                );

                string encTicket = FormsAuthentication.Encrypt(ticket);
                HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);

                if (ticket.IsPersistent) {
                    faCookie.Expires = ticket.Expiration;
                }
                Response.Cookies.Add(faCookie);
                return RedirectToAction("index", "raMainReclamo", new { area = "Reclamos"});
            }
        }
        return View(login);
    }

In Menu.cshtml (Partial View)

 @{
    List<Crd.Web.Models.AdmMenu> menuList = ViewBag.Menu;       
}
<div class="sectiontitle">     
<ul class="menu" id="header">  
    @foreach (var mp in menuList.Where(p => p.ParentId == 0))
    {    
        <li><a href="#">@mp.Name</a> 
        @if (menuList.Count(p => p.ParentId == mp.Id) > 0)
        {
            @:<ul>
        }          
        @RenderMenuItem(menuList, mp)       
        @if (menuList.Count(p => p.ParentId == mp.Id) > 0)
        {
            @:</ul>
        }       
        </li>
    }
</ul>   
</div> 

But when I enter the credentials have the following error:

menulist is equal a null, why? I am following the code step by step, enters BaseController and execute BuildMenu method... why null? I have this message:

How to resolve this problem?

回答1:

You can call a controller action by using

@Html.Action("Action", "Controller")

Your controller action can do the

Session["Menu"] == null

check and load it if necessary. Then return a partial with

return PartialView("_Partial");

The nice thing about using this approach is it will allow you to get the code of checking for Session["Menu"] out of your layout page.

I'm not exactly sure if this will help; please clarify your question further, if necessary.



回答2:

There is no point to store result of Html.Partial action (which is MvcHtmlString) into Session. Just create MenuController with method e.g. CreateForRole and call:

@{Html.RenderAction("CreateForRole","Menu")}

This method should return view valid for logged role. If you do now want to re-create menu on every call (which you should - imagine your user is granted by additional roles without logging out) and you really need to persist this call, use caching with role as parameter instead.