poniedziałek, 29 sierpnia 2011

JSON obsługa w ASP MVC 2

Z pewnością wielu z Was spotkało się z formatem JSON - JavaScript Object Notation. Format ten przekazywany jest w postaci tekstowej. Ponieważ dane przekazywane są jako zwykły tekst, mniej zajmują a co za tym idzie przesyłanie jest szybsze niż w przypadku standardowego XMLa. Obecnie wykorzystywany jest w aplikacjach silnie korzystających z AJAXu.
ASP MVC 2 pozwala w łatwy sposób na przesyłanie danych w omawianym formacie. Wystarczy tylko zwrócić dane w metodzie kontrolera jako typ JsonResult.

Zobaczmy na bardzo prosty przykład:
W kontrolerze umieścimy metodę zwracającą tablicę liczb od 1 do 20, a następnie stworzymy z niej listę w naszym widoku:


Code:
public ActionResult GetJSONData()
        {
            int[] data = Enumerable.Range(1, 20).ToArray();
            JsonResult jSonResult = new JsonResult();
            jSonResult.Data = data;
            jSonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;

            return jSonResult;
        }

Widok Home:


Code:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%: ViewData["Message"] %></h2>
    <br />

    <div id="JsonDiv">
        <ul>
            
        </ul>
    </div>

    <script type="text/javascript">
        $(document).ready(function () {
            $.getJSON("/Home/GetJSONData", null, function (data) {
                $.each(data, function (index, value) {
                    var newValue = "<li>" + value + "</li>";
                    $("#JsonDiv ul").append(newValue);
                });
            });
        });
    </script>
</asp:Content>

Parsowanie JSONa przy użyciu jQuery jest niezwykle proste. W tym przypadku:
  1. Czekamy aż dokument całkowicie się załaduje w celu dodania do diva listy naszych liczb
  2. Pobieramy dane przekazane przez metodę za pomocą metody getJSON - przekazując jako argument nazwę kontrolera i metody która zwraca dane
  3. Za pomocą funkcji each iterujemy po kolekcji zawierającej nasze dane i dodajemy je do listy
Rezultat:





Jak widać proste i bardzo łatwe, podobnie ma się rzecz do obiektów o bardziej skomplikowanej strukturze:

W modelu tworzymy definicję klasy Person:


Code:
public class Person
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDate { get; set; }
        public List<Car> Cars { get; set; }

        public Person(int id, string firstName, string lastName, DateTime birthDate)
        {
            Id = id;
            FirstName = firstName;
            LastName = lastName;
            BirthDate = birthDate;
        }
    }

Następnie klasę Car:


Code:
public class Car
    {
        public string Make { get; set; }
        public int Year { get; set; }
        public string Model { get; set; }
    }

Ostatnia klasa będzie klasą generującą testowe dane:


Code:
public class FakeData
    {
        public List<Person> GetFakeData(int fakeEntitiesCount)
        {
            List<Person> lPerson = new List<Person>();
            Random r = new Random();
            string[] firstNames = { "Jacek", "Maciek", "Paweł", "Sylwek" };
            string[] lastNames = { "Kowalski", "Markowski", "Piotrkowski" };
            string[] carMakers = { "VW", "Ford", "Fiat" };
            string[] carModels = { "Jetta", "Bora", "Focus", "Panda" };

            for (int i = 0; i < fakeEntitiesCount; i++)
            {
                Person p = new Person(i, firstNames[r.Next(0, firstNames.Length)], lastNames[r.Next(0, lastNames.Length)],
                    DateTime.Now.AddYears(r.Next(19, 50)));
                p.Cars = new List<Car>();
                int carCount = r.Next(0, 4);
                for (int j = 0; j < carCount; j++)
                {
			        p.Cars.Add(new Car { Make = carMakers[r.Next(0, carMakers.Length)], 
                        Model = carModels[r.Next(0, carModels.Length)],
                        Year = DateTime.Now.AddYears(r.Next(0,8)).Year});
                }
                lPerson.Add(p);
            }

            return lPerson;
        }
    }

