MVC领域&共享布局

时间:2017-04-11 13:28:52

标签: asp.net-mvc razor

希望我能清楚自己。我的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从未收到区域路由,因为它没有定义。

编辑:对不起我在描述问题时遇到了麻烦(即使是同事也是如此......)

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

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

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

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

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

我希望看到当我单击导航菜单的角色或用户以保持采购布局并引用相同的支持控制器时是否可能。我不想为我正在创建的每个区域创建角色和用户页面。

3 个答案:

答案 0 :(得分:2)

如果您希望某些区域有特定的布局,可以使用简单的解决方案。

使用<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" /> <xsl:strip-space elements="*"/> <!-- identity rule Copy all elements and attributes from the source to the target--> <xsl:template match="@*|node()" name="identity"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- Wrap Element --> <xsl:template match="/dataroot/qryXMLOrders"> <xsl:copy> <xsl:apply-templates select="PreDocTypAR21|ComNomCMD1|NamCE27|MarNumOfPacGS21/preceding-sibling::*" mode="copy-if-needed"/> <PREADMREFAR2> <xsl:apply-templates select="PreDocTypAR21|PreDocRefAR26|PreDocCatPREADMREF21"/> </PREADMREFAR2> <COMCODGODITM> <xsl:apply-templates select="ComNomCMD1|TARCodCMD1|TARFirAddCodCMD1|TARSecAddCodCMD1|NAtAddCodCMD1"/> </COMCODGODITM> <TRACONCE2> <xsl:apply-templates select="NamCE27|StrAndNumCE222|PosCodCE223|CitCE224|CouCE225|NADLNGGICE"/> </TRACONCE2> <PACGS2> <xsl:apply-templates select="MarNumOfPacGS21|KinOfPacGS23|NumOfPacGS24"/> </PACGS2> <xsl:apply-templates select="PreDocCatPREADMREF21|NAtAddCodCMD1|NADLNGGICE|NumOfPacGS24/following-sibling::*" mode="copy-if-needed"/> </xsl:copy> </xsl:template> <xsl:template match="PreDocTypAR21|PreDocRefAR26|PreDocCatPREADMREF21|ComNomCMD1|TARCodCMD1|TARFirAddCodCMD1|TARSecAddCodCMD1|NAtAddCodCMD1|NamCE27|StrAndNumCE222|PosCodCE223|CitCE224|CouCE225|NADLNGGICE|MarNumOfPacGS21|KinOfPacGS23|NumOfPacGS24" mode="copy-if-needed"> <!-- Do nothing, skip these nodes --> </xsl:template> <xsl:template match="*" mode="copy-if-needed"> <!-- Copy (apply default template) --> <xsl:apply-templates select="current()"/> </xsl:template> </xsl:stylesheet> 文件指定要用于每个区域的布局。

_ViewStart档案:

~/Views/_ViewStart.cshtml

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

~/Areas/Xxx/Views/_ViewStart.cshtml

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

不要忘记从视图中删除@{ Layout = "~/Views/Shared/_LayoutXxx.cshtml"; } 声明,以便ViewStart能够正常工作。

答案 1 :(得分:0)

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

修改

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

答案 2 :(得分:0)

如果您想有条件地驾驶使用哪个视图,您可以从视图引擎继承并基于每个请求覆盖视图位置

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中的请求对象来根据用户的角色选择视图。