Aracılığıyla paylaş


Windows Phone 8 Uygulamasından Web API'sine Çağrı Yapma (C#)

tarafından Robert McMurray

Bu öğreticide, bir Windows Phone 8 uygulamasına kitap kataloğu sağlayan bir ASP.NET Web API uygulamasından oluşan eksiksiz bir uçtan uca senaryo oluşturmayı öğreneceksiniz.

Genel Bakış

ASP.NET Web API'si gibi RESTful hizmetleri, sunucu tarafı ve istemci tarafı uygulamalar için mimariyi soyutlayarak geliştiriciler için HTTP tabanlı uygulamalar oluşturmayı basitleştirir. İletişim için özel bir yuva tabanlı protokol oluşturmak yerine, Web API geliştiricilerinin uygulamaları için gerekli HTTP yöntemlerini yayımlamaları yeterlidir (örneğin: GET, POST, PUT, DELETE) ve istemci uygulama geliştiricilerinin yalnızca uygulamaları için gerekli OLAN HTTP yöntemlerini kullanmaları gerekir.

Bu uçtan uca öğreticide, Aşağıdaki projeleri oluşturmak için Web API'sini kullanmayı öğreneceksiniz:

Önkoşullar

  • Windows Phone 8 SDK'sının yüklü olduğu Visual Studio 2013
  • Hyper-V yüklü bir 64 bit sistemde Windows 8 veya üzeri
  • Ek gereksinimlerin listesi için Windows Phone SDK 8.0 indirme sayfasındaki Sistem Gereksinimleri bölümüne bakın.

Not

Web API'si ile Windows Phone 8 proje arasındaki bağlantıyı yerel sisteminizde test edecekseniz, test ortamınızı ayarlamak için Windows Phone 8 Öykünücüsünüzü Yerel Bilgisayardaki Web API Uygulamalarına Bağlama makalesindeki yönergeleri izlemeniz gerekir.

1. Adım: Web API Kitapçısı Projesi Oluşturma

Bu uçtan uca öğreticinin ilk adımı, tüm CRUD işlemlerini destekleyen bir Web API projesi oluşturmaktır; bu öğreticinin 2. Adımında Windows Phone uygulama projesini bu çözüme ekleyeceksiniz.

  1. Visual Studio 2013 açın.

  2. Dosya'ya, yeni'ye ve ardından Proje'ye tıklayın.

  3. Yeni Proje iletişim kutusu görüntülendiğinde, Yüklü'leri, şablonlar'ı, Visual C# ve ardından Web'i genişletin.

    Menüde dosya yolunu gösteren ve yeni projeyi oluşturma adımlarını vurgulayan 'yeni proje' iletişim kutusunun ekran görüntüsü.
    Genişletmek için resme tıklayın
  4. Web Uygulaması ASP.NET vurgulayın, proje adı olarak BookStore yazın ve Tamam'a tıklayın.

  5. Yeni ASP.NET Projesi iletişim kutusu görüntülendiğinde, Web API şablonunu seçin ve tamam'a tıklayın.

    Şablon klasörünü ve çekirdek başvuruyu seçmek için şablon seçeneklerini ve onay kutularını gösteren A S P noktalı NET proje kitapçısı iletişim kutusunun ekran görüntüsü.
    Genişletmek için resme tıklayın
  6. Web API projesi açıldığında, örnek denetleyiciyi projeden kaldırın:

    1. Çözüm gezgininde Denetleyiciler klasörünü genişletin.
    2. ValuesController.cs dosyasına sağ tıklayın ve ardından Sil'e tıklayın.
    3. Silme işlemini onaylamanız istendiğinde Tamam'a tıklayın.
  7. Web API projesine XML veri dosyası ekleme; bu dosya, kitapçı kataloğunun içeriğini içerir:

    1. Çözüm gezgininde App_Data klasörüne sağ tıklayın, Ekle'ye ve ardından Yeni Öğe'ye tıklayın.

    2. Yeni Öğe Ekle iletişim kutusu görüntülendiğinde, XML Dosyası şablonunu vurgulayın.

    3. dosyayı Books.xmladlandırın ve Ekle'ye tıklayın.

    4. Books.xml dosyası açıldığında, dosyadaki kodu MSDN'deki örnek books.xml dosyasındaki XML ile değiştirin:

      <?xml version="1.0" encoding="utf-8"?>
      <catalog>
        <book id="bk101">
          <author>Gambardella, Matthew</author>
          <title>XML Developer's Guide</title>
          <genre>Computer</genre>
          <price>44.95</price>
          <publish_date>2000-10-01</publish_date>
          <description>
            An in-depth look at creating applications
            with XML.
          </description>
        </book>
        <book id="bk102">
          <author>Ralls, Kim</author>
          <title>Midnight Rain</title>
          <genre>Fantasy</genre>
          <price>5.95</price>
          <publish_date>2000-12-16</publish_date>
          <description>
            A former architect battles corporate zombies,
            an evil sorceress, and her own childhood to become queen
            of the world.
          </description>
        </book>
        <book id="bk103">
          <author>Corets, Eva</author>
          <title>Maeve Ascendant</title>
          <genre>Fantasy</genre>
          <price>5.95</price>
          <publish_date>2000-11-17</publish_date>
          <description>
            After the collapse of a nanotechnology
            society in England, the young survivors lay the
            foundation for a new society.
          </description>
        </book>
        <book id="bk104">
          <author>Corets, Eva</author>
          <title>Oberon's Legacy</title>
          <genre>Fantasy</genre>
          <price>5.95</price>
          <publish_date>2001-03-10</publish_date>
          <description>
            In post-apocalypse England, the mysterious
            agent known only as Oberon helps to create a new life
            for the inhabitants of London. Sequel to Maeve
            Ascendant.
          </description>
        </book>
        <book id="bk105">
          <author>Corets, Eva</author>
          <title>The Sundered Grail</title>
          <genre>Fantasy</genre>
          <price>5.95</price>
          <publish_date>2001-09-10</publish_date>
          <description>
            The two daughters of Maeve, half-sisters,
            battle one another for control of England. Sequel to
            Oberon's Legacy.
          </description>
        </book>
        <book id="bk106">
          <author>Randall, Cynthia</author>
          <title>Lover Birds</title>
          <genre>Romance</genre>
          <price>4.95</price>
          <publish_date>2000-09-02</publish_date>
          <description>
            When Carla meets Paul at an ornithology
            conference, tempers fly as feathers get ruffled.
          </description>
        </book>
        <book id="bk107">
          <author>Thurman, Paula</author>
          <title>Splish Splash</title>
          <genre>Romance</genre>
          <price>4.95</price>
          <publish_date>2000-11-02</publish_date>
          <description>
            A deep sea diver finds true love twenty
            thousand leagues beneath the sea.
          </description>
        </book>
        <book id="bk108">
          <author>Knorr, Stefan</author>
          <title>Creepy Crawlies</title>
          <genre>Horror</genre>
          <price>4.95</price>
          <publish_date>2000-12-06</publish_date>
          <description>
            An anthology of horror stories about roaches,
            centipedes, scorpions  and other insects.
          </description>
        </book>
        <book id="bk109">
          <author>Kress, Peter</author>
          <title>Paradox Lost</title>
          <genre>Science Fiction</genre>
          <price>6.95</price>
          <publish_date>2000-11-02</publish_date>
          <description>
            After an inadvertant trip through a Heisenberg
            Uncertainty Device, James Salway discovers the problems
            of being quantum.
          </description>
        </book>
        <book id="bk110">
          <author>O'Brien, Tim</author>
          <title>Microsoft .NET: The Programming Bible</title>
          <genre>Computer</genre>
          <price>36.95</price>
          <publish_date>2000-12-09</publish_date>
          <description>
            Microsoft's .NET initiative is explored in
            detail in this deep programmer's reference.
          </description>
        </book>
        <book id="bk111">
          <author>O'Brien, Tim</author>
          <title>MSXML3: A Comprehensive Guide</title>
          <genre>Computer</genre>
          <price>36.95</price>
          <publish_date>2000-12-01</publish_date>
          <description>
            The Microsoft MSXML3 parser is covered in
            detail, with attention to XML DOM interfaces, XSLT processing,
            SAX and more.
          </description>
        </book>
        <book id="bk112">
          <author>Galos, Mike</author>
          <title>Visual Studio 7: A Comprehensive Guide</title>
          <genre>Computer</genre>
          <price>49.95</price>
          <publish_date>2001-04-16</publish_date>
          <description>
            Microsoft Visual Studio 7 is explored in depth,
            looking at how Visual Basic, Visual C++, C#, and ASP+ are
            integrated into a comprehensive development
            environment.
          </description>
        </book>
      </catalog>
      
    5. XML dosyasını kaydedin ve kapatın.

  8. Kitapçı modelini Web API projesine ekleyin; Bu model, kitapçı uygulaması için Oluşturma, Okuma, Güncelleştirme ve Silme (CRUD) mantığını içerir:

    1. Çözüm gezgininde Modeller klasörüne sağ tıklayın, Ekle'ye ve ardından Sınıf'a tıklayın.

    2. Yeni Öğe Ekle iletişim kutusu görüntülendiğinde sınıf dosyasını BookDetails.cs olarak adlandırın ve Ekle'ye tıklayın.

    3. BookDetails.cs dosyası açıldığında, dosyadaki kodu aşağıdakiyle değiştirin:

      using System;
      using System.Collections.Generic;
      using System.ComponentModel.DataAnnotations;
      using System.Linq;
      using System.Xml;
      using System.Xml.Linq;
      using System.Xml.XPath;
      using System.Web;
      
      namespace BookStore.Models
      {
          /// <summary>
          /// Define a class that will hold the detailed information for a book.
          /// </summary>
          public class BookDetails
          {
              [Required]
              public String Id { get; set; }
              [Required]
              public String Title { get; set; }
              public String Author { get; set; }
              public String Genre { get; set; }
              public Decimal Price { get; set; }
              public DateTime PublishDate { get; set; }
              public String Description { get; set; }
          }
      
          /// <summary>
          /// Define an interface which contains the methods for the book repository.
          /// </summary>
          public interface IBookRepository
          {
              BookDetails CreateBook(BookDetails book);
              IEnumerable<BookDetails> ReadAllBooks();
              BookDetails ReadBook(String id);
              BookDetails UpdateBook(String id, BookDetails book);
              Boolean DeleteBook(String id);
          }
      
          /// <summary>
          /// Define a class based on the book repository interface which contains the method implementations.
          /// </summary>
          public class BookRepository : IBookRepository
          {
              private string xmlFilename = null;
              private XDocument xmlDocument = null;
      
              /// <summary>
              /// Define the class constructor.
              /// </summary>
              public BookRepository()
              {
                  try
                  {
                      // Determine the path to the books.xml file.
                      xmlFilename = HttpContext.Current.Server.MapPath("~/app_data/books.xml");
                      // Load the contents of the books.xml file into an XDocument object.
                      xmlDocument = XDocument.Load(xmlFilename);
                  }
                  catch (Exception ex)
                  {
                      // Rethrow the exception.
                      throw ex;
                  }
              }
      
              /// <summary>
              /// Method to add a new book to the catalog.
              /// Defines the implementation of the POST method.
              /// </summary>
              public BookDetails CreateBook(BookDetails book)
              {
                  try
                  {
                      // Retrieve the book with the highest ID from the catalog.
                      var highestBook = (
                          from bookNode in xmlDocument.Elements("catalog").Elements("book")
                          orderby bookNode.Attribute("id").Value descending
                          select bookNode).Take(1);
                      // Extract the ID from the book data.
                      string highestId = highestBook.Attributes("id").First().Value;
                      // Create an ID for the new book.
                      string newId = "bk" + (Convert.ToInt32(highestId.Substring(2)) + 1).ToString();
                      // Verify that this book ID does not currently exist.
                      if (this.ReadBook(newId) == null)
                      {
                          // Retrieve the parent element for the book catalog.
                          XElement bookCatalogRoot = xmlDocument.Elements("catalog").Single();
                          // Create a new book element.
                          XElement newBook = new XElement("book", new XAttribute("id", newId));
                          // Create elements for each of the book's data items.
                          XElement[] bookInfo = FormatBookData(book);
                          // Add the element to the book element.
                          newBook.ReplaceNodes(bookInfo);
                          // Append the new book to the XML document.
                          bookCatalogRoot.Add(newBook);
                          // Save the XML document.
                          xmlDocument.Save(xmlFilename);
                          // Return an object for the newly-added book.
                          return this.ReadBook(newId);
                      }
                  }
                  catch (Exception ex)
                  {
                      // Rethrow the exception.
                      throw ex;
                  }
                  // Return null to signify failure.
                  return null;
              }
      
              /// <summary>
              /// Method to retrieve all of the books in the catalog.
              /// Defines the implementation of the non-specific GET method.
              /// </summary>
              public IEnumerable<BookDetails> ReadAllBooks()
              {
                  try
                  {
                      // Return a list that contains the catalog of book ids/titles.
                      return (
                          // Query the catalog of books.
                          from book in xmlDocument.Elements("catalog").Elements("book")
                          // Sort the catalog based on book IDs.
                          orderby book.Attribute("id").Value ascending
                          // Create a new instance of the detailed book information class.
                          select new BookDetails
                          {
                              // Populate the class with data from each of the book's elements.
                              Id = book.Attribute("id").Value,
                              Author = book.Element("author").Value,
                              Title = book.Element("title").Value,
                              Genre = book.Element("genre").Value,
                              Price = Convert.ToDecimal(book.Element("price").Value),
                              PublishDate = Convert.ToDateTime(book.Element("publish_date").Value),
                              Description = book.Element("description").Value
                          }).ToList();
                  }
                  catch (Exception ex)
                  {
                      // Rethrow the exception.
                      throw ex;
                  }
              }
      
              /// <summary>
              /// Method to retrieve a specific book from the catalog.
              /// Defines the implementation of the ID-specific GET method.
              /// </summary>
              public BookDetails ReadBook(String id)
              {
                  try
                  {
                      // Retrieve a specific book from the catalog.
                      return (
                          // Query the catalog of books.
                          from book in xmlDocument.Elements("catalog").Elements("book")
                          // Specify the specific book ID to query.
                          where book.Attribute("id").Value.Equals(id)
                          // Create a new instance of the detailed book information class.
                          select new BookDetails
                          {
                              // Populate the class with data from each of the book's elements.
                              Id = book.Attribute("id").Value,
                              Author = book.Element("author").Value,
                              Title = book.Element("title").Value,
                              Genre = book.Element("genre").Value,
                              Price = Convert.ToDecimal(book.Element("price").Value),
                              PublishDate = Convert.ToDateTime(book.Element("publish_date").Value),
                              Description = book.Element("description").Value
                          }).Single();
                  }
                  catch
                  {
                      // Return null to signify failure.
                      return null;
                  }
              }
      
              /// <summary>
              /// Populates a book BookDetails class with the data for a book.
              /// </summary>
              private XElement[] FormatBookData(BookDetails book)
              {
                  XElement[] bookInfo =
                  {
                      new XElement("author", book.Author),
                      new XElement("title", book.Title),
                      new XElement("genre", book.Genre),
                      new XElement("price", book.Price.ToString()),
                      new XElement("publish_date", book.PublishDate.ToString()),
                      new XElement("description", book.Description)
                  };
                  return bookInfo;
              }
      
              /// <summary>
              /// Method to update an existing book in the catalog.
              /// Defines the implementation of the PUT method.
              /// </summary>
              public BookDetails UpdateBook(String id, BookDetails book)
              {
                  try
                  {
                      // Retrieve a specific book from the catalog.
                      XElement updateBook = xmlDocument.XPathSelectElement(String.Format("catalog/book[@id='{0}']", id));
                      // Verify that the book exists.
                      if (updateBook != null)
                      {
                          // Create elements for each of the book's data items.
                          XElement[] bookInfo = FormatBookData(book);
                          // Add the element to the book element.
                          updateBook.ReplaceNodes(bookInfo);
                          // Save the XML document.
                          xmlDocument.Save(xmlFilename);
                          // Return an object for the updated book.
                          return this.ReadBook(id);
                      }
                  }
                  catch (Exception ex)
                  {
                      // Rethrow the exception.
                      throw ex;
                  }
                  // Return null to signify failure.
                  return null;
              }
      
              /// <summary>
              /// Method to remove an existing book from the catalog.
              /// Defines the implementation of the DELETE method.
              /// </summary>
              public Boolean DeleteBook(String id)
              {
                  try
                  {
                      if (this.ReadBook(id) != null)
                      {
                          // Remove the specific child node from the catalog.
                          xmlDocument
                              .Elements("catalog")
                              .Elements("book")
                              .Where(x => x.Attribute("id").Value.Equals(id))
                              .Remove();
                          // Save the XML document.
                          xmlDocument.Save(xmlFilename);
                          // Return a success status.
                          return true;
                      }
                      else
                      {
                          // Return a failure status.
                          return false;
                      }
                  }
                  catch (Exception ex)
                  {
                      // Rethrow the exception.
                      throw ex;
                  }
              }
          }
      }
      
    4. BookDetails.cs dosyasını kaydedin ve kapatın.

  9. Kitapçı denetleyicisini Web API projesine ekleyin:

    1. Çözüm gezgininde Denetleyiciler klasörüne sağ tıklayın, ekle'ye ve ardından Denetleyici'ye tıklayın.

    2. yapı iskelesi ekle iletişim kutusu görüntülendiğinde, Web API 2 Denetleyicisi - Boş'u vurgulayın ve ekle'ye tıklayın.

    3. Denetleyici Ekle iletişim kutusu görüntülendiğinde denetleyiciyi BooksController olarak adlandırın ve Ekle'ye tıklayın.

    4. BooksController.cs dosyası açıldığında, dosyadaki kodu aşağıdakiyle değiştirin:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Net;
      using System.Net.Http;
      using System.Web.Http;
      using BookStore.Models;
      
      namespace BookStore.Controllers
      {
          public class BooksController : ApiController
          {
              private BookRepository repository = null;
      
              // Define the class constructor.
              public BooksController()
              {
                  this.repository = new BookRepository();
              }
      
              /// <summary>
              /// Method to retrieve all of the books in the catalog.
              /// Example: GET api/books
              /// </summary>
              [HttpGet]
              public HttpResponseMessage Get()
              {
                  IEnumerable<BookDetails> books = this.repository.ReadAllBooks();
                  if (books != null)
                  {
                      return Request.CreateResponse<IEnumerable<BookDetails>>(HttpStatusCode.OK, books);
                  }
                  else
                  {
                      return Request.CreateResponse(HttpStatusCode.NotFound);
                  }
              }
      
              /// <summary>
              /// Method to retrieve a specific book from the catalog.
              /// Example: GET api/books/5
              /// </summary>
              [HttpGet]
              public HttpResponseMessage Get(String id)
              {
                  BookDetails book = this.repository.ReadBook(id);
                  if (book != null)
                  {
                      return Request.CreateResponse<BookDetails>(HttpStatusCode.OK, book);
                  }
                  else
                  {
                      return Request.CreateResponse(HttpStatusCode.NotFound);
                  }
              }
      
              /// <summary>
              /// Method to add a new book to the catalog.
              /// Example: POST api/books
              /// </summary>
              [HttpPost]
              public HttpResponseMessage Post(BookDetails book)
              {
                  if ((this.ModelState.IsValid) && (book != null))
                  {
                      BookDetails newBook = this.repository.CreateBook(book);
                      if (newBook != null)
                      {
                          var httpResponse = Request.CreateResponse<BookDetails>(HttpStatusCode.Created, newBook);
                          string uri = Url.Link("DefaultApi", new { id = newBook.Id });
                          httpResponse.Headers.Location = new Uri(uri);
                          return httpResponse;
                      }
                  }
                  return Request.CreateResponse(HttpStatusCode.BadRequest);
              }
      
              /// <summary>
              /// Method to update an existing book in the catalog.
              /// Example: PUT api/books/5
              /// </summary>
              [HttpPut]
              public HttpResponseMessage Put(String id, BookDetails book)
              {
                  if ((this.ModelState.IsValid) && (book != null) && (book.Id.Equals(id)))
                  {
                      BookDetails modifiedBook = this.repository.UpdateBook(id, book);
                      if (modifiedBook != null)
                      {
                          return Request.CreateResponse<BookDetails>(HttpStatusCode.OK, modifiedBook);
                      }
                      else
                      {
                          return Request.CreateResponse(HttpStatusCode.NotFound);
                      }
                  }
                  return Request.CreateResponse(HttpStatusCode.BadRequest);
              }
      
              /// <summary>
              /// Method to remove an existing book from the catalog.
              /// Example: DELETE api/books/5
              /// </summary>
              [HttpDelete]
              public HttpResponseMessage Delete(String id)
              {
                  BookDetails book = this.repository.ReadBook(id);
                  if (book != null)
                  {
                      if (this.repository.DeleteBook(id))
                      {
                          return Request.CreateResponse(HttpStatusCode.OK);
                      }
                  }
                  else
                  {
                      return Request.CreateResponse(HttpStatusCode.NotFound);
                  }
                  return Request.CreateResponse(HttpStatusCode.BadRequest);
              }
          }
      }
      
    5. BooksController.cs dosyasını kaydedin ve kapatın.

  10. Hataları denetlemek için Web API'sini oluşturun.

