Ustawianie adresu URL ajax dla jQuery w pliku JS za pomocą ASP.NET MVC

Podczas wykonywania Ajax wywołania do działania MVC obecnie mam mój javascript wewnątrz widoku, a nie wewnątrz jego własnego pliku JS.

Bardzo łatwo jest to zrobić:

var xhr = $.ajax({
     url: '<%= Url.Action("DisplayItem","Home") %>/' + el1.siblings("input:hidden").val(),
     data: { ajax: "Y" },
     cache: false,
     success: function(response) { displayMore(response, el1, xhr) }
});

...następnie włączenie adresu URL w wywołaniu ajax za pomocą Url.Action() wewnątrz JS jest dość łatwe. Jak mogę przenieść to zrobić własny plik JS, gdy bez twardego kodowania adresu URL?

Author: Schotime, 2008-12-18

5 answers

W ten sposób w pełni wykorzystuje się Routing MVC, dzięki czemu można w pełni wykorzystać Framework MVC. Zainspirowany odpowiedzią stusmith ' a.

Tutaj mam akcję w ApplicationController dla dynamicznego javascript dla tego adresu URL:

 /application/js

Włączam tutaj pliki statyczne, ponieważ chcę pobrać tylko jeden główny plik javascript. Możesz wybrać, aby po prostu zwrócić dynamiczne rzeczy, jeśli chcesz:

     /// <summary>
    /// Renders out javascript
    /// </summary>
    /// <returns></returns>
    [OutputCache(CacheProfile = "Script")]
    [ActionName("js")]
    public ContentResult RenderJavascript()
    {
        StringBuilder js = new StringBuilder();

        // load all my static javascript files                    
        js.AppendLine(IO.File.ReadAllText(Request.MapPath("~/Scripts/rr/cart.js")));
        js.AppendLine(";");

        // dynamic javascript for lookup tables
        js.AppendLine(GetLookupTables());
        js.AppendLine(";");

        return new ContentResult()
        {
            Content = js.ToString(),
            ContentType = "application/x-javascript"
        };
    }

Jest to funkcja pomocnicza, która tworzy naszą tabelę wyszukiwania. Wystarczy dodać linię dla każdej trasy, którą chcesz do użycia.

    [NonAction]
    private string GetLookupTables() 
    {
        StringBuilder js = new StringBuilder();

        // list of keys that correspond to route URLS
        var urls = new[] {
            new { key = "updateCart", url = Url.RouteUrl("cart-route", new { action = "updatecart" }) },
            new { key = "removeItem", url = Url.RouteUrl("cart-route", new { action = "removeitem" }) }
        };

        // lookup table function
        js.AppendLine("// URL Lookuptable");
        js.AppendLine("$.url=function(url) {");
        js.AppendLine("var lookupTable = " + new JavaScriptSerializer().Serialize(urls.ToDictionary(x=>x.key, x=>x.url)) + ";");
        js.AppendLine("return lookupTable[url];");
        js.AppendLine("}");

        return js.ToString();
    }

Generuje to następujący dynamiczny javascript, który jest w zasadzie tylko tabelą wyszukiwania z dowolnego klucza do adresu URL, którego potrzebuję do mojej metody akcji :

// URL Lookuptable
$.url=function(url) {
var lookupTable = {"updateCart":"/rrmvc/store/cart/updatecart","removeItem":"/rrmvc/store/cart/removeitem"};
return lookupTable[url];
}

W koszyku.js mogę mieć taką funkcję. Zauważ, że parametr url jest pobrany z tabeli wyszukiwania:

 var RRStore = {};
 RRStore.updateCart = function(sku, qty) {

    $.ajax({

        type: "POST",
        url: $.url("updateCart"),
        data: "sku=" + sku + "&qty=" + qty,
        dataType: "json"

        // beforeSend: function (){},
        // success: function (){},
        // error: function (){},
        // complete: function (){},
    });

    return false;

};

