5

I am attempting to write a javascript heavy portion of my Asp.net MVC Web App (this portion of the website is a RIA using Extjs). However, I have come up to a standstill at the correct way to handle URLs in the javascript.

For example, right now I have an Ajax call to the List action in the ObjectsController, which resides in the Reading area. The List action takes a parameter of documentId (int). As of right now, this maps to /Reading/Objects/List since I have no changed routing yet (the site is too young at the moment to finalize routes). Normally in a view, to put this URL in a string I would do @Html.Action("List", "Objects", new { area = "Reading", documentId = 3).

However, this doesn't work when dealing with javascript, since javascript isn't parsed by a viewengine.

To get around this, I have a very small view that returns javascript constants, such as URLs, that is loaded prior to my main application's js files. The issue is that I can't call Html.Action for this action because at constant creation time I (obviously) do not know what documentId the ajax calls are going to be, and if you exclude documentId from the Html.Action call an exception occurs. The documentId could change during the normal workflow of the application.

How do I handle this? I don't want to hardcode the URL to /Reading/Objects/List because if I change my routing for this (for a more user friendly json API), or this web app isn't hosted on the root of the domain, the URL will no longer be valid.

How does everyone else handle MVC URLs in their javascript calls?

3
  • 1
    Have a look at the answer to this question stackoverflow.com/questions/376644/…. I think this is what you need. Commented Nov 24, 2010 at 5:58
  • Does the List action method also return documentId's that could be used for further ajax calls? Commented Nov 24, 2010 at 8:35
  • I'm not sure how that link helps, as at the time that code generates URLS it does not have parameter information and thus I will have the same issue, unless Url.RouteUrl() can form the URL without a parameter (which is worth trying when I get home). the List action returns JSON containing the Id and Names of objects related to that specific documentId Commented Nov 24, 2010 at 13:01

3 Answers 3

6

Here's a safe technique that I've been using. Even if your route changes, your JavaScript will automatically conform to the new route:

<script>
var url = '@Url.Action("List", "Objects", new { area = "Reading", documentId = "_documentId_")';
var id = 100;
var finalUrl = url.replace('_documentId_', id);
</script>

"_documentId_" is essentially a dummy placeholder. Then inside my JavaScript, I replace "_documentId_" with the proper id value once I know what it is. This way, regardless of how your route is configured, your URL will conform.


Update: Dec 20

I just saw this interesting blog post. The author built a library that allows you to build routes inside of your JavaScript file with intellisense support in VisualStudio.

http://weblogs.asp.net/zowens/archive/2010/12/20/asp-net-mvc-javascript-routing.aspx

Sign up to request clarification or add additional context in comments.

2 Comments

That's an interesting idea actually!
Just thought that I would add that if you want to be able to access mvc model value in your url.action then you need to do this on the .cshtml page and not in an external js file you can then do: var url = '@Url.Action("Action","Controller", new {Name = @Model.Name })';
2

Personally I use unobtrusive javascript and avoid mixing markup with javascript. AJAX calls are normally triggered by clicking on some buttons or links:

@Html.ActionLink("click me", "List", "Objects", 
    new { area = "Reading", documentId = 3 }, new { id = "foo" })

and then in a separate js file I would attach and handle the onclick event (example with jquery):

$(function() {
    $('#foo').click(function() {
        $('#resultDiv').load(this.href);
        return false;    
    });
});

As you can I didn't need to use any hardcoded URL in my javascript file. URLs should always be handled by the routing engine and generated with html helpers.

If it was a <form> instead of a link I would simply handle the onsubmit event (the same way) and use the form's action attribute to get the URL.


UPDATE:

After pointing out in the comments section that the documentId is known only at client-side you could do this:

@Html.ActionLink("click me", "List", "Objects", 
    new { area = "Reading" }, new { id = "foo" })

And then:

$(function() {
    $('#foo').click(function() {
        $('#resultDiv').load(this.href, { documentId: '123' });
        return false;    
    });
});

8 Comments

OP does not know the documentId action parameter value at the point .ActionLink() is called.
Since I am creating a javascript-only RIA, this is not an option. The GUI and the parts of the GUI that will be created all via Javascript, thus ActionLink.
And like Crescent Fresh pointed out, at the time the View engine is used, I do not know what documentId will be used when I use my ajax call.
@KallDrexx, sorry I misunderstood your question. I've updated my answer to take this into account. You could then exclude those parameters when generating the link and pass them as additional arguments when performing the AJAX request.
I'll have to test this out but I don't think this will work. When I do @Html.Action() without the documentId field the view engine crashes because it is expecting a documentId for this route, due to it being a required parameter for the action. I don't want to have to make all the parameters for my JSON actions optional because that means I have to do a lot more error checking for each issue for the sole purpose of URL abstraction.
|
0

Turns out, this was all solved by using Url.Action() instead of Html.Action(). Url.Action() is (so far) allowing me to generate URLS without all of the parameters. I am assuming that this only works when the route does not specify the parameters in the target URL itself.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.