C# 在 ASP.NET MVC 中获取操作的完整 URL

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2005367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 22:34:54  来源:igfitidea点击:

Getting full URL of action in ASP.NET MVC

c#.netasp.net-mvcurl-routing

提问by Alan Spark

Is there a built-in way of getting the full URL of an action?

是否有获取操作完整 URL 的内置方法?

I am looking for something like GetFullUrl("Action", "Controller")that would return something like http://www.fred.com/Controller/Action.

我正在寻找类似的东西GetFullUrl("Action", "Controller")会返回类似的东西http://www.fred.com/Controller/Action

The reason I am looking for this is to avoid hardcoding URLs in automated emails that are generated so that the URLs can always be generated relative to the current location of the site.

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

采纳答案by Paddy

There is an overload of Url.Action that takes your desired protocol (e.g. http, https) as an argument - if you specify this, you get a fully qualified URL.

Url.Action 有一个重载,它将您想要的协议(例如 http、https)作为参数 - 如果您指定它,您将获得一个完全限定的 URL。

Here's an example that uses the protocol of the current request in an action method:

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

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

HtmlHelper (@Html) also has an overload of the ActionLink method that you can use in razor to create an anchor element, but it also requires the hostName and fragment parameters. So I'd just opt to use @Url.Action again:

HtmlHelper (@Html) 也有一个 ActionLink 方法的重载,你可以在 razor 中使用它来创建一个锚元素,但它也需要 hostName 和 fragment 参数。所以我只是选择再次使用@Url.Action:

<span>
  Copy
  <a href='@Url.Action("About", "Home", null, Request.Url.Scheme)'>this link</a> 
  and post it anywhere on the internet!
</span>

回答by Marius Schulz

As Paddy mentioned: if you use an overload of UrlHelper.Action()that explicitly specifies the protocol to use, the generated URL will be absolute and fully qualified instead of being relative.

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

I wrote a blog post called How to build absolute action URLs using the UrlHelper classin which I suggest to write a custom extension method for the sake of readability:

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

/// <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);
}

You can then simply use it like that in your view:

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

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

回答by Matas Vaitkevicius

This question is specific to ASP .NET however I am sure some of you will benefit of system agnostic javascript which is beneficial in many situations.

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

UPDATE:The way to get url formed outside of the page itself is well described in answers above.

更新:在上面的答案中很好地描述了在页面本身之外形成 url 的方法。

Or you could do a oneliner like following:

或者你可以做一个像下面这样的oneliner:

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

from filter or:

从过滤器或:

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

However quite often one needs to get the url of current page, for those cases using Html.Actionand putting he name and controller of page you are in to me feels awkward. My preference in such cases is to use JavaScript instead. This is especially good in systems that are half re-written MVT half web-forms half vb-script half God knows what - and to get URL of current page one needs to use different method every time.

然而,很多时候需要获取当前页面的 url,对于那些使用Html.Action和放置他的名称和页面控制器的情况,我觉得很尴尬。在这种情况下,我更喜欢使用 JavaScript。这在一半重写 MVT 一半 web 表单一半 vb 脚本一半天知道是什么的系统中特别好 - 并且每次需要使用不同的方法来获取当前页面的 URL。

One way is to use JavaScript to get URL is window.location.hrefanother - document.URL

一种方法是使用 JavaScript 来获取 URL 是window.location.href另一种 -document.URL

回答by Jorge Aguirre

This may be just me being really, really picky, but I like to only define constants once. If you use any of the approaches defined above, your action constant will be defines multiple times.

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

To avoid this, you can do the following:

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

    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();
        }
    }

Then create your controllers, say for example the DataController:

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

    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);
    }

Then just use it like:

然后像这样使用它:

    // GET: Data/Cat
    [ActionName(ControllerRoutes.DataController.CatAction)]
    public ActionResult Etisys()
    {
        return View();
    }

And from your .cshtml (or any code)

从你的 .cshtml (或任何代码)

<ul>
    <li><a href="@ControllerRoutes.Data.Dog">Dog</a></li>
    <li><a href="@ControllerRoutes.Data.Cat">Cat</a></li>
</ul>

This is definitely a lot more work, but I rest easy knowing compile time validation is on my side.

这肯定是更多的工作,但我知道编译时验证就在我身边,我就放心了。

回答by Salman Zahid

This what you need to do.

这是你需要做的。

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

回答by Matt D

I was having an issue with this, my server was running behind a load balancer. The load balancer was terminating the SSL/TLS connection. It then passed the request to the web servers using http.

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

Using the Url.Action() method with Request.Url.Schema, it kept creating a http url, in my case to create a link in an automated email (which my PenTester didn't like).

使用带有 Request.Url.Schema 的 Url.Action() 方法,它不断创建一个 http url,在我的例子中是在自动电子邮件中创建一个链接(我的 PenTester 不喜欢)。

I may have cheated a little, but it is exactly what I needed to force a https url:

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

<a href="@Url.Action("Action", "Controller", new { id = Model.Id }, "https")">Click Here</a>

I actually use a web.config AppSetting so I can use http when debugging locally, but all test and prod environments use transformation to set the https value.

我实际上使用了 web.config AppSetting,因此我可以在本地调试时使用 http,但所有测试和生产环境都使用转换来设置 https 值。