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

时间:2010-01-05 10:30:09

标签: c# .net asp.net-mvc url-routing

是否有内置方式获取操作的完整网址?

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

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

6 个答案:

答案 0 :(得分:551)

Url.Action超载会将您所需的协议(例如http,https)作为参数 - 如果您指定了此协议,则会获得完全限定的网址。

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

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

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>

答案 1 :(得分:131)

正如Paddy所说:如果使用明确指定要使用的协议的UrlHelper.Action()重载,生成的URL将是绝对的且完全合格而不是相对的。

我写了一篇名为How to build absolute action URLs using the UrlHelper class的博客文章,其中我建议为了便于阅读而编写自定义扩展方法:

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

然后您可以在视图中使用它:

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

答案 2 :(得分:1)

这就是你需要做的。

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

答案 3 :(得分:0)

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

更新:上面的答案中详细说明了在网页外部形成网址的方法。

或者你可以做一个oneliner如下:

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

来自过滤器或:

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

然而,通常需要获取当前页面的网址,对于那些使用Html.Action的情况并将他所在页面的名称和控制器放在我身上感觉很尴尬。在这种情况下,我的偏好是使用JavaScript代替。这在半重写的系统中特别好.MVT半网络形式半个vb-script半知道什么 - 并且要获取当前页面的URL,每次都需要使用不同的方法。

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

答案 4 :(得分:0)

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

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

    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:

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

然后就像使用它一样:

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

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

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

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

答案 5 :(得分:0)

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

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

我可能有一点作弊,但这正是我需要强制使用https网址:

subfoldersOfFolder2

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