在 ASP.NET MVC 的模型中调用 UrlHelper

发布于 08-18 00:12 字数 141 浏览 12 评论 0原文

我需要在 ASP.NET MVC 的模型中生成一些 URL。我想调用类似 UrlHelper.Action() 的方法,它使用路由来生成 URL。我不介意填写常见的空白,例如主机名、方案等。

我可以调用任何方法吗?有没有办法构造一个UrlHelper?

I need to generate some URLs in a model in ASP.NET MVC. I'd like to call something like UrlHelper.Action() which uses the routes to generate the URL. I don't mind filling the usual blanks, like the hostname, scheme and so on.

Is there any method I can call for that? Is there a way to construct an UrlHelper?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

痕至2024-08-25 00:12:14

当前 HttpContext 的引用

HttpContext.Current

有用的提示,在任何 ASP.NET 应用程序中,您都可以获取派生自 System.Web 的 。因此,以下内容将在 ASP.NET MVC 应用程序中的任何位置工作:

UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
url.Action("ContactUs"); // Will output the proper link according to routing info

示例:

public class MyModel
{
    public int ID { get; private set; }
    public string Link
    {
        get
        {
            UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
            return url.Action("ViewAction", "MyModelController", new { id = this.ID });
        }
    }

    public MyModel(int id)
    {
        this.ID = id;
    }
}

在创建的 MyModel 对象上调用 Link 属性将返回有效的 Url,以根据 Global.asax 中的路由查看模型

Helpful tip, in any ASP.NET application, you can get a reference of the current HttpContext

HttpContext.Current

which is derived from System.Web. Therefore, the following will work anywhere in an ASP.NET MVC application:

UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
url.Action("ContactUs"); // Will output the proper link according to routing info

Example:

public class MyModel
{
    public int ID { get; private set; }
    public string Link
    {
        get
        {
            UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
            return url.Action("ViewAction", "MyModelController", new { id = this.ID });
        }
    }

    public MyModel(int id)
    {
        this.ID = id;
    }
}

Calling the Link property on a created MyModel object will return the valid Url to view the Model based on the routing in Global.asax

爱情眠于流年2024-08-25 00:12:14

我喜欢奥马尔的回答,但这对我不起作用。仅供记录,这是我现在使用的解决方案:

var httpContext = HttpContext.Current;

if (httpContext == null) {
  var request = new HttpRequest("/", "http://example.com", "");
  var response = new HttpResponse(new StringWriter());
  httpContext = new HttpContext(request, response);
}

var httpContextBase = new HttpContextWrapper(httpContext);
var routeData = new RouteData();
var requestContext = new RequestContext(httpContextBase, routeData);

return new UrlHelper(requestContext);

I like Omar's answer but that's not working for me. Just for the record this is the solution I'm using now:

var httpContext = HttpContext.Current;

if (httpContext == null) {
  var request = new HttpRequest("/", "http://example.com", "");
  var response = new HttpResponse(new StringWriter());
  httpContext = new HttpContext(request, response);
}

var httpContextBase = new HttpContextWrapper(httpContext);
var routeData = new RouteData();
var requestContext = new RequestContext(httpContextBase, routeData);

