Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get an instance of WebApi UrlHelper from inside an Mvc Action

I am running WebApi and Mvc from within the same project (so they are in-process). Mvc mostly for serving assets (pages and generated downloads) and web api for ajax data requests.

In order to be RESTish, most of the WebApi requests include a set of links where are generated by the following class:

public class ApiLinkMaker
{
    public ApiLinkMaker(UrlHelper url, string authority) {
        this.url = url;
        this.authority = authority;
    }
    public ApiLinkMaker(ApiController controller)
        : this(controller.Url, controller.Request.RequestUri.Authority) { }

    public string MakeLink(string controller, string id) {
        return "//" + authority + url.Route("DefaultApi", new { controller = controller, id = id });
    }
}

There's a few other methods on there, but this is really the core of things and it works fine.

Now I want to optimize a particular page. Where previously I had two requests

  1. Download the html
  2. Do an Ajax query to get some data (and some links)

Now I realize that for optimization purposes it is better to do just one in this case.

  1. Download the html with the data already JSON embedded into it.

The problem is that since the html is being generated by Mvc, I cannot create an Api UrlHelper that seems to work.

I tried

var url = new UrlHelper(new HttpRequestMessage(verb, controller.Request.Url.AbsoluteUri));
if (!url.Request.Properties.ContainsKey(HttpPropertyKeys.HttpConfigurationKey)) //http://stackoverflow.com/questions/11053598/how-to-mock-the-createresponset-extension-method-on-httprequestmessage
   url.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());

But this still blows up

System.ArgumentException was unhandled by user code
  HResult=-2147024809
  Message=A route named 'DefaultApi' could not be found in the route collection.
Parameter name: name
  Source=System.Web.Http
  ParamName=name
  StackTrace:
       at System.Web.Http.HttpRouteCollection.GetVirtualPath(HttpRequestMessage request, String name, IDictionary`2 values)
       at System.Web.Http.Routing.UrlHelper.GetHttpRouteHelper(HttpRequestMessage request, String routeName, IDictionary`2 routeValues)
       at System.Web.Http.Routing.UrlHelper.GetHttpRouteHelper(HttpRequestMessage request, String routeName, Object routeValues)
       at System.Web.Http.Routing.UrlHelper.Route(String routeName, Object routeValues)
       at MyProject.Models.ApiLinkMaker.MakeLink(String controller, String id) in w:\MyProject\Models\ApiLinkMaker.cs:line 42
       ...

This leads me to think that I'm going about this wrong - that I need to create the url helper from the api routing configuration somehow.

like image 501
George Mauer Avatar asked Feb 16 '23 15:02

George Mauer


1 Answers

Why create one? There is an instance of the UriHelper exposed as a property on both the MVC Controller and ApiController classes.

    public ActionResult Index()
    {
        string url = Url.RouteUrl("DefaultApi", new {httproute = "", controller = "test"});
        return View();
    }

Edit: Updated code. While the url helpers are different you can use the MVC url helper to resolve the web api url.

Edit2: The correct method to use if you want to get webapi routes from an Mvc UrlHelper is

string url = Url.HttpRouteUrl("DefaultApi", new {httproute = "", controller = "test"});
like image 157
Jace Rhea Avatar answered Mar 23 '23 06:03

Jace Rhea