2. Adım: Windows Phone 8 Kitapçı Kataloğu Projesi Ekleme

Bu uçtan uca senaryonun bir sonraki adımı, Windows Phone 8 için katalog uygulaması oluşturmaktır. Bu uygulama, varsayılan kullanıcı arabirimi için Windows Phone Databound Uygulaması şablonunu ve veri kaynağı olarak bu öğreticinin 1. Adımında oluşturduğunuz Web API'sini kullanır.

  1. Çözüm gezgininde BookStore çözümüne sağ tıklayın, ardından Ekle'ye ve ardından Yeni Proje'ye tıklayın.

  2. Yeni Proje iletişim kutusu görüntülendiğinde, Yüklü'leri, visual C# öğesini genişletin ve Windows Phone.

  3. Databound Uygulaması Windows Phone vurgulayın, ad olarak BookCatalog yazın ve Tamam'a tıklayın.

  4. Json.NET NuGet paketini BookCatalog projesine ekleyin:

    1. Çözüm gezgininde BookCatalog projesi için Başvurular'a sağ tıklayın ve ardından NuGet Paketlerini Yönet'e tıklayın.
    2. NuGet Paketlerini Yönet iletişim kutusu görüntülendiğinde Çevrimiçi bölümünü genişletin ve nuget.org vurgulayın.
    3. Arama alanına Json.NET girin ve arama simgesine tıklayın.
    4. Arama sonuçlarında Json.NET vurgulayın ve yükle'ye tıklayın.
    5. Yükleme tamamlandığında Kapat'a tıklayın.
  5. BookCatalog projesine BookDetails modelini ekleyin; bu, kitapçı sınıfının genel bir modelini içerir:

    1. Çözüm gezgininde BookCatalog projesine sağ tıklayın, Ekle'ye ve ardından Yeni Klasör'e tıklayın.

    2. Yeni klasöre Models adını verin.

    3. Çözüm gezgininde Modeller klasörüne sağ tıklayın, Ekle'ye ve ardından Sınıf'a tıklayın.

    4. Yeni Öğe Ekle iletişim kutusu görüntülendiğinde sınıf dosyasını BookDetails.cs olarak adlandırın ve Ekle'ye tıklayın.

    5. BookDetails.cs dosyası açıldığında, dosyadaki kodu aşağıdakiyle değiştirin:

      using System;
      using System.Text;
      
      namespace BookCatalog.Models
      {
          /// <summary>
          /// Define a class that will hold the detailed information for a book.
          /// </summary>
          public class BookDetails
          {
              public String Id { get; set; }
              public String Title { get; set; }
              public String Author { get; set; }
              public String Genre { get; set; }
              public Decimal Price { get; set; }
              public DateTime PublishDate { get; set; }
              public String Description { get; set; }
          }
      }
      
    6. BookDetails.cs dosyasını kaydedin ve kapatın.

  6. MainViewModel.cs sınıfını, BookStore Web API uygulamasıyla iletişim kurma işlevselliğini içerecek şekilde güncelleştirin:

    1. Çözüm gezgininde ViewModels klasörünü genişletin ve ardından MainViewModel.cs dosyasına çift tıklayın.

    2. MainViewModel.cs dosyası açıldığında, dosyadaki kodu aşağıdakiyle değiştirin; Sabitin değerini apiUrl Web API'nizin gerçek URL'si ile güncelleştirmeniz gerektiğini unutmayın:

      using System;
      using System.Collections.ObjectModel;
      using System.ComponentModel;
      using System.Net;
      using System.Net.NetworkInformation;
      using BookCatalog.Resources;
      using System.Collections.Generic;
      using Newtonsoft.Json;
      using BookCatalog.Models;
      
      namespace BookCatalog.ViewModels
      {
          public class MainViewModel : INotifyPropertyChanged
          {
              const string apiUrl = @"http://www.contoso.com/api/Books";
      
              public MainViewModel()
              {
                  this.Items = new ObservableCollection<ItemViewModel>();
              }
      
              /// <summary>
              /// A collection for ItemViewModel objects.
              /// </summary>
              public ObservableCollection<ItemViewModel> Items { get; private set; }
      
              public bool IsDataLoaded
              {
                  get;
                  private set;
              }
      
              /// <summary>
              /// Creates and adds a few ItemViewModel objects into the Items collection.
              /// </summary>
              public void LoadData()
              {
                  if (this.IsDataLoaded == false)
                  {
                      this.Items.Clear();
                      this.Items.Add(new ItemViewModel() { ID = "0", LineOne = "Please Wait...", LineTwo = "Please wait while the catalog is downloaded from the server.", LineThree = null });
                      WebClient webClient = new WebClient();
                      webClient.Headers["Accept"] = "application/json";
                      webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadCatalogCompleted);
                      webClient.DownloadStringAsync(new Uri(apiUrl));
                  }
              }
      
              private void webClient_DownloadCatalogCompleted(object sender, DownloadStringCompletedEventArgs e)
              {
                  try
                  {
                      this.Items.Clear();
                      if (e.Result != null)
                      {
                          var books = JsonConvert.DeserializeObject<BookDetails[]>(e.Result);
                          int id = 0;
                          foreach (BookDetails book in books)
                          {
                              this.Items.Add(new ItemViewModel()
                              {
                                  ID = (id++).ToString(),
                                  LineOne = book.Title,
                                  LineTwo = book.Author,
                                  LineThree = book.Description.Replace("\n", " ")
                              });
                          }
                          this.IsDataLoaded = true;
                      }
                  }
                  catch (Exception ex)
                  {
                      this.Items.Add(new ItemViewModel()
                      {
                          ID = "0",
                          LineOne = "An Error Occurred",
                          LineTwo = String.Format("The following exception occured: {0}", ex.Message),
                          LineThree = String.Format("Additional inner exception information: {0}", ex.InnerException.Message)
                      });
                  }
              }
      
              public event PropertyChangedEventHandler PropertyChanged;
              private void NotifyPropertyChanged(String propertyName)
              {
                  PropertyChangedEventHandler handler = PropertyChanged;
                  if (null != handler)
                  {
                      handler(this, new PropertyChangedEventArgs(propertyName));
                  }
              }
          }
      }
      
    3. MainViewModel.cs dosyasını kaydedin ve kapatın.

  7. Uygulama adını özelleştirmek için MainPage.xaml dosyasını güncelleştirin:

    1. Çözüm gezgininde MainPage.xaml dosyasına çift tıklayın.

    2. MainPage.xaml dosyası açıldığında aşağıdaki kod satırlarını bulun:

      <StackPanel Grid.Row="0" Margin="12,17,0,28">
          <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/> 
          <TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
      </StackPanel>
      
    3. Bu satırları aşağıdakilerle değiştirin:

      <StackPanel Grid.Row="0" Margin="12,17,0,28">
          <TextBlock Text="Book Store" Style="{StaticResource PhoneTextTitle1Style}"/> 
          <TextBlock Text="Current Catalog" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle2Style}"/>
      </StackPanel>
      
    4. MainPage.xaml dosyasını kaydedin ve kapatın.

  8. Görüntülenen öğeleri özelleştirmek için DetailsPage.xaml dosyasını güncelleştirin:

    1. Çözüm gezgininde DetailsPage.xaml dosyasına çift tıklayın.

    2. DetailsPage.xaml dosyası açıldığında aşağıdaki kod satırlarını bulun:

      <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
          <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
          <TextBlock Text="{Binding LineOne}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
      </StackPanel>
      
    3. Bu satırları aşağıdakilerle değiştirin:

      <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
          <TextBlock Text="Book Store" Style="{StaticResource PhoneTextTitle1Style}"/>
          <TextBlock Text="{Binding LineOne}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle2Style}"/>
      </StackPanel>
      
    4. DetailsPage.xaml dosyasını kaydedin ve kapatın.

  9. Hataları denetlemek için Windows Phone uygulamasını oluşturun.

3. Adım: Uçtan Uca Çözümü Test Etme

Bu öğreticinin Önkoşullar bölümünde belirtildiği gibi, yerel sisteminizde Web API'si ile Windows Phone 8 proje arasındaki bağlantıyı test ederken, test ortamınızı ayarlamak için Windows Phone 8 Öykünücüsünün Yerel Bilgisayardaki Web API Uygulamalarına Bağlanma makalesindeki yönergeleri izlemeniz gerekir.

Test ortamını yapılandırdıktan sonra, Windows Phone uygulamasını başlangıç projesi olarak ayarlamanız gerekir. Bunu yapmak için, çözüm gezgininde BookCatalog uygulamasını vurgulayın ve ardından StartUp Projesi Olarak Ayarla'ya tıklayın:

Windows Phone uygulamasını 'başlangıç projesi olarak ayarla' seçeneğinde ayarlamak için menü seçeneklerini gösteren çözüm gezgini penceresinin ekran görüntüsü.
Genişletmek için resme tıklayın

F5 tuşuna bastığınızda Visual Studio, uygulama verileri Web API'nizden alınırken "Lütfen Bekleyin" iletisini görüntüleyen Windows Phone Öykünücüsü'ne başlar:

Telefon öykünücüsünün üzerine gelip Kitap Mağazası başlığını ve 'lütfen bekleyin' iletisini gösteren çözüm gezgini penceresinin ekran görüntüsü.
Genişletmek için resme tıklayın

