Asp.net mvc 从局部视图调用动态菜单

Asp.net mvc 从局部视图调用动态菜单,asp.net-mvc,Asp.net Mvc,我的网络应用程序有一个菜单系统,模仿保罗·谢里夫的课程,效果很好。我希望通过为每个订户级别以及管理员提供特定的菜单来增强其可用性。我的意图是创建一个局部视图,该视图将注入菜单html,该html从MenuController中的代码派生,MenuController从服务库调用MenuUservice中的方法 这样做对吗?我是MVC的新手,过去一直在使用webforms。如果我从布局页面中删除菜单html,那么带有新菜单代码的partialview如何调用?一旦登录的用户登录并且应用程序知道需要

我的网络应用程序有一个菜单系统,模仿保罗·谢里夫的课程,效果很好。我希望通过为每个订户级别以及管理员提供特定的菜单来增强其可用性。我的意图是创建一个局部视图,该视图将注入菜单html,该html从MenuController中的代码派生,MenuController从服务库调用MenuUservice中的方法


这样做对吗?我是MVC的新手,过去一直在使用webforms。如果我从布局页面中删除菜单html,那么带有新菜单代码的partialview如何调用?一旦登录的用户登录并且应用程序知道需要什么菜单,是否有办法缓存该布局,这样就不必在每个页面请求中创建菜单?

如果我对您的案例的假设是正确的,那么您就在正确的轨道上了。MVC就是这样使用的

补充Chris Pratt的回答:

[ChildActionOnly]
public ActionResult GetMenu()
{
    // fetch user, subscriber levels, etc.
    return PartialView("_Menu", model);
}
您可能希望使用
[ChildActionOnly]
阻止服务器处理此操作方法,因为它响应了客户端请求。使用此属性,当使用其他视图请求局部视图时,将呈现局部视图

假设您有一个partial view SubMenu.cshtml,那么在主菜单视图或Layout.cshtml中,您将有
@Html.RenderPartial(“Path\u To\u SubMenu\u view”)

关于缓存,以下是本文的摘录:

在ASP.NET MVC中,缓存完整呈现页面的更简单方法是使用OutputCacheAttribute,如下所示:

[Authorize]
public class DashboardController : Controller 
{
    [OutputCache(Duration = 3600)]
    public ActionResult Index() 
    {
       // Your awesome code goes here
    }
}
前面的代码将使索引操作在缓存中停留一小时。这对于公共内容非常有效,但对于特定于用户的内容,必须补充缓存键,以便不同的用户看不到彼此的缓存

为此,我们使用OutputCacheAttribute的VaryByCustom属性,如下所示:

[Authorize]
public class DashboardController : Controller 
{
    [OutputCache(Duration = 3600, VaryByCustom = "User")]
    public ActionResult Index() 
    {
       // Your awesome code goes here
    }
}
您还需要在通过HttpApplication调用的方法中处理该“用户”值:GetVaryByCustomString方法。 因此,您需要转到Global.asax.cs并覆盖该方法:

public override string GetVaryByCustomString(HttpContext context, string arg) 
{ 
    if (arg.Equals("User", StringComparison.InvariantCultureIgnoreCase)) 
    {
        var user = context.User.Identity.Name; // TODO here you have to pick an unique identifier from the current user identity
        return string.Format("{0}@{1}", userIdentifier.Name, userIdentifier.Container); 
    }

    return base.GetVaryByCustomString(context, arg); 
}
或者,如果未在管道中设置自定义主体,则可以按如下方式查找会话id:

private static SessionStateSection SessionStateSection = (System.Web.Configuration.SessionStateSection)ConfigurationManager.GetSection("system.web/sessionState");

public override string GetVaryByCustomString(HttpContext context, string arg) 
{ 
    if (arg.Equals("User", StringComparison.InvariantCultureIgnoreCase)) 
    {
        var cookieName =  SessionStateSection.CookieName;
        var cookie = context.Request.Cookies[cookieName];
        return cookie.Value;
    }

    return base.GetVaryByCustomString(context, arg); 
}

我正在使用会话状态配置部分来获取会话cookie名称,这样,如果您更改了默认的“ASP.NET_SessionId”,它仍然可以工作。

如果我对您的案例的假设是正确的,那么您就在正确的轨道上了。MVC就是这样使用的

补充Chris Pratt的回答:

[ChildActionOnly]
public ActionResult GetMenu()
{
    // fetch user, subscriber levels, etc.
    return PartialView("_Menu", model);
}
您可能希望使用
[ChildActionOnly]
阻止服务器处理此操作方法,因为它响应了客户端请求。使用此属性,当使用其他视图请求局部视图时,将呈现局部视图

假设您有一个partial view SubMenu.cshtml,那么在主菜单视图或Layout.cshtml中,您将有
@Html.RenderPartial(“Path\u To\u SubMenu\u view”)

关于缓存,以下是本文的摘录:

