views:

1480

answers:

5

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?

A: 

I think what you're looking for is this:

Url.Action("ActionName", "ControllerName");
+1  A: 

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.)

Nathan Taylor
But I don't have a controller in the model.
J. Pablo Fernández
Okay I apologize, I wasn't sure exactly where the code was being executed. Let me take a look...
Nathan Taylor
+2  A: 

Hey,

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

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

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.

Brian
This will not work, though it's very close. See my answer below.
Nathan Taylor
+4  A: 

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

Baddie
Are you sure there's a HttpContext.Current.Request.RequestContext? HttpContext.Current.Request seems not to have a RequestContext.
J. Pablo Fernández
Thats odd. I just tested this solution out and it works perfectly. I'm running ASP.NET MVC 2 Preview 2, but I think this works across all versions. Not sure why it's not working for you. Are you creating the class outside of an MVC project? Also make sure there are `using` for both `System.Web` and `System.Web.Mvc`
Baddie
I'm on an ASP.NET MVC 1 project, I thought about missing usings but I have both of them.
J. Pablo Fernández
Not really sure why it's not showing. If anyone else could confirm this doesn't exist in ASP.NET MVC 1 that would be great. I only have one machine with VS2010 and MVC 2 installed. If you're interested, MVC RC 2 http://haacked.com/archive/2009/12/16/aspnetmvc-2-rc.aspx
Baddie
Thanks Baddie. Worked like a champ. Using MVC 2 though.
Rake36
+7  A: 

I like Baddie'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);
J. Pablo Fernández
What is Config.Url?
joshcomley
It contains the URL of my site. There, I removed it.
J. Pablo Fernández