Windows Phone 8 애플리케이션에서 Web API 호출(C#)Calling Web API from a Windows Phone 8 Application (C#)

Robert McMurrayby Robert McMurray

이 자습서에서는 Windows Phone 8 응용 프로그램에 책 카탈로그를 제공 하는 ASP.NET Web API 응용 프로그램으로 구성 되는 완전 한 종단 간 시나리오를 만드는 방법에 대해 알아봅니다.In this tutorial, you will learn how to create a complete end-to-end scenario consisting of an ASP.NET Web API application that provides a catalog of books to a Windows Phone 8 application.

개요Overview

ASP.NET Web API와 같은 RESTful 서비스는 서버 쪽 및 클라이언트 쪽 응용 프로그램에 대 한 아키텍처를 추상화 하 여 개발자를 위한 HTTP 기반 응용 프로그램 만들기를 간소화 합니다.RESTful services like ASP.NET Web API simplify the creation of HTTP-based applications for developers by abstracting the architecture for server-side and client-side applications. 통신을 위한 전용 소켓 기반 프로토콜을 만드는 대신 웹 API 개발자는 응용 프로그램에 대 한 필수 HTTP 메서드 (예: GET, POST, PUT, DELETE)를 게시 하 고 클라이언트 응용 프로그램 개발자만을 사용 해야 합니다. 응용 프로그램에 필요한 HTTP 메서드입니다.Instead of creating a proprietary socket-based protocol for communication, Web API developers simply need to publish the requisite HTTP methods for their application, (for example: GET, POST, PUT, DELETE), and client application developers only need to consume the HTTP methods that are necessary for their application.

이 종단 간 자습서에서는 Web API를 사용 하 여 다음 프로젝트를 만드는 방법에 대해 설명 합니다.In this end-to-end tutorial, you will learn how to use Web API to create the following projects:

사전 요구 사항Prerequisites

  • Windows Phone 8 SDK가 설치 된 Visual Studio 2013Visual Studio 2013 with the Windows Phone 8 SDK installed
  • Hyper-v가 설치 된 64 비트 시스템의 Windows 8 이상Windows 8 or later on a 64-bit system with Hyper-V installed
  • 추가 요구 사항 목록은 WINDOWS PHONE SDK 8.0 다운로드 페이지의 시스템 요구 사항 섹션을 참조 하세요.For a list of additional requirements, see the System Requirements section on the Windows Phone SDK 8.0 download page.

Note

Web API와 로컬 시스템의 Windows Phone 8 프로젝트 간의 연결을 테스트 하려는 경우 테스트 환경을 설정 하려면 Windows Phone 8 에뮬레이터를 로컬 컴퓨터의 웹 Api 응용 프로그램에 연결 문서의 지침을 따라야 합니다.If you are going to test the connectivity between Web API and Windows Phone 8 projects on your local system, you will need to follow the instructions in the Connecting the Windows Phone 8 Emulator to Web API Applications on a Local Computer article to set up your testing environment.

1 단계: Web API 서 점 프로젝트 만들기Step 1: Creating the Web API Bookstore Project

이 종단 간 자습서의 첫 번째 단계는 모든 CRUD 작업을 지 원하는 Web API 프로젝트를 만드는 것입니다. 이 자습서의 2 단계 에서는이 솔루션에 Windows Phone 응용 프로그램 프로젝트를 추가 합니다.The first step of this end-to-end tutorial is to create a Web API project that supports all of the CRUD operations; note that you will add the Windows Phone application project to this solution in Step 2 of this tutorial.

  1. Visual Studio 2013를 엽니다.Open Visual Studio 2013.

  2. 파일, 새로 만들기, 프로젝트를 차례로 클릭 합니다.Click File, then New, and then Project.

  3. 새 프로젝트 대화 상자가 표시 되 면 설치 됨, 템플릿, C#시각적 개체, 을 차례로 확장 합니다.When the New Project dialog box is displayed, expand Installed, then Templates, then Visual C#, and then Web.

    확장 하려면 이미지를 클릭 합니다.Click image to expand
  4. ASP.NET 웹 응용 프로그램을 강조 표시 하 고 프로젝트 이름으로 서 을 입력 한 다음 확인을 클릭 합니다.Highlight ASP.NET Web Application, enter BookStore for the project name, and then click OK.

  5. 새 ASP.NET 프로젝트 대화 상자가 표시 되 면 Web API 템플릿을 선택 하 고 확인을 클릭 합니다.When the New ASP.NET Project dialog box is displayed, select the Web API template, and then click OK.

    확장 하려면 이미지를 클릭 합니다.Click image to expand
  6. Web API 프로젝트가 열리면 프로젝트에서 샘플 컨트롤러를 제거 합니다.When the Web API project opens, remove the sample controller from the project:

    1. 솔루션 탐색기에서 컨트롤러 폴더를 확장 합니다.Expand the Controllers folder in the solution explorer.
    2. ValuesController.cs 파일을 마우스 오른쪽 단추로 클릭 한 다음 삭제를 클릭 합니다.Right-click the ValuesController.cs file, and then click Delete.
    3. 삭제를 확인 하는 메시지가 표시 되 면 확인 을 클릭 합니다.Click OK when prompted to confirm the deletion.
  7. Web API 프로젝트에 XML 데이터 파일을 추가 합니다. 이 파일에는 서 점 카탈로그의 내용이 포함 됩니다.Add an XML data file to the Web API project; this file contains the contents of the bookstore catalog:

    1. 솔루션 탐색기에서 App_Data 폴더를 마우스 오른쪽 단추로 클릭 하 고 추가를 클릭 한 다음 새 항목을 클릭 합니다.Right-click the App_Data folder in the solution explorer, then click Add, and then click New Item.

    2. 새 항목 추가 대화 상자가 표시 되 면 XML 파일 템플릿을 강조 표시 합니다.When the Add New Item dialog box is displayed, highlight the XML File template.

    3. Books.xml파일의 이름을 지정한 다음 추가를 클릭 합니다.Name the file Books.xml, and then click Add.

    4. Books.xml 파일을 열면 파일의 코드를 MSDN의 sample .xml 파일에 있는 xml로 바꿉니다.When the Books.xml file is opened, replace the code in the file with the XML from the sample books.xml file on MSDN:

      <?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 파일을 저장 하 고 닫습니다.Save and close the XML file.

  8. 웹 API 프로젝트에 서 점 모델을 추가 합니다. 이 모델은 응용 프로그램 응용 프로그램에 대 한 CRUD (만들기, 읽기, 업데이트 및 삭제) 논리를 포함 합니다.Add the bookstore model to the Web API project; this model contains the Create, Read, Update, and Delete (CRUD) logic for the bookstore application:

    1. 솔루션 탐색기에서 모델 폴더를 마우스 오른쪽 단추로 클릭 하 고 추가를 클릭 한 다음 클래스를 클릭 합니다.Right-click the Models folder in the solution explorer, then click Add, and then click Class.

    2. 새 항목 추가 대화 상자가 표시 되 면 클래스 파일의 이름을 BookDetails.cs로 지정한 다음 추가를 클릭 합니다.When the Add New Item dialog box is displayed, name the class file BookDetails.cs, and then click Add.

    3. BookDetails.cs 파일이 열리면 파일의 코드를 다음으로 바꿉니다.When the BookDetails.cs file is opened, replace the code in the file with the following:

      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 파일을 저장 하 고 닫습니다.Save and close the BookDetails.cs file.

  9. 웹 작업 컨트롤러를 웹 API 프로젝트에 추가 합니다.Add the bookstore controller to the Web API project:

    1. 솔루션 탐색기에서 컨트롤러 폴더를 마우스 오른쪽 단추로 클릭 하 고 추가를 클릭 한 다음 컨트롤러를 클릭 합니다.Right-click the Controllers folder in the solution explorer, then click Add, and then click Controller.

    2. 스 캐 폴드 추가 대화 상자가 표시 되 면 Web API 2 컨트롤러-비어 있음을 강조 표시 하 고 추가를 클릭 합니다.When the Add Scaffold dialog box is displayed, highlight Web API 2 Controller - Empty, and then click Add.

    3. 컨트롤러 추가 대화 상자가 표시 되 면 컨트롤러 이름을 bookscontroller로 지정한 다음 추가를 클릭 합니다.When the Add Controller dialog box is displayed, name the controller BooksController, and then click Add.

    4. BooksController.cs 파일이 열리면 파일의 코드를 다음으로 바꿉니다.When the BooksController.cs file is opened, replace the code in the file with the following:

      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 파일을 저장 하 고 닫습니다.Save and close the BooksController.cs file.

  10. 웹 API 응용 프로그램을 빌드하여 오류를 확인 합니다.Build the Web API application to check for errors.

2 단계: Windows Phone 8 서 점 카탈로그 프로젝트 추가Step 2: Adding the Windows Phone 8 Bookstore Catalog Project

이 종단 간 시나리오의 다음 단계는 Windows Phone 8 용 카탈로그 응용 프로그램을 만드는 것입니다.The next step of this end-to-end scenario is to create the catalog application for Windows Phone 8. 이 응용 프로그램은 기본 사용자 인터페이스에 대 한 Windows Phone 데이터 바인딩된 앱 템플릿을 사용 하며,이 자습서의 1 단계 에서 만든 웹 API 응용 프로그램을 데이터 원본으로 사용 합니다.This application will use the Windows Phone Databound App template for the default user interface, and it will use the Web API application that you created in Step 1 of this tutorial as the data source.

  1. 솔루션 탐색기에서의 서 솔루션을 마우스 오른쪽 단추로 클릭 하 고 추가를 클릭 한 다음 새 프로젝트를 클릭 합니다.Right-click the BookStore solution in the in the solution explorer, then click Add, and then New Project.

  2. 새 프로젝트 대화 상자가 표시 되 면 설치 됨, C#시각적 개체를 차례로 확장 한 다음 Windows Phone합니다.When the New Project dialog box is displayed, expand Installed, then Visual C#, and then Windows Phone.

  3. 데이터 바인딩된 앱 Windows Phone강조 표시 하 고 이름으로 bookcatalog 를 입력 한 다음 확인을 클릭 합니다.Highlight Windows Phone Databound App, enter BookCatalog for the name, and then click OK.

  4. Json.NET NuGet 패키지를 Bookcatalog 프로젝트에 추가 합니다.Add the Json.NET NuGet package to the BookCatalog project:

    1. 솔루션 탐색기에서 Bookcatalog 프로젝트에 대 한 참조 를 마우스 오른쪽 단추로 클릭 한 다음 NuGet 패키지 관리를 클릭 합니다.Right-click References for the BookCatalog project in the solution explorer, and then click Manage NuGet Packages.
    2. NuGet 패키지 관리 대화 상자가 표시 되 면 온라인 섹션을 확장 하 고 nuget.org를 강조 표시 합니다.When the Manage NuGet Packages dialog box is displayed, expand the Online section, and highlight nuget.org.
    3. 검색 필드에 Json.NET 를 입력 하 고 검색 아이콘을 클릭 합니다.Enter Json.NET in the search field and click the search icon.
    4. 검색 결과에서 Json.NET 를 강조 표시 하 고 설치를 클릭 합니다.Highlight Json.NET in the search results, and then click Install.
    5. 설치가 완료 되 면 닫기를 클릭 합니다.When the installation has completed, click Close.
  5. Bookdetails 프로젝트에 Bookdetails 모델 을 추가 합니다. 여기에는 클래스의 일반 모델 (:)이 포함 됩니다.Add the BookDetails model to the BookCatalog project; this contains a generic model of the bookstore class:

    1. 솔루션 탐색기에서 Bookcatalog 프로젝트를 마우스 오른쪽 단추로 클릭 하 고 추가를 클릭 한 다음 새 폴더를 클릭 합니다.Right-click the BookCatalog project in the solution explorer, then click Add, and then click New Folder.

    2. 새 폴더의 이름을 모델로 합니다.Name the new folder Models.

    3. 솔루션 탐색기에서 모델 폴더를 마우스 오른쪽 단추로 클릭 하 고 추가를 클릭 한 다음 클래스를 클릭 합니다.Right-click the Models folder in the solution explorer, then click Add, and then click Class.

    4. 새 항목 추가 대화 상자가 표시 되 면 클래스 파일의 이름을 BookDetails.cs로 지정한 다음 추가를 클릭 합니다.When the Add New Item dialog box is displayed, name the class file BookDetails.cs, and then click Add.

    5. BookDetails.cs 파일이 열리면 파일의 코드를 다음으로 바꿉니다.When the BookDetails.cs file is opened, replace the code in the file with the following:

      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 파일을 저장 하 고 닫습니다.Save and close the BookDetails.cs file.

  6. MainViewModel.cs 클래스를 업데이트 하 여 서 점 웹 API 응용 프로그램과 통신 하는 기능을 포함 합니다.Update the MainViewModel.cs class to include the functionality to communicate with the BookStore Web API application:

    1. 솔루션 탐색기에서 Viewmodels 폴더를 확장 한 다음 MainViewModel.cs 파일을 두 번 클릭 합니다.Expand the ViewModels folder in the solution explorer, and then double-click the MainViewModel.cs file.

    2. MainViewModel.cs 파일이 열리면 파일의 코드를 다음으로 바꿉니다. apiUrl 상수 값을 Web API의 실제 URL로 업데이트 해야 합니다.When the MainViewModel.cs file is opened, replace the code in the file with the following; note that you will need to update the value of the apiUrl constant with the actual URL of your Web API:

      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 파일을 저장 하 고 닫습니다.Save and close the MainViewModel.cs file.

  7. Mainpage 파일을 업데이트 하 여 응용 프로그램 이름을 사용자 지정 합니다.Update the MainPage.xaml file to customize the application name:

    1. 솔루션 탐색기에서 Mainpage .xaml 파일을 두 번 클릭 합니다.Double-click the MainPage.xaml file in the solution explorer.

    2. Mainpage .xaml 파일을 열면 다음 코드 줄을 찾습니다.When the MainPage.xaml file is opened, locate the following lines of code:

      <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. 해당 줄을 다음으로 바꿉니다.Replace those lines with the following:

      <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 파일을 저장 한 후 닫습니다.Save and close the MainPage.xaml file.

  8. DetailsPage 파일을 업데이트 하 여 표시 된 항목을 사용자 지정 합니다.Update the DetailsPage.xaml file to customize the displayed items:

    1. 솔루션 탐색기에서 DetailsPage 파일을 두 번 클릭 합니다.Double-click the DetailsPage.xaml file in the solution explorer.

    2. DetailsPage 파일이 열리면 다음 코드 줄을 찾습니다.When the DetailsPage.xaml file is opened, locate the following lines of code:

      <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. 해당 줄을 다음으로 바꿉니다.Replace those lines with the following:

      <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 파일을 저장 하 고 닫습니다.Save and close the DetailsPage.xaml file.

  9. 오류를 확인 하는 Windows Phone 응용 프로그램을 빌드합니다.Build the Windows Phone application to check for errors.

3 단계: 종단 간 솔루션 테스트Step 3: Testing the End-to-End Solution

이 자습서의 전제 조건 섹션에서 설명한 것 처럼 로컬 시스템에서 web api와 Windows Phone 8 프로젝트 간의 연결을 테스트할 때 테스트 환경을 설정 하려면 로컬 컴퓨터에서 Web api 응용 프로그램에 Windows Phone 8 에뮬레이터 연결 문서에 설명 된 지침을 따라야 합니다.As mentioned in the Prerequisites section of this tutorial, when you are testing the connectivity between Web API and Windows Phone 8 projects on your local system, you will need to follow the instructions in the Connecting the Windows Phone 8 Emulator to Web API Applications on a Local Computer article to set up your testing environment.

테스트 환경을 구성한 후에는 Windows Phone 응용 프로그램을 시작 프로젝트로 설정 해야 합니다.Once you have the testing environment configured, you will need to set the Windows Phone application as the startup project. 이렇게 하려면 솔루션 탐색기에서 Bookcatalog 응용 프로그램을 강조 표시 하 고 시작 프로젝트로 설정을 클릭 합니다.To do so, highlight the BookCatalog application in the solution explorer, and then click Set as StartUp Project:

확장 하려면 이미지를 클릭 합니다.Click image to expand

F5 키를 누르면 Visual Studio에서 Windows Phone 에뮬레이터를 모두 시작 합니다 .이 에뮬레이터는 웹 API에서 응용 프로그램 데이터를 검색 하는 동안" "를 표시 합니다.When you press F5, Visual Studio will start both the Windows Phone Emulator, which will display a "Please Wait" message while the application data is retrieved from your Web API:

확장 하려면 이미지를 클릭 합니다.Click image to expand

모든 작업이 성공 하면 카탈로그가 표시 됩니다.If everything is successful, you should see the catalog displayed:

확장 하려면 이미지를 클릭 합니다.Click image to expand

책 제목을 누르면 응용 프로그램에 책 설명이 표시 됩니다.If you tap on any book title, the application will display the book description:

확장 하려면 이미지를 클릭 합니다.Click image to expand

응용 프로그램이 Web API와 통신할 수 없는 경우 다음과 같은 오류 메시지가 표시 됩니다.If the application cannot communicate with your Web API, an error message will be displayed:

확장 하려면 이미지를 클릭 합니다.Click image to expand

오류 메시지를 탭 하면 오류에 대 한 추가 정보가 표시 됩니다.If you tap on the error message, any additional details about the error will be displayed:

확장 하려면 이미지를 클릭 합니다.Click image to expand