简体   繁体   中英

Handling ASP.NET MVC Routing in External JavaScript

What's the best way to avoid hardcoding URL's in JavaScript (primarily used when making AJAX calls)?

In the past:

  1. Render JavaScript variable with result of @Url.Action or @Url.RouteUrl
  2. Pass result of @Url.Action or @Url.RouteUrl to JavaScript in init/ctor.

Is there a better way?

It would be good to do something like this:

var url = $.routes("actionName", "controllerName") // or "routeName" for named routes
$.post(url, { id = 1 }, function() { //.. });

Which of course isn't really possible (JavaScript doesn't have direct access the to the ViewContext and thus doesn't have access to the route tables).

But i'm wondering if there's a way i can kind of setup my own "route table" for JavaScript, with only the ones i know it would need? (eg i set it up in the View)

How do people handle this?

in-spite of injecting javascript in views i rather prefer - let HTML do its job and javascript do its. Below is the pattern.

For Links

/*A cssclass=ajaxlink is added to all those links which we want to ajaxify*/

//html in view
<a class='ajaxlink' href='@Url.Action("Action","Controller")'>I am An Ajax Link</a>

//generated clean html
<a class='ajaxlink' href='/controller/action'>I am An Ajax Link</a>


//Js


jQuery('.ajaxlink').live('click',function(e){
    e.preventDefault();    /*Prevent default behavior of links*/
    var url= $(e.target).attr('href');
   /*
          Now u have url, do post or get: 
          then append received data in some DOM element.
   */
});

//Controller

public ActionResult()
{
       if(Request.IsAjax())
       {    
            /*Return partial content*/
            return View(); 
       }
       else
       {
             return View("SomeOther_View.cshtml");

             /*
                At this point you may reject this request or return full view
                whatever you feel is okie.
             */
       }
}

This way both type of users can be handled javascript enabled and javascript disabled.

Same can be done for forms.

Implementing a Javascript routing engine wouldn't be too difficult. First, serialize the Routes from C# to Javascript. Second, recreate the Url.Action method.

However, that's a bit overkill for any of the projects I've worked on. My team's projects have always rendered a common Javascript variable that holds all necessary URL's.
This approach ensures strongly-typed action methods and lends better to refactoring too.

This is easier said than achieved in practice, but your website should be fully functional with JavaScript turned off. When this is achieved, you should be able to add AJAX support to your website and re-use existing HREF attributes in your anchor tags or action attributes in your FORM tags. The website will be easier to maintain as you won't need to update links in your JavaScript files.

I've decided to implement my own UrlFactory, using ASP.NET helpers directly (Html/Url) in my code, now I don't have the src with me, I'll post'em tomorrow.

Pros on this: I can track each and every url easily and perform some rewriting in a centralized fashion.

Example of usage:

@{
  string myAjaxUrl = UrlFactory.GetUrl (ActionName, ControllerName, new { query-params });
}

Then using 'em in javascript with

var jsUrl = '@myAjaxUrl';

Once you've defined your own Factory, you can hijack "important" urls (eg. for rewriting), and leave common to the Url helper implementation.

However for having this fully client side, there's an extra step of rendering a Js routing context, for accessing client side variables.

EDIT: As promised my very simple Url class builder:

public static class UrlFactory
{
    public static string GetUrl(string Action, string Controller, object RouteValues)
    {
        UrlHelper Url = new UrlHelper(HttpContext.Current.Request.RequestContext);
        return Url.Action(Action, Controller, RouteValues);
    }

    // Common URLS for Denied et similars.
    public static string GetDeniedUrl(PEDUtenti Utente, object RouteValues)
    {
        return GetUrl(Utente, "Denied", "Errors", RouteValues);
    }
    public static string GetDeniedUrl(object RouteValues)
    {
        return GetUrl("Denied", "Errors", RouteValues);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM