关于c#:获取ASP.NET MVC中的完整操作URL

Getting full URL of action in ASP.NET MVC

本问题已经有最佳答案,请猛点这里访问。

是否有一种内置的方式来获取操作的完整URL?

我在找一些像GetFullUrl("Action","Controller")的东西,可以返回像http://www.fred.com/Controller/Action的东西。

我寻找这个的原因是为了避免在自动生成的电子邮件中对URL进行硬编码,这样就可以始终相对于站点的当前位置生成URL。


有一个url.action的重载,它将您所需的协议(如http、https)作为参数-如果指定此参数,您将得到一个完全限定的url。

下面是一个在操作方法中使用当前请求的协议的示例:

1
var fullUrl = this.Url.Action("Edit","Posts", new { id = 5 }, this.Request.Url.Scheme);

htmlhelper(@html)还具有ActionLink方法的重载,您可以在Razor中使用该方法来创建锚元素,但它还需要主机名和片段参数。所以我选择再次使用@url.action:

1
2
3
4
5
<span>
  Copy
  this link
  and post it anywhere on the internet!
</span>


正如Paddy所提到的:如果使用一个明确指定要使用的协议的UrlHelper.Action()重载,生成的URL将是绝对的和完全限定的,而不是相对的。

我写了一篇名为"如何使用urlhelper类构建绝对操作URL"的博客文章,我建议在其中编写一个自定义扩展方法,以提高可读性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// <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)
{
    string scheme = url.RequestContext.HttpContext.Request.Url.Scheme;

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

然后您可以像在视图中那样简单地使用它:

1
@Url.AbsoluteAction("Action","Controller")


我有一个问题,我的服务器在负载均衡器后面运行。负载平衡器正在终止SSL/TLS连接。然后,它使用HTTP将请求传递给Web服务器。

使用带有request.url.schema的url.action()方法,它不断地创建一个HTTP URL,在我的例子中,它在自动电子邮件中创建一个链接(我的pentester不喜欢)。

我可能有点作弊,但这正是我强制使用https URL所需要的:

1
Click Here

实际上,我使用web.config appsetting,以便在本地调试时使用HTTP,但所有测试和prod环境都使用转换来设置https值。


这就是你需要做的。

1
@Url.Action(action,controller, null, Request.Url.Scheme)


这可能只是我非常,非常挑剔,但我只喜欢定义一次常量。如果您使用上面定义的任何方法,您的操作常量将被定义多次。

要避免这种情况,可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    public class Url
    {
        public string LocalUrl { get; }

        public Url(string localUrl)
        {
            LocalUrl = localUrl;
        }

        public override string ToString()
        {
            return LocalUrl;
        }
    }

    public abstract class Controller
    {
        public Url RootAction => new Url(GetUrl());

        protected abstract string Root { get; }

        public Url BuildAction(string actionName)
        {
            var localUrl = GetUrl() +"/" + actionName;
            return new Url(localUrl);
        }

        private string GetUrl()
        {
            if (Root =="")
            {
                return"";
            }

            return"/" + Root;
        }

        public override string ToString()
        {
            return GetUrl();
        }
    }

然后创建控制器,例如DataController:

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static readonly DataController Data = new DataController();
    public class DataController : Controller
    {
        public const string DogAction ="dog";
        public const string CatAction ="cat";
        public const string TurtleAction ="turtle";

        protected override string Root =>"data";

        public Url Dog => BuildAction(DogAction);
        public Url Cat => BuildAction(CatAction);
        public Url Turtle => BuildAction(TurtleAction);
    }

然后像这样使用它:

1
2
3
4
5
6
    // GET: Data/Cat
    [ActionName(ControllerRoutes.DataController.CatAction)]
    public ActionResult Etisys()
    {
        return View();
    }

以及来自.cshtml(或任何代码)的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul>

   
<li>
Dog
</li>

   
<li>
Cat
</li>


</ul>

这肯定是更多的工作,但我很容易知道编译时验证在我这边。


这个问题是针对ASP.NET的,但是我相信你们中的一些人会受益于系统不可知的javascript,这在许多情况下都是有益的。

更新:获取在页面本身之外形成的URL的方法在上面的答案中有很好的描述。

或者你可以做如下的一行:

1
2
3
4
5
6
new UrlHelper(actionExecutingContext.RequestContext).Action(
   "SessionTimeout","Home",
    new {area = string.Empty},
    actionExecutingContext.Request.Url!= null?
    actionExecutingContext.Request.Url.Scheme :"http"
);

从过滤器或:

1
2
3
4
5
6
new UrlHelper(this.Request.RequestContext).Action(
   "Details",
   "Journey",
    new { area = productType },
    this.Request.Url!= null? this.Request.Url.Scheme :"http"
);

然而,经常需要得到当前页面的URL,对于那些使用Html.Action并将您所在页面的名称和控制器放在我面前的情况,我感到很尴尬。在这种情况下,我的首选是使用JavaScript。这在半重写的MVT半Web窗体半VB脚本半上帝知道什么的系统中特别好——要获得当前页面的URL,每次都需要使用不同的方法。

一种方法是使用javascript获取URL,它是window.location.href,另一种是document.URL