return new UrlHelper(requestContext);
甜`诱少女2024-08-25 00:12:14

可以通过以下方式从 Controller 操作内部构造 UrlHelper:

 var url = new UrlHelper(this.ControllerContext.RequestContext);
 url.Action(...);

在控制器外部,可以通过从 RouteTable.Routes RouteData 创建 RequestContext 来构造 UrlHelper。

HttpContextWrapper httpContextWrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
UrlHelper urlHelper = new UrlHelper(new RequestContext(httpContextWrapper, RouteTable.Routes.GetRouteData(httpContextWrapper)));

(基于 Brian 的回答,添加了少量代码更正。)

A UrlHelper can be constructed from within a Controller action with the following:

 var url = new UrlHelper(this.ControllerContext.RequestContext);
 url.Action(...);

Outside of a controller, a UrlHelper can be constructed by creating a RequestContext from the RouteTable.Routes RouteData.

HttpContextWrapper httpContextWrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
UrlHelper urlHelper = new UrlHelper(new RequestContext(httpContextWrapper, RouteTable.Routes.GetRouteData(httpContextWrapper)));

(Based on Brian's answer, with a minor code correction added.)

荒芜了季节2024-08-25 00:12:14

是的,您可以实例化它。你可以这样做:

var ctx = new HttpContextWrapper(HttpContext.Current);
UrlHelper helper = new UrlHelper(
   new RequestContext(ctx,
   RouteTable.Routes.GetRouteData(ctx));

RouteTable.Routes 是一个静态属性,所以你应该没问题;为了获取 HttpContextBase 引用,HttpContextWrapper 获取对 HttpContext 的引用,然后 HttpContext 传递该引用。

Yes, you can instantiate it. You can do something like:

var ctx = new HttpContextWrapper(HttpContext.Current);
UrlHelper helper = new UrlHelper(
   new RequestContext(ctx,
   RouteTable.Routes.GetRouteData(ctx));

RouteTable.Routes is a static property, so you should be OK there; to get a HttpContextBase reference, HttpContextWrapper takes a reference to HttpContext, and HttpContext delivers that.

故人如初2024-08-25 00:12:14

在尝试了所有其他答案之后,我最终得到了

$"/api/Things/Action/{id}"

仇恨者会讨厌 ́\_(ツ)_/́

After trying all the other answers, I ended up with

$"/api/Things/Action/{id}"

Haters gonna hate ¯\_(ツ)_/¯

最初的梦2024-08-25 00:12:14

我试图在页面内(控制器外部)执行类似的操作。

UrlHelper 不允许我像 Pablos 的回答一样轻松地构建它,但后来我想起了一个有效做同样事情的老技巧:

string ResolveUrl(string pathWithTilde)

I was trying to do something similar from within a page (outside of a controller).

UrlHelper did not allow me to construct it as easily as Pablos answer, but then I remembered a old trick to effective do the same thing:

string ResolveUrl(string pathWithTilde)
聽兲甴掵2024-08-25 00:12:14

之前的回复对我没有帮助。我的方法是在我的 Home 控制器中创建一个与 UrlHelper 具有相同功能的操作。

    [HttpPost]
    [Route("format-url")]
    public ActionResult FormatUrl()
    {
        string action = null;
        string controller = null;
        string protocol = null;
        dynamic parameters = null;

        foreach (var key in this.Request.Form.AllKeys)
        {
            var value = this.Request.Form[key];
            if (key.Similar("action"))
            {
                action = value;
            }
            else if (key.Similar("controller"))
            {
                controller = value;
            }
            else if (key.Similar("protocol"))
            {
                protocol = value;
            }
            else if (key.Similar("parameters"))
            {
                JObject jObject = JsonConvert.DeserializeObject<dynamic>(value);

                var dict = new Dictionary<string, object>();
                foreach (var item in jObject)
                {
                    dict[item.Key] = item.Value;
                }

                parameters = AnonymousType.FromDictToAnonymousObj(dict);
            }
        }

        if (string.IsNullOrEmpty(action))
        {
            return new ContentResult { Content = string.Empty };
        }

        int flag = 1;
        if (!string.IsNullOrEmpty(controller))
        {
            flag |= 2;
        }

        if (!string.IsNullOrEmpty(protocol))
        {
            flag |= 4;
        }

        if (parameters != null)
        {
            flag |= 8;
        }

        var url = string.Empty;
        switch (flag)
        {
            case 1: url = this.Url.Action(action); break;
            case 3: url = this.Url.Action(action, controller); break;
            case 7: url = this.Url.Action(action, controller, protocol); break;
            case 9: url = this.Url.Action(action, parameters); break;
            case 11: url = this.Url.Action(action, controller, parameters); break;
            case 15: url = this.Url.Action(action, controller, parameters, protocol); break;
        }

        return new ContentResult { Content = url };
    }

作为一个操作,您可以从任何地方请求它,甚至在 Hub 内部:

            var postData = "action=your-action&controller=your-controller";

            // Add, for example, an id parameter of type integer
            var json = "{\"id\":3}";
            postData += $"¶meters={json}";

            var data = Encoding.ASCII.GetBytes(postData);

#if DEBUG
            var url = $"https://localhost:44301/format-url";
#else
            var url = $"https://your-domain-name/format-url";
#endif

            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/text/plain";
            request.ContentLength = data.Length;

            using (var stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

            var response = (HttpWebResponse)request.GetResponse();
            var link = new StreamReader(stream: response.GetResponseStream()).ReadToEnd();

您可以获取 AnonymousType 的源代码 此处

Previous responses didn't help me. My approach has been create an action in my Home controller with the same functionality that UrlHelper.

    [HttpPost]
    [Route("format-url")]
    public ActionResult FormatUrl()
    {
        string action = null;
        string controller = null;
        string protocol = null;
        dynamic parameters = null;

        foreach (var key in this.Request.Form.AllKeys)
        {
            var value = this.Request.Form[key];
            if (key.Similar("action"))
            {
                action = value;
            }
            else if (key.Similar("controller"))
            {
                controller = value;
            }
            else if (key.Similar("protocol"))
            {
                protocol = value;
            }
            else if (key.Similar("parameters"))
            {
                JObject jObject = JsonConvert.DeserializeObject<dynamic>(value);

                var dict = new Dictionary<string, object>();
                foreach (var item in jObject)
                {
                    dict[item.Key] = item.Value;
                }

                parameters = AnonymousType.FromDictToAnonymousObj(dict);
            }
        }

        if (string.IsNullOrEmpty(action))
        {
            return new ContentResult { Content = string.Empty };
        }

        int flag = 1;
        if (!string.IsNullOrEmpty(controller))
        {
            flag |= 2;
        }

        if (!string.IsNullOrEmpty(protocol))
        {
            flag |= 4;
        }

        if (parameters != null)
        {
            flag |= 8;
        }

        var url = string.Empty;
        switch (flag)
        {
            case 1: url = this.Url.Action(action); break;
            case 3: url = this.Url.Action(action, controller); break;
            case 7: url = this.Url.Action(action, controller, protocol); break;
            case 9: url = this.Url.Action(action, parameters); break;
            case 11: url = this.Url.Action(action, controller, parameters); break;
            case 15: url = this.Url.Action(action, controller, parameters, protocol); break;
        }

        return new ContentResult { Content = url };
    }

Been an action, you can request it from anywhere, even inside the Hub:

            var postData = "action=your-action&controller=your-controller";

            // Add, for example, an id parameter of type integer
            var json = "{\"id\":3}";
            postData += 
quot;¶meters={json}";

            var data = Encoding.ASCII.GetBytes(postData);

#if DEBUG
            var url = 
quot;https://localhost:44301/format-url";
#else
            var url = 
quot;https://your-domain-name/format-url";
#endif

            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/text/plain";
            request.ContentLength = data.Length;

            using (var stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

            var response = (HttpWebResponse)request.GetResponse();
            var link = new StreamReader(stream: response.GetResponseStream()).ReadToEnd();

You can get source code of AnonymousType here.

番薯2024-08-25 00:12:14

我想你正在寻找的是这样的:

Url.Action("ActionName", "ControllerName");

I think what you're looking for is this:

Url.Action("ActionName", "ControllerName");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文