Click here to Skip to main content
15,881,882 members
Articles / Web Development / ASP.NET

Accessing MVC Routing URLs in JavaScript

Rate me:
Please Sign up or sign in to vote.
4.64/5 (6 votes)
5 May 2011CPOL2 min read 62.6K   5   3
Using the UrlHelper class to query the routing engine and generate the correct URLs for us

As we all know, the MVC Framework for ASP.NET uses the .NET routing engine, introduced in .NET 3.5, for generating and resolving URLs at runtime. As such, we can use the UrlHelper class to query the routing engine and generate the correct URL for us. For example:

ASP.NET
<a href='<%= Url.Action("MyAction", "MyController") %>'>Foo<a>

will generate the following at runtime:

HTML
<a href='http://www.codeproject.com/MyController/MyAction'>Foo<a>

This is great, as it means any changes we make to our routing rules are 'automagically' reflected in the affected URLs. Additionally, the routing engine will take into account where on our web-server our application is located. In the example above, if our application were deployed to a virtual directory called MySite, the routing engine would generate the following:

HTML
<a href='http://www.codeproject.com/MySite/MyController/MyAction'>Foo<a>

Well, that's fine and dandy, but what happens when we want to use URLs in JavaScript? Consider the following simple scenario: A simple web-page with a text-box and a button. You enter a person ID into the text-box, click the button, and via an AJAX request, the person's details are displayed on the page. We have a controller:

C#
// C#
public class PersonController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Details(int id)
    {
        PersonService service = new PersonService();
        Person person = service.GetPerson(id);
        return PartialView(person);
    }
}
VB.NET
' Visual Basic
Public Class PersonController
    Inherits System.Web.Mvc.Controller

    Public Function Index() As ActionResult
        Return View()
    End Function

    Public Function Details(ByVal id As Integer) As ActionResult
        Dim service As PersonService = New PersonService()
        Dim person As Person = service.GetPerson(id)
        Return PartialView(person)
    End Function

End Class

A view:

ASP.NET
<!-- C# -->
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>Person</title>
    <script type="text/javascript" 
       src='<%= Url.Content("~/Scripts/jquery-1.5.1.min.js") %>'></script>
</head>
<body>
    <div>
        <input id="personId" type="text" />
        <input id="getPersonButton" type="button" value="Get Person" />
    </div>
    <div id="personPlaceHolder">
    </div>
    <script type="text/javascript">
        $(document).ready(function () {
            $("#getPersonButton").click(function () {
                var id = $("#personId").val();
                getPerson(id);
            });
        });

        function getPerson(id) {
            var url = '/Person/Details/' + id;
            $.get(url, function (result) {
                $("#personPlaceHolder").html(result);
            });
        }

    </script>
</body>
</html>
ASP.NET
<!-- Visual Basic -->
<%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>Person</title>
    <script type="text/javascript" 
      src='<%= Url.Content("~/Scripts/jquery-1.5.1.min.js") %>'></script>
</head>
<body>
    <div>
        <input id="personId" type="text" />
        <input id="getPersonButton" type="button" value="Get Person" />
    </div>
    <div id="personPlaceHolder">
    </div>
    <script type="text/javascript">
        $(document).ready(function () {
            $("#getPersonButton").click(function () {
                var id = $("#personId").val();
                getPerson(id);
            });
        });

        function getPerson(id) {
            var url = '/Person/Details/' + id;
            $.get(url, function (result) {
                $("#personPlaceHolder").html(result);
            });
        }

    </script>
</body>
</html>

And a partial view:

ASP.NET
<!-- C# -->
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Person>" %>
<fieldset>
    <legend>Person</legend>
    <table>
        <tbody>
            <tr>
                <th>
                    ID
                </th>
                <td>
                    <%: Html.DisplayFor(model => model.Id) %>
                </td>
            </tr>
            <tr>
                <th>
                    Name
                </th>
                <td>
                    <%: Html.DisplayFor(model => model.Name) %>
                </td>
            </tr>
            <tr>
                <th>
                    Date of Birth
                </th>
                <td>
                    <%: Html.DisplayFor(model => model.DateOfBirth) %>
                </td>
            </tr>
        </tbody>
    </table>
</fieldset>
ASP.NET
<!-- Visual Basic -->
<%@ Control Language="VB" 
    Inherits="System.Web.Mvc.ViewUserControl(Of Person)" %>
<fieldset>
    <legend>Person</legend>
    <table>
        <tbody>
            <tr>
                <th>
                    ID
                </th>
                <td>
                    <%: Html.DisplayFor(Function(model) model.Id)%>
                </td>
            </tr>
            <tr>
                <th>
                    Name
                </th>
                <td>
                    <%: Html.DisplayFor(Function(model) model.Name)%>
                </td>
            </tr>
            <tr>
                <th>
                    Date of Birth
                </th>
                <td>
                    <%: Html.DisplayFor(Function(model) model.DateOfBirth)%>
                </td>
            </tr>
        </tbody>
    </table>
</fieldset>

Now look closely at the getPerson() function:

JavaScript
function getPerson(id) {
    var url = '/Person/Details/' + id;
    $.get(url, function (result) {
        $("#personPlaceHolder").html(result);
    });
}

You will see that the URL is hard-coded and the person ID is simply concatenated onto the end. Clearly, this will break if we either change our routing rules or deploy the application to anywhere other than the root of our web-server. One solution is to place an ASP.NET call to the routing engine within the string literal used for the URL:

JavaScript
// C#
function getPerson(id) {
    var url = '<%= Url.Action("Details", "Person", 
                 new { Id = -999 }) %>'.replace('-999', id);
    $.get(url, function (result) {
        $("#personPlaceHolder").html(result);
    });
}
JavaScript
// Visual Basic
function getPerson(id) {
    var url = '<%= Url.Action("Details", "Person", 
                 New With {.Id = -999}) %>'.replace('-999', id);
    $.get(url, function (result) {
        $("#personPlaceHolder").html(result);
    });
}

Note how we use a 'dummy' value of "-999" for the person ID, to ensure that the routing engine resolves the URL correctly. We then replace this value with the 'real' ID at runtime.

However, what if we want to move the getPerson() function to a separate .js file? Our ASP.NET call to the routing engine will no longer work as the .js file is not processed on the server side. The solution is to use a JavaScript helper object:

JavaScript
// C#
function UrlHelper() {
    this.personDetails = function (id) {
        return '<%= Url.Action("Details", "Person", 
                  new { Id = -999 }) %>'.replace('-999', id);
    }
}
JavaScript
// Visual Basic
function UrlHelper() {
    this.personDetails = function (id) {
        return '<%= Url.Action("Details", "Person", 
                   New With {.Id = -999}) %>'.replace('-999', id);
    }
}

The helper object must still remain in the view, as the call to the routing engine needs to be processed on the server side. However, our getPerson() function can now be modified to use the helper object and be safely moved into a separate .js file:

JavaScript
function getPerson(id) {
    var urlHelper = new UrlHelper();
    var url = urlHelper.personDetails(id);
    $.get(url, function (result) {
        $("#personPlaceHolder").html(result);
    });
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Sentenryu2-Oct-12 7:42
Sentenryu2-Oct-12 7:42 
GeneralMy vote of 4 Pin
robvon1-May-12 18:37
robvon1-May-12 18:37 
QuestionNot bad. Bit too much fluff Pin
robvon1-May-12 18:36
robvon1-May-12 18:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.