Her şey başarılı olursa kataloğun görüntülendiğini görmeniz gerekir:

Telefon öykünücüsünün üzerinde yer alan ve katalogdaki başlıkları içeren Kitap Mağazası'nı gösteren çözüm gezgini penceresinin ekran görüntüsü.
Genişletmek için resme tıklayın

Herhangi bir kitap başlığına dokunursanız, uygulama kitap açıklamasını görüntüler:

Çözüm gezgini penceresinin üzerinde telefon öykünücüsünün ekran görüntüsü, kitap başlığı ve açıklaması görüntüleniyor.
Genişletmek için resme tıklayın

Uygulama Web API'nizle iletişim kuramazsa bir hata iletisi görüntülenir:

Çözüm gezgini penceresinde görüntülenen ve 'Bir Hata Oluştu' ifadesini ve hatanın kısa bir açıklamasını gösteren telefon öykünücüsünün ekran görüntüsü.
Genişletmek için resme tıklayın

Hata iletisine dokunursanız, hatayla ilgili ek ayrıntılar görüntülenir:

Çözüm gezgini iletişim kutusunun üzerindeki telefon öykünücüsünün ekran görüntüsü, 'Bir Hata Oluştu' ifadesini ve ardından hatanın ayrıntılarını gösterir.
Genişletmek için resme tıklayın