在ASP.NET MVC中,缓存完整呈现页面的更简单方法是使用OutputCacheAttribute,如下所示:

[Authorize]
public class DashboardController : Controller 
{
    [OutputCache(Duration = 3600)]
    public ActionResult Index() 
    {
       // Your awesome code goes here
    }
}
前面的代码将使索引操作在缓存中停留一小时。这对于公共内容非常有效,但对于特定于用户的内容,必须补充缓存键,以便不同的用户看不到彼此的缓存

为此,我们使用OutputCacheAttribute的VaryByCustom属性,如下所示:

[Authorize]
public class DashboardController : Controller 
{
    [OutputCache(Duration = 3600, VaryByCustom = "User")]
    public ActionResult Index() 
    {
       // Your awesome code goes here
    }
}
您还需要在通过HttpApplication调用的方法中处理该“用户”值:GetVaryByCustomString方法。 因此,您需要转到Global.asax.cs并覆盖该方法:

public override string GetVaryByCustomString(HttpContext context, string arg) 
{ 
    if (arg.Equals("User", StringComparison.InvariantCultureIgnoreCase)) 
    {
        var user = context.User.Identity.Name; // TODO here you have to pick an unique identifier from the current user identity
        return string.Format("{0}@{1}", userIdentifier.Name, userIdentifier.Container); 
    }

    return base.GetVaryByCustomString(context, arg); 
}
或者,如果未在管道中设置自定义主体,则可以按如下方式查找会话id:

private static SessionStateSection SessionStateSection = (System.Web.Configuration.SessionStateSection)ConfigurationManager.GetSection("system.web/sessionState");

public override string GetVaryByCustomString(HttpContext context, string arg) 
{ 
    if (arg.Equals("User", StringComparison.InvariantCultureIgnoreCase)) 
    {
        var cookieName =  SessionStateSection.CookieName;
        var cookie = context.Request.Cookies[cookieName];
        return cookie.Value;
    }

    return base.GetVaryByCustomString(context, arg); 
}

我正在使用会话状态配置部分来获取会话cookie名称,因此,如果您更改了默认的“ASP.NET_SessionId”,它仍然可以工作。

您需要利用子操作:

[Authorize]
public class FooController : Controller
{
    ...

    [AllowAnonymous]
    [ChildActionOnly]
    public ActionResult GetMenu()
    {
        // fetch user, subscriber levels, etc.
        return PartialView("_Menu", model);
    }
}
然后,创建视图,
Views\Foo\\u Menu.cshtml
,并利用模型中的数据确定要显示的菜单。最后,在布局中,在希望菜单出现的位置添加以下内容:

@Html.Action("GetMenu", "Foo")
要缓存结果,您可以使用
[OutputCache]
修饰子操作,但您需要根据登录用户的不同对其进行更改,以便为每个用户单独缓存,而不是在多个用户之间共享。但是,输出缓存没有内置的随用户而异的功能,所以您必须实现自己的功能

在Global.asax中,添加以下内容:

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg == "user")
    {
        return context.User.Identity.Name;
    }
    return string.Empty;
}
然后,添加输出缓存,如下所示:

[OutputCache(Duration = 3600, VaryByCustom = "user")]
public ActionResult GetMenu()
注:

  • FooController
    可以是您喜欢的任何控制器
  • 如果控制器未使用
    [Authorize]
    修饰,则需要执行子操作。否则,您将无法访问用户主体。但是,在布局中使用子操作时,必须允许匿名访问。否则,您将在任何匿名页面(如登录和注册)上获得无限重定向

  • 您需要利用子操作:

    [Authorize]
    public class FooController : Controller
    {
        ...
    
        [AllowAnonymous]
        [ChildActionOnly]
        public ActionResult GetMenu()
        {
            // fetch user, subscriber levels, etc.
            return PartialView("_Menu", model);
        }
    }
    
    然后,创建视图,
    Views\Foo\\u Menu.cshtml
    ,并利用模型中的数据确定要显示的菜单。最后,在布局中,在希望菜单出现的位置添加以下内容:

    @Html.Action("GetMenu", "Foo")
    
    要缓存结果,您可以使用
    [OutputCache]
    修饰子操作,但您需要根据登录用户的不同对其进行更改,以便为每个用户单独缓存,而不是在多个用户之间共享。但是,输出缓存没有内置的随用户而异的功能,所以您必须实现自己的功能

    在Global.asax中,添加以下内容:

    public override string GetVaryByCustomString(HttpContext context, string arg)
    {
        if (arg == "user")
        {
            return context.User.Identity.Name;
        }
        return string.Empty;
    }
    
    然后,添加输出缓存,如下所示:

    [OutputCache(Duration = 3600, VaryByCustom = "user")]
    public ActionResult GetMenu()
    
    注:

  • FooController
    可以是您喜欢的任何控制器
  • 如果控制器未使用
    [Authorize]
    修饰,则需要执行子操作。否则,您将无法访问用户princi