Mogę zadzwonić z dowolnego miejsca po prostu:

 RRStore.updateCart(1001, 5);

Wydawało mi się, że to jedyny sposób, który pozwoliłby mi używać routingu w czysty sposób. Dynamiczne tworzenie adresów URL w javascript jest trudne i trudne do przetestowania. Typy testowania mogą być dodawane w warstwie gdzieś tutaj, aby łatwo ułatwić testowanie.

 19
Author: Simon_Weaver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-16 07:14:48

Sposób, w jaki to robię, to generowanie adresu URL po stronie serwera i zapisywanie w wygenerowanym HTML przy użyciu atrybutu danych HTML5 , np: (składnia Razor)

<li class='customClass' data-url='@Url.Action("DisplayItems", "Home", new { id = Model.Id })'>...</li>

Następnie możesz użyć funkcji jQuery attr (), aby podnieść adres url, np:

$(".customClass").click(function () {
    $.ajax({
        url: $(this).attr("data-url"),
        success: function (data) {
            // do stuff
        }
    });
});

Jeśli generujesz klienta HTML w odpowiedzi na wywołania AJAX, możesz dołączyć odpowiednie adresy URL do ładunku JSON i wypełnić atrybut data- w ten sam sposób.

 34
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-18 07:22:58

Zawiń wywołanie AJAX w funkcję, która przyjmuje adres URL (i wszelkie inne dane) jako parametr(y) i zwraca odpowiedź. Następnie w Twoim widoku wywołaj funkcję, zamiast wywoływać bezpośrednio wywołanie AJAX.

function doAjax( url, data, elem, callback )
{
    return $.ajax({
        url: url,
        data: { ajax: data },
        cache: false,
        success: function(response) { callback(response, elem, xhr); }
    });
}

...

<input type='button' value='Go get it' onclick='doAjax( <%= Url.Action ...

Nie jestem pewien, czy jest to lepsze niż wywołanie Ajax na stronie zamiast w pliku JS, chyba że często używasz dokładnie tego samego wzorca.

 6
Author: tvanfosson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-18 01:53:18

Użyj wzorca modułu.


// separate js file
var PAGE_MODULE = (function () {
  var url = {},
      init = function(url) { ... },
      load = function() {
      $.ajax({
           url: url,
           ...
           });
      }

      return { init: init };
})();


// calling init goes on the page itself
PAGE_MODULE.init(" %: Url.Action(...) %>");

Ogólnie rzecz biorąc, wbudowana obsługa onclick nie jest dobra w javascript, ponieważ używasz funkcji globalnej.


onclick='doAjax( 

Polecam lekturę http://jqfundamentals.com/book/index.html#N20D82 aby lepiej zrozumieć wzór modułu.

 3
Author: Kyle Nunery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-15 04:49:46

Oto inny sposób:

Na stronie wzorcowej Dodaj obszar dla skryptów wbudowanych:

<head>
  ...
  <asp:ContentPlaceHolder runat="server" ID="_inlineScripts" />
  ...
</head>

Następnie w Page_Load Utwórz funkcję użytkową:

protected void Page_Load( object sender, EventArgs e )
{
  AddInlineScript( string.Format( "$.url=function(url){{return '{0}'+url;}}", GetBaseUri() ) );
  ...
}

private Uri GetBaseUri()
{
  var requestUrl = Request.Url.AbsoluteUri;
  var i = requestUrl.IndexOf( request.Path );

  return new Uri( requestUrl.Substring( 0, i ) );
}

private void AddInlineScript( string content )
{
  var script = new HtmlGenericControl( "script" );

  script.Attributes.Add( "type", "text/javascript" );
  script.InnerHtml = content;

  _inlineScripts.Controls.Add( script );
}

Teraz możesz używać tej funkcji w Ajaxie:

$.ajax({
  url: $.url('path/to/my-handler'),
  ...
});
 -1
Author: stusmith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-31 12:44:33