如何使用 MVC .NET 路由创建一致的 URL?

How to create consistent URLs with MVC .NET routing?

我是 运行 ASP.Net .NET Framework 4.8 中的 MVC 5。由于生成的 URL 不一致,我不断收到 404 错误。例如,在每个页面顶部包含的 _PageNav.chstml 部分中,我使用以下命令将用户带回主页:@Url.Action("Index", new { controller = "Home" })。在导航栏中,这解析为 <a class="navbar-brand" href="/" /> 并正常运行。

当我在同一页面上使用相同的 @Url.Action("Index", new { controller = "Home" }),但稍后在一个按钮上,它解析为:<a id="doneButton" class="btn btn-secondary px-4" href="https://localhost:44337/smrt/">Done</a>

由于这种不一致,我经常遇到以下问题:AJAX JavaScript 对控制器的引用最终缺少控制器引用,例如 /create 导致 https://localhost:44337/create 而不是https://localhost:44337/home/create/home/create 导致 https://localhost:44337/home/home/create 而不是 https://localhost:44337/home/create

由于安全限制,我确实也有一些限制;例如,我不能在页面本身上有任何 JavaScript,所以我不能在我的 .cshtml 文件中编写会导致 JavaScript 的剃刀代码。我只能使用页面源文件中引用的 JavaScript。

@Url.Action("Index", "Home") 应该足以完成这项工作,但我注意到有时在更改级别时自定义路由起作用时会出现一些问题。 Url.Action 例程不呈现完全限定的 url,有时我发现我必须附加“../”才能导航到不同的控制器结构,当一个控制器的视图对另一个文件夹的视图进行 AJAX 调用时.此外,默认的 URL 结构可以抛出相对 URL 调用,因为默认的实现是在 URL 结构中隐藏 /Index。所以 URL:

  • localhost/site(默认值 Home/Index)
  • localhost/site/other(默认索引)

在不同的文件夹结构中查看这两个视图,URL 导航可能会丢失。

这就是我的经验,说明您可能会遇到一些问题。

我提出了一些不同的想法,但我能够解决我的问题。我现在每次都以我需要的方式获得一致的 URLs。

首先,我使用这篇文章How to Build Absolute Action URLs Using the UrlHelper Class,使用基于 UrlHelper Class 的扩展方法创建了以下 class。

using System.Web.Mvc;

namespace MVCPages.Utilities
{
    public static class UrlHelperExtenions
    {
        /// <summary>
        /// Generates a fully qualified URL to an action method by using
        /// the specified action name, controller name and route values.
        /// </summary>
        /// <param name="url">The URL helper.</param>
        /// <param name="actionName">The name of the action method.</param>
        /// <param name="controllerName">The name of the controller.</param>
        /// <param name="routeValues">The route values.</param>
        /// <returns>The absolute URL.</returns>        
        public static string AbsoluteAction(
            this UrlHelper url,
            string actionName,
            string controllerName,
            object routeValues = null
        )
        {
            var httpContext = url.RequestContext.HttpContext;
            string scheme = httpContext.Request.Url.Scheme;

            return url.Action(
                actionName,
                controllerName,
                routeValues,
                scheme
            );
        }
    }
}

无论网站部署在何处,这种新方法都会动态地为我提供网站的根目录。

然后我在需要 URL 一致性的视图中调用新方法扩展,并使用 ViewBag 将绝对根 URL 传递给视图。

public ActionResult Index()
{
   string rootUrl = Url.AbsoluteAction("Index", "Smrt");
   ViewBag.RootUrl = rootUrl;
}

因为不允许我使用 Razor 创建 JavaScript,接下来我使用 Razor 创建一个包含根 URL 的隐藏 HTML div 标签, <div id="rootUrl">https://rooturl.com/</div>

现在,在 JavaScript 中,我使用 DOM 从 HTML 标签中检索 URL;然后将广告用于我的 ajax 调用,为 AJAX 调用创建完整的 URL。

window.onload = function () { 
   var rootUrl = document.getElementById("rootUrl").innerHTML;
   var ajaxUrl = rootUrl + ajaxCall;
};