如何使用 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;
};
我是 运行 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;
};