首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用强类型视图的上下文敏感的ASP.NET MVC导航菜单?

问使用强类型视图的上下文敏感的ASP.NET MVC导航菜单?
EN

Stack Overflow用户
提问于 2009-07-26 03:15:31
回答 2查看 1.5K关注 0票数 1

我正在尝试找出在ASP.NET MVC中创建导航菜单的最佳方法,该导航菜单可以根据构建它的控制器操作进行更改(它也会根据用户权限等而有所不同)。导航菜单显示在母版页中,并且我们所有的视图都是强类型的。

我想在一个基本控制器中使用OnActionExecuting来填充标准菜单,然后在每个控制器操作中相应地修改它。但是,这似乎不是一个选项,因为视图模型在调用我的操作之前是不可用的。

我能想到的另一件事就是在基本的ViewModel构造函数中预先填充menu对象。然后我可以在我的控制器操作中根据需要添加/删除。不过,这似乎并不完全合适,因为我需要在ViewModel构造函数中实例化回控制器操作的链接(因为每个菜单项都可以有一个控制器/操作/id)。

有什么建议是最好的方法吗?特别是对于基于上下文而显著改变的导航菜单(或可能的树视图)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-11-04 06:53:50

我使用MasterModel来处理这类事情。

在我看来,.aspx和它的.master是可分离的(例如,你可以在渲染aspx的时候换掉母版;而且aspx不是从母版继承的,它只使用母版),因此视图模型也应该是分开的。(即PageModel不应从MasterModel继承。)

aspx可能只关心接收,比方说,一个IEnumerable,为什么它的视图模型要继承一些公共类?

因此,不是:

代码语言:javascript
复制
public class MasterModel
{
    public string Title { get; set; }
    public MenuModel Menu { get; set; }
}

public class PageViewModel
    : MasterModel
{
    public IEnumerable<Foo> TheOnlyThingInTheWorldMyPageReallyCaresAbout { get; set; }
}

public ActionResult TheAction()
{
    var items = GetItems();
    var model = new PageViewModel {
        TheOnlyThingInTheWorldMyPageReallyCaresAbout = items
    };
    return view("Viewname", model);
}

我使用:

代码语言:javascript
复制
public class BaseController
    : Controller
{
    protected MasterModel MasterModel
    {
        get { return ViewData["MasterModel"] as MasterModel; }
        set { ViewData["MasterModel"] = value; }
    }
}

public class MasterModel
{
    public MasterModel()
    {
        // Sensible defaults
    }
    
    public string Title { get; set; }
    public MenuModel Menu { get; set; }
}

public ActionResult TheAction()
{
    var items = GetItems();
    
    // Prepare the MasterModel as part of the controller's "select and prepare the view" responsibility.
    // Common cases can be factored into ActionFilter attributes or to a base Controller class.
    MasterModel = new MasterModel();
    return view("Viewname", items);
}

然后,您可以将此代码添加到母版页中:

代码语言:javascript
复制
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>

<script runat="server">
    public MasterModel Model { get { return ViewData["MasterModel"] as MasterModel; } }
</script>

现在,您不必对页面视图模型执行任何特殊操作。他们可以只关心他们应该关心的事情。

为什么所有这些转弯抹角的东西都很有趣?

我想在一个基本控制器中使用OnActionExecuting来填充标准菜单,然后在每个控制器操作中相应地修改它。但是,这似乎不是一个选项,因为视图模型在调用我的操作之前是不可用的。

我能想到的另一件事就是在基本的ViewModel构造函数中预先填充menu对象。然后我可以在我的控制器操作中根据需要添加/删除。不过,这似乎并不完全合适,因为我需要在ViewModel构造函数中实例化回控制器操作的链接(因为每个菜单项都可以有一个控制器/操作/id)。

现在很容易做到这些,独立于你的页面视图模型:

代码语言:javascript
复制
MasterModel = this.DefaultMasterModel();

// -- or --

MasterModel = this.DefaultMasterModel();
this.AlterMenu(MasterModel.Menu);

// -- or --

MasterModel = new MasterModel();
MasterModel.Menu = this.SpecialReplacementMenu();

// -- or --

MasterModel = new NestedMasterModel();

// -- or -- 

public class FlyingPigAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var viewResult = filterContext.Result as ViewResult;

        if (viewResult!=null)
        {
            var masterModel = viewResult.ViewData["MasterModel"] as MasterModel;
            MakePigsFly(masterModel);
        }
    }
}    

虽然没有给出一个具体的解决方案,但这是否为您提供了如何重构代码以使其看起来更好的选择?

票数 1
EN

Stack Overflow用户

发布于 2009-07-26 08:19:16

MvcContrib中的SubControllers似乎是您问题的合适解决方案。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1183640

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档