An Example Of The Need To Use Absolute URLs

I have been doing some work around twitter and ASP.NET MVC. The way twitter authentication works, is that I have a page that creates a twitter URL, redirects the user to twitter, imagethe users accepts to use the application associated with the website, and twitter redirects the user to a callback URL, the completes processing of the user credentials. In order to set a callback URL dynamically (especially in development, when the callback is likely a localhost one), we need to send the absolute URL to twitter.

Other examples might include having a “permanent URL” for some resource (product, blog post, etc..), or maybe a link to be used in emails or so. There can be many usages, so, let’s see how to do it!

How We Did It In Webforms

In webforms, the easiest way to do it was to use the Control.ResolveClientUrl() method.

Typically you pass a URL relative to the current code file (.aspx, .master or .ascx file). and it returns the corresponding absolute URL of that. Of course when the file is a control or a master page file, we don’t always want/have a path relative to this file. The work around for this was passing a relative URL that starts with “~/”. As you probably know, “~/” represents the root of the website.

Example:

Assuming your website is running in “https://localhost:4444/my-application”, calling:

var contactUsUrl = Page.ResolveClientUrl("~/About/Contact-Us.aspx");

from any page or control wiill return “https://localhost:4444/my-application/About/Contact-Us.aspx”.

Fully Qualified Urls In ASP.NET MVC

Similar to webforms, where we used a current control as a starting point, we can use the controller (or view, if we really want to [hint: we don’t]), to access the current instance of “UrlHelper” class (the “Url” property of an ASP.NET MVC Controller), which gives us access to the routing system that comes with ASP.NET in general, and gives shortcut methods specific to ASP.NET MVC, like Url.Action().

This will return us the relative URL though, to convert this to an absolute / fully-qualified URL, we use Request.Url.AbsoluteUri (Controller.Request is the current HttpRequestBase instance) to get the absolute Uri information, and the “UriBuilder” class to create the Url.

Update:

Turns out you can call any of the UrlHelper methods and get an absolute URL directly if you call the overload that accepts a “protocol” value (also called “scheme”, that’s  “http”, “https”, etc..), even if the protocol is the same protocol used in the current request.

Original Example

Going with the same assumptions in the webforms example, replacing “contact-us.aspx” page with a controller “AboutController”, and an action “ContactUs” that has ActionName set to “Contact-Us”, adding the following code inside any ASP.NET MVC action:

var contactUsUrlBuilder =
    new UriBuilder(Request.Url.AbsoluteUri)
        {
            Path = Url.Action("Contact-Us", "About")
        };
var contactUsUri = contactUsUrlBuilder.Uri;
var contactUsUriString = contactUsUrlBuilder.ToString();
// or contactUsUrlBuilder.Uri.ToString()

can be used to get “https://localhost:4444/my-application/About/Contact-Us”.

Updated Example

We can get “contactUsUriString” in the previous example in a different way, by calling:

var contactUsUriString =
    Url.RouteUrl("" /* route name, add if needed */,
                 new // route values, add more if needed
                     {
                         action = "Contact-Us",
                         controller = "About"
                     },
                 Request.Url.Scheme);

Or alternatively even more compact:

var contactUsUriString =
    Url.Action("Contact-Us", "About",
               routeValues: null /* specify if needed */,
               protocol: Request.Url.Scheme);

Of course we could change the action name and routing etc to maintain lower case, or do it from IIS or so, but doing this would be too much to the point this blog post is concerned about

Hope this was useful to you.

Now that we're done, click this out ;)

, , ,