niedziela, 25 listopada 2012

Metoda jQuery.ajax()

Jedną z największych zalet jQuery, jakie do tej pory miałem okazję wykorzystać, jest asynchroniczne odwołanie się kodu napisanego w javascript do metod, napisanych w C#. W najprostszej postaci (metoda javascript -> metoda c#) służy do tego jQuery.ajax.

Jak to działa?
Na stronie c# piszemy statyczną funkcję, którą oznaczamy atrybutem "Web Method", ktora w najprostszej postaci będzie wyglądać tak:

    public partial class WebMethodCommonHelper : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
        [WebMethod]
        public static string GetActualDateTime()
        {
            return DateTime.Now.ToShortTimeString();
        }
    }

Odwołanie się do tej funkcji za pomocą javascriptu będzie natomiast wyglądało w ten sposób:

function GetDateTimeFromPage() {
  $.ajax({
                        type: 'POST',
                        url: 'WebMethodCommonHelper.aspx/GetActualDateTime',
                        data: JSON.stringify({ }),
                        contentType: 'application/json; charset=utf-8',
                        dataType: 'json',
                        success: function (data) {
                            var dateTimeFromPage =  data.d.Value
                            setDateTime(dateTimeFromPage);
                        }
                    });
}

function setDateTime(dateTimeToSet)
{
//TODO: tutaj wykorzystujemy date, pobrana ze strony
}

Krótki opis, kodu, który widzimy powyżej:
a) Tworzymy stronę aspx, na której umieszamy statyczną web methodę z atrybutem [Web Method]. To ta metoda jest odpowiedzialna za "część serwerową".
b) po stronie javascriptu tworzmy 2 metody, o nazwach "GetDateTimeFromPage()" oraz "setDateTime". Jedna będzie odpowiedzialna, za pobranie danych z metody c# o nazwie "GetActualDateTime", natomiast druga będzie wykorzystywała te dane bezpośrednio na stronie ( "setDateTime").
 Metoda $.ajax w najprostszej formie, pobiera 4 parametry:
- type: 'POST' -> tryb pracy protokołu http (POST lub GET)
- url - adres naszej web methody, poprzedzony adresem do strony aspx na której się znajduje (jeżeli strona jest w odpowiednim katalogu, jak to często bywa np. w aplikacjach sharpoint, to wtedy adres może wyglądać np tak: '/_layouts/Branding/Common/WebMethodCommonHelper.aspx/GetActualDateTime'
- data - parametry, jakie przekazujemy do web methody z poziomu javascriptu (zostaną opisane później przy bardziej zaawansowanym przypadku)
-contentType: 'application/json; charset=utf-8' - kodowanie (tego zazwyczaj nie zmieniamy)
- dataType: 'json' - rodzaj danych (tego zazwyczaj nie zmieniamy)
- success: function (data) {
                           var dateTimeFromPage =  data.d;
                            setDateTime(dateTimeFromPage);
                        }
- fragment kodu, odpowiedzialny, za to, co powinno się zadziać, w przypadku, gdy metoda wykona się poprawnie. W naszym przypadku, tworzymy zmienną  'dateTimeFromPage' i przypisujemy do niej wartości, jakie zwróciła nam nasza 'Web Method', a nast. przekazujemy tą wartość do metody pomocniczej, która wykorzysta ją dalej w naszym kodzie.
Co ważne, dane które dostajemy z powrotem to: "data.d". Dla typów wbudowanych, np. 'int32', 'string' itp. dane zwracane są jako "data.d". Dla klas, należy się odwołać to zmiennych wewnątrz klasy (jeżeli klasa, którą zwracamy ma publiczną własciwość o nazie "wartosc" to odwołamy się do niej poprzez var wartosc = data.d.wartosc").

Ok, skoro najprostszy przykład mamy już za sobą, to teraz spróbujmy jakiś bardziej zaawansowany przykład, np. z wykorzystaniem sharepointa:
a) kod javasctipt

function getCurrency()
{
                    var urlLink = window.location.protocol + "//" + window.location.host + _spPageContextInfo.siteServerRelativeUrl; //_spPageContextInfo.webServerRelativeUrl;
                    $.ajax({
                        type: 'POST',
                        url: '/_layouts/Branding/Common/WebMethodCommonHelper.aspx/GetCurrency',
                        data: JSON.stringify({ url: urlLink }),
                        contentType: 'application/json; charset=utf-8',
                        dataType: 'json',
                        success: function (data) {
                            var currency = parseFloat(data.d.Value);
                            setCurrency(currency);
                        }
                    });
}
function setCurrency(currency)
{
 //TODO: tutaj ustawimy przelicznik
}

b) kod c#
     public partial class WebMethodCommonHelper : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
        [WebMethod]
        public static CurrencyHelper GetCurrency(string url)
        {
            using (SPSite oSiteCollection = new SPSite(url))
            {
                using (SPWeb web = oSiteCollection.OpenWeb())
                {
                    double rate = 4.56; //CurrencyHelper.GetRate(web);
                    CurrencyHelper lineHelper = new CurrencyHelper() { Value = rate, HfName = "Rate" };
                    return lineHelper;
                }
            }
        }
        [Serializable]
        public class CurrencyHelper
        {
            public string HfName { get; set; }
            public double Value { get; set; }
        }
}

Ok. Przejdźmy do analizy kodu:
Tym razem najpierw tworzymy metodę javascript. Ponieważ będziemy wykorzystywać sharpointa, bedziemy potrzebowali utworzyć obiekty SpSite oraz SpWeb. W tym celu, wykorzystamy zmienne shapointowe dostępne w języku javascript (tylko dla sharepoint 2010 lub nowszego). Mam na myśli:
_spPageContextInfo.siteServerRelativeUrl - zwraca adres SpSite
_spPageContextInfo.webServerRelativeUrl - zwraca adres SpWeb
Z pomocą tych zmiennych tworzymy pełny adres http, strony jaka nas interesuje (w zależności od tego, na której witrynie znajduje się lista do której zamierzamy się odwołać, czy na bierzącej witrynie, czy na 'root webie').
Mają odpowiedni adres http przekazujemy go do metody jQuery.ajax jako parametr url (ważne, aby nazwa parametru w jQuery.ajax oraz metodzie c# były takie same).
Jako rezultat otrzymujemy klasę napisaną przez użytkownika, więc w ceku odczytania wartości odwołujemy się do jej publicznej właściwości (Value), którą nast. przekazujemy do metody docelowej.

W przypadku kodu c#, ponownie tworzymy metodę statyczna z adrybutem "Web Method", oraz parametrem "url". Wykorzystując parametr, otwieramy SpSite oraz SpWeb'a, a nast. wykonujemy na nim interesujące nas operacje. Jako wynik, zwracamy obiekt stworzonej przez nas klasy CurrencyHelper.


p.s. Należy pamiętać, o dołączeniu odpowiednich referencji, tj. pliku z biblioteką "jQuery" po stronie javascriptu, oraz odpowiednich namespece po stronie c#.