Oczywiście testowe dane - to tylko testowe dany, raczej każdy wie że Fiat nie produkuje Bory :).

W metodzie Index naszego kontrolera w zmiennej sesji przechowamy dane odnośnie osób i ich samochodów:


Code:
public ActionResult Index()
        {
            Session["Data"] = new FakeData().GetFakeData(20);
            ViewData["Message"] = "Przekazywanie danych w formacie JSON";

            return View();
        }

Metoda CarEvidence zwróci nam listę osób:


Code:
public ActionResult CarEvidence()
        {
            List<Person> lPerson = new List<Person>();
            if (Session["Data"] != null)
            {
                lPerson = (List<Person>)Session["Data"];
                List<SelectListItem> lPersonList = new List<SelectListItem>();
                foreach (var person in lPerson)
                {
                    lPersonList.Add(new SelectListItem { Text = person.FirstName + " " + person.LastName, Value = person.Id.ToString() });
                }
                ViewData["PersonList"] = lPersonList;
            }

            return View(lPerson);
        }

Łatwo zauważyć, że jeżeli ktoś od razu wejdzie na stronę CarEvidence nie otrzyma żadnych danych - jest to jednak tylko przykład w realnej aplikacji z pewnością źródłem danych będzie baza danych bądź plik XML.

Za pomocą metody GetPersonCars wydobędziemy informacje o samochodach danego kierowcy:


Code:
[HttpGet]
        public ActionResult GetPersonCars(int idPerson)
        {
            JsonResult jSonData = new JsonResult();
            jSonData.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            if (Session["Data"] != null)
            {
                List<Car> lCars = ((List<Person>)Session["Data"]).Where(x => x.Id == idPerson).SingleOrDefault().Cars;
                jSonData.Data = lCars;
            }

            return jSonData;
        }

Definicja widoku CarEvidence:


Code:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcApplication2.Models.Person>>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
	CarEvidence
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>CarEvidence</h2>
    <div>
        <%: Html.Label("Wybierz osobę: ")%>
        <br />
        <%: Html.DropDownList("ddlPersonList", (List<SelectListItem>)ViewData["PersonList"]) %>
    </div>

    <div id="PersonCars">
        <ul>
        </ul>
    </div>

    
    <script type="text/javascript">
        $("#ddlPersonList").change(function () {
            var id = $("#ddlPersonList").val();
            $.getJSON("/Home/GetPersonCars/", { idPerson: $(this).val() }, function (data) {
                $("#PersonCars ul li").remove();
                $.each(data, function (index, value) {
                    var car = "<li>" + value.Year + " " + value.Make + " " + value.Model + "</li>";
                    $("#PersonCars ul").append(car);
                });
            });
        });    
    </script>

</asp:Content>

Po uruchomieniu aplikacji otrzymamy następujący widok:





Zmieniając wybór na liście, możemy oglądać dane o samochodach danego użytkownika.
Kilka uwag co do kodu jQuery tutaj użytego:
- Metoda change przechwytuje zdarzenie zmiany elementu na liście
- funkcja val() pobiera wartość - id osoby danego elementu listy
- metoda getJSON pobiera JSON przesyłając do metody kontrolera informację o wybranej osobie: {idPerson: $(this).val()}
- za pomocą metody each()  - wyświetlamy informacje o samochodach wybranego kierowcy

Jak widać korzystanie z JSONa nie jest trudne. Można za pomocą niego uzyskać bardzo ciekawe efekty bez potrzeby przeładowywania całej strony. System serializacji wbudowany w ASP MVC z łatwością deserializuje i serializuje dane przekazywane w tym formacie - co czyni jego użycie jeszcze prostszym. jQuery dopełnia zestaw narzędzi pozwalając w prosty sposób wyświetlić użytkownikowi otrzymane dane czy też przekazać je do kontrolera w celu otrzymania żądanych dnaych.

Miłego eksperymentowania.

Brak komentarzy:

Prześlij komentarz