【问题标题】:MVC Areas & Shared LayoutsMVC 区域和共享布局
【发布时间】:2017-04-11 13:28:52
【问题描述】:

希望我能说清楚。我的 mvc 项目中有一个区域有两个共享布局 _Application.cshtml(适用于区域)_Layout.cshtml(适用于非区域)

报告和收藏夹适用于区域控制器。
角色和用户用于默认命名空间控制器。

<li>@Html.ActionLink("Reports", "Reports", "Home")</li>
<li>@Html.ActionLink("Favourites", "Favourites", "Home")</li>
<li>@Html.ActionLink("System Roles", "Roles", "Support",new { Area = "" },  htmlAttributes: new { title = "System Roles" }) </li>
<li>@Html.ActionLink("Users", "Users", "Support", new { Area = "" },   htmlAttributes: new { title = "Users" })</li>

在角色和用户视图中定义 我正在定义不同的共享布局。没有指向报告和收藏夹的链接(只是完全不同的导航菜单)。

是否可以将角色和用户的布局分配给我的 _Application 共享布局,而不会失去从默认命名空间控制器调用操作的能力?

if (this.ViewContext.RouteData.DataTokens["Area"] != null)    {
    Layout = "~/Views/Shared/_Application.cshtml";
}
else
{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

我已经尝试过了,但是 DataToken 从来没有收到过 Area 路由,因为它没有被定义。

编辑:抱歉,我无法描述这个问题(即使与同事也是如此......)

区域“采购”:控制器:“主页”具有索引、报告和收藏夹三个视图。导航菜单 (_Applicaiton.cshtml) 仅适用于采购区

非区域:控制器“支持”有两个视图角色和用户。导航菜单 (_Layout.cshtml) 是通用的,包含导航到项目其他区域的链接

上面的操作链接位于索引视图中。如果我单击报告或收藏夹,它将导航到 ApplicationName/Procurement/Home/Reports 或 ApplicationName/Procurement/Home/Favourites

如果我单击角色或用户,它会将我导航到 ApplicationName/Support/Roles 或 ApplicationName/SupportUsers

由于我为角色和用户定义布局的方式,导航菜单默认返回到通用菜单,而不是显示特定于采购区域的菜单。

我正在寻找当我单击导航菜单的角色或用户时是否有可能停留在采购布局上并引用相同的支持控制器。我不想为我正在创建的每个区域创建角色和用户页面。

【问题讨论】:

    标签: asp.net-mvc razor


    【解决方案1】:

    如果您希望在某些区域有特定的布局,有一个简单的解决方案。

    使用_ViewStart 文件指定用于每个区域的布局。

    ~/Views/_ViewStart.cshtml文件:

    @{
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    

    ~/Areas/Xxx/Views/_ViewStart.cshtml文件:

    @{
        Layout = "~/Views/Shared/_LayoutXxx.cshtml";
    }
    

    您可以阅读ASP.NET MVC 3: Layouts with Razor

    不要忘记从视图中删除 Layout = "..." 声明,以便让 ViewStart 完成它的工作。

    【讨论】:

    • 但我引用的视图在该特定区域中不存在。
    • 你的问题很难从你的帖子中理解。您能否尝试给我们列出您希望在您拥有的不同情况下发生的事情(哪个角色、哪个用户属性、哪个区域、哪个 url)?
    【解决方案2】:

    传统上,您只使用ViewContext.RouteData.Values["key"],而不是DataTokens。不确定这是否有所作为。另外,我认为关键是“区域”,而不是“区域”。字典键是区分大小写的,所以这很可能是您的问题。

    编辑

    好的。我想我现在可能理解得更好了。要实现您想要的,您需要在采购区域中重新实现角色和用户功能。但是,这并不意味着您只需复制代码即可。您可以依靠视图约定来加载正确的视图。例如,如果您将 Roles 视图移动到 Views\Shared,则 Razor 可以在不同控制器或区域中搜索该视图时找到它,因为 Views\Shared 始终是搜索的最后一个结果路径。至于动作本身,您可以利用控制器继承在一个或多个不同区域实现相同的控制器/动作,而无需实际重复代码。

    【讨论】:

    • 您对“区域”小写字母的看法是正确的。但是我不认为这种方法对我有用。我没有在我的 ActionLink 中定义区域,因为这些是我的默认命名空间控制器中的操作,所以该键永远不会被设置...
    • 基本上我正在尝试在项目的各个区域重用角色和用户视图和操作。但是,我想为用户提供不为那些重复使用的视图和操作离开特定区域的体验。
    • _Application.cshtml 是否继承自 _Layout.cshtml
    • 它不继承。两个独立的布局
    • 对不起,我真的不明白你的问题。
    【解决方案3】:

    如果您想有条件地驱动使用哪个视图,您可以从视图引擎继承并根据每个请求覆盖视图位置

    This post 说明了不同的静态视图分辨率模式。

    您可以覆盖ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) 方法来自定义给定请求的可用视图。 controllerContext 对象将允许您查找用户及其角色,以便您返回正确的视图。

    public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
        if (/* user has role X */)
        {
            return new ViewEngineResult(new string[] { "Some View.cshtml" });
        }
    
        return base.FindView(controllerContext, viewName, masterName, useCache);
    }
    

    This article 展示如何从经典视图引擎继承并声明它们。 This article 展示了如何使用自定义 ViewEngine 中的请求对象来根据用户的角色选择视图。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-20
      • 2018-03-22
      相关资源
      最近更新 更多