Today my article on extending Umbraco has been published on the Umbraco Advent calendar site and on a comment Ismail asked if one could have used the umbRequestHelper.GetApiUrl method to build the Url to the backoffice API instead of hardcoding it into the $http request. Since it would quite a long explanation which wouldn't fit in the comment, I'm posting it here instead.

The umbRequestHelper.GetApiUrl method

This method is used to simplify the creation of Url to the backoffice web api, and it creates them based on a JavaScript dictionary Umbraco.Sys.ServerVariables[umbracoUrls] that is created on the server, directly using the MVC routing engine to get the correct url for controllers. Once a custom controller has been registered in the umbracoUrls dictionary, using the method is pretty easy. You just call it by specifying the apiName (which is the key with which you register your controller in the dictionary) and the actionName within the controller (and a query paramter if needed). For example, if you want the url for the GetLanguages action of the NuTranslation API you just do:

umbRequestHelper.getApiUrl("nuTranslation","GetLanguages")

Setting the key in the umbracoUrls dictionary

But for it to work you need to first set the url in the umbracoUrls dictionary. And here comes the tricky bit.

This has to be done inside as handler for the ServerVariablesParser.Parsing event, where you just ask to the UrlHelper to get you the url of a given controller. Here is a simplified version of the code.

public class NuTransationApplication : ApplicationEventHandler
{
    protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
        ServerVariablesParser.Parsing += ServerVariablesParser_Parsing;
    }

    private void ServerVariablesParser_Parsing(object sender, Dictionary<string, object> serverVars)
    {
        if (HttpContext.Current == null) throw new InvalidOperationException("HttpContext is null");
        var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()));

        umbracoUrls["nuTranslation"] = urlHelper.GetUmbracoApiServiceBaseUrl<NuTranslationController>("Index");
    }
}

To make sure it all goes well, in a production level solution you should probably add some more error checking. You can see a complete version on NuTranslation github repo.

If you now call the getApiUrl("nuTranslation","GetLanguages") it will return /umbraco/BackOffice/Api/NuTranslation/GetLanguages.

Now if you rename the controller you won't have to update the frontend as well, and you won't have to remember the exact route to API controllers.