【问题标题】:How to correctly use Html.ActionLink with ASP.NET MVC 4 Areas如何正确使用 Html.ActionLink 与 ASP.NET MVC 4 区域
【发布时间】:2014-04-19 21:32:17
【问题描述】:

我最近发现了 Areas in ASP.NET MVC 4,我已经成功实现了它,但是我在 Razor 视图中遇到了 @Html.ActionLink 助手的问题。这个助手生成的 URL 似乎总是相对于当前页面的 URL。

我在 IIS 7 (Win7) 中将我的网站配置为 /Foo 的应用程序虚拟目录。

我注册了两个区域:管理员和博客。我在AdminAreaRegistration.csBlogsAreaRegistration.cs 文件中有默认代码。我在默认 RouteConfig 的默认值中添加了 namespaces = new[] { "MvcProject.Controllers" }

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new {
                controller = "Home", action = "Index", id = UrlParameter.Optional,
                namespaces = new[] { "MvcProject.Controllers" }
            }
        );
    }
}

当我转到我网站的主页:http://localhost/Foo 时,它会正确加载我网站的“主页”页面。此时,所有操作链接都有正确的 URL。

来自MvcProject/Views/Shared/_Layout.cshtml的示例代码

<h2>Main Navigation</h2>
<ul>
    <li>@Html.ActionLink("Home", "Index", "Home")</li>
    <li>@Html.ActionLink("Blogs", "Index", "Blogs/Home")</li>
    <li>@Html.ActionLink("Admin", "Index", "Admin/Home")</li>
</ul>

这正确地将 HTML 呈现为:

<h2>Main Navigation</h2>
<ul>
    <li><a href="/Foo">Home</a></li>
    <li><a href="/Foo/Blogs/Home"></li>
    <li><a href="/Foo/Admin/Home"></li>
</ul>

例如,当我在浏览器中导航到“博客”时,此 URL 会正确加载到浏览器中:/Foo/Blogs/Home

现在我的主导航中的链接将它们的 URL 更改为:

<h2>Main Navigation</h2>
<ul>
    <li><a href="/Foo/Blogs/Home">Home</a></li>
    <li><a href="/Foo/Blogs/Blogs/Home"></li>
    <li><a href="/Foo/Blogs/Admin/Home"></li>
</ul>

请注意,“Blogs/”附加到 IIS 虚拟目录名称后,因此 /Foo/Blogs/Home 现在是 /Foo/Blogs/Blogs/Home

控制器和视图呈现正常,只是在我的MvcProject/Views/Shared/_Layout.cshtml 视图中对@Html.ActionLink 的调用没有按预期工作。

感觉好像我错过了一些微不足道的东西,但没有多少搜索得到答案。我发现的用于在 ASP.NET MVC4 中实现区域的每一篇博文和教程都没有提及 @Html.ActionLink 行为方式的变化。

【问题讨论】:

    标签: c# asp.net-mvc-4 razor asp.net-mvc-routing


    【解决方案1】:

    我讨厌回答自己的问题,但@Matt Bodily 让我走上了正轨。

    @Html.Action 方法实际上调用了一个控制器并呈现了视图,因此在我的例子中,它无法创建 HTML 的 sn-p,因为这会导致递归函数调用,从而导致 StackOverflowException。 @Url.Action(action, controller, { area = "abc" }) 确实返回了 URL,但我终于发现 Html.ActionLink 的重载为我的情况提供了更好的解决方案:

    @Html.ActionLink("Admin", "Index", "Home", new { area = "Admin" }, null)
    

    注意:, null 在这种情况下很重要,以匹配正确的签名。

    文档:@Html.ActionLink (LinkExtensions.ActionLink)

    此特定重载的文档:

    LinkExtensions.ActionLink(Controller, Action, Text, RouteArgs, HtmlAttributes)

    很难找到这些助手的文档。当我可能应该搜索“LinkExtensions.ActionLink”时,我倾向于搜索“Html.ActionLink”,如果这对将来的任何人有帮助的话。

    仍然将马特的回答标记为答案。

    编辑:找到另一个 HTML 助手来解决这个问题:

    @Html.RouteLink("Admin", new { action = "Index", controller = "Home", area = "Admin" })
    

    【讨论】:

    • 仅供参考,回答您自己的问题仍然是件好事!它允许像我这样的人出现并找到我可能遇到的问题/问题的答案。谢谢!
    • 这个答案帮助我解决了我的问题。我收到一个错误,上面写着The controller for path '/' was not found or does not implement IController. 这是因为我删除了我的 HomeController.cs 文件,但我不明白它依赖于什么。
    • 解决方案被证明是最有用的。我正在尝试不包括“null”。
    • @Colin:Visual Studio 2017 很好,因为它更明确地告诉您方法是扩展方法。旧版本的 VS 在这方面不太有用。当谈到这些 Razor 模板扩展方法时,我仍然与我的 Google-fu 斗争。
    【解决方案2】:

    我如何重定向到一个区域是将其添加为参数

    @Html.Action("Action", "Controller", new { area = "AreaName" })
    

    对于我使用的链接的 href 部分

    @Url.Action("Action", "Controller", new { area = "AreaName" })
    

    【讨论】:

    • 所以,有趣的巧合。一旦我将它添加到我的视图中,我就得到了 StackOverflowException :) 不太清楚为什么...是时候深入研究 Windows 事件日志了。
    • 稍作阅读后,似乎@Html.Action(...) 实际调用并呈现了动作。就我而言,我只是想吐出一个 URL。我认为我遇到了堆栈溢出,因为主布局文件呈现了 Blogs/Home 动作,该动作拉入了布局文件,该动作呈现了 Blogs/Home 动作,该动作拉入了主布局文件,...我们去无穷远。
    • 对于链接的 href 部分或我在 jquery 中使用的 url,我使用 url.action 代替。看看我上面的变化
    【解决方案3】:

    只是把我的一点加起来:
    请记住,您需要在 MVC 应用程序中至少有 2 个区域才能使 routeValues: { area="" } 正常工作;否则,面积值将用作查询字符串参数,您的链接将如下所示:/?area=

    如果您没有至少 2 个区域,您可以通过以下方式解决此问题:
    1. 编辑RouteConfig.cs中的默认路由如下:

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { area = "", controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
    


    2. 为您的 MVC 项目添加一个虚拟区域。

    【讨论】:

    • 在我的例子中,我们从最初的 MVC 项目结构开始,然后添加了一个区域。我必须进行上述更改,以便默认主页的徽标 url 可以在所有控制器上工作。
    【解决方案4】:

    以下是在 MVC 中创建链接按钮的一些方法。

    @Html.ActionLink("Admin", "Index", "Home", new { area = "Admin" }, null)  
    @Html.RouteLink("Admin", new { action = "Index", controller = "Home", area = "Admin" })  
    @Html.Action("Action", "Controller", new { area = "AreaName" })  
    @Url.Action("Action", "Controller", new { area = "AreaName" })  
    <a class="ui-btn" data-val="abc" href="/Home/Edit/ANTON">Edit</a>  
    <a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#CustomerList" href="/Home/Germany">Customer from Germany</a>  
    <a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#CustomerList" href="/Home/Mexico">Customer from Mexico</a> 
    

    希望这会对你有所帮助。

    【讨论】:

    • 请注意Html.Action(...)。我发现它不会创建链接。它呈现一个控制器。不然很好总结的方法。谢谢。
    猜你喜欢
    • 2011-07-22
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 1970-01-01
    相关资源
    最近更新 更多