Windows Phone 8 アプリケーションから Web API を呼び出す (C#)
投稿者: Robert McMurray
このチュートリアルでは、Windows Phone 8 アプリケーションに書籍のカタログを提供する ASP.NET Web API アプリケーションで構成される完全なエンド ツー エンドのシナリオを作成する方法について説明します。
概要
ASP.NET Web API などの RESTful サービスは、サーバー側およびクライアント側のアプリケーションのアーキテクチャを抽象化することで、開発者向けの HTTP ベースのアプリケーションの作成を簡略化します。 Web API 開発者は、通信用に独自のソケット ベースのプロトコルを作成する代わりに、アプリケーションに必要な HTTP メソッド (GET、POST、PUT、DELETE など) を発行するだけで済み、クライアント アプリケーション開発者に必要なのは、アプリケーションに必要な HTTP メソッドを使用することだけです。
このエンド ツー エンドのチュートリアルでは、Web API を使用して次のプロジェクトを作成する方法について説明します。
- このチュートリアルの最初の部分では、書籍カタログを管理するためのすべての作成、読み取り、更新、および削除 (CRUD) 操作をサポートする ASP.NET Web API アプリケーションを作成します。 このアプリケーションでは、MSDN のサンプル XML ファイル (books.xml) を使用します。
- このチュートリアルの第 2 部では、Web API アプリケーションからデータを取得する対話型の Windows Phone 8 アプリケーションを作成します。
前提条件
- Windows Phone 8 SDK がインストールされた Visual Studio 2013
- Hyper-V がインストールされている 64 ビット システム上の Windows 8 以降
- その他の要件の一覧については、Windows Phone SDK 8.0 のダウンロード ページの「システム要件」セクションを参照してください。
Note
ローカル システム上の Web API と Windows Phone 8 プロジェクトの間の接続をテストする場合は、「ローカル コンピューターでの Windows Phone 8 Emulator から Web API アプリケーションへの接続」の手順に従ってテスト環境を設定する必要があります。
手順 1: Web API Bookstore プロジェクトの作成
このエンド ツー エンドのチュートリアルの最初の手順は、すべての CRUD 操作をサポートする Web API プロジェクトを作成することです。このチュートリアルの手順 2 で、Windows Phone アプリケーション プロジェクトをこのソリューションに追加します。
Visual Studio 2013 を開きます。
[ファイル]、[新規作成]、[プロジェクト] の順にクリックします。
[新しいプロジェクト] ダイアログ ボックスが表示されたら、[インストール済み]、[テンプレート]、[Visual C#]、[Web] の順に展開します。
画像をクリックして展開 ASP.NET Web アプリケーションを強調表示し、プロジェクト名として「BookStore」と入力し、[OK] をクリックします。
[新しい ASP.NET プロジェクト] ダイアログ ボックスが表示されたら、[Web API] テンプレートを選択し、[OK] をクリックします。
画像をクリックして展開 Web API プロジェクトが開いたら、プロジェクトからサンプル コントローラーを削除します。
- ソリューション エクスプローラーで Controllers フォルダーを展開します。
- ValuesController.cs ファイルを右クリックし、[削除] をクリックします。
- 削除するかどうかを確認するメッセージが表示されたら、[OK] をクリックします。
Web API プロジェクトに XML データ ファイルを追加します。このファイルには、書店カタログの内容が含まれています。
ソリューション エクスプローラーで App_Data フォルダーを右クリックし、[追加] をクリックしてから [新しい項目] をクリックします。
[新しい項目の追加] ダイアログ ボックスが表示されたら、[XML ファイル] テンプレートを強調表示します。
ファイルに Books.xml と名前を付け、[追加] をクリックします。
Books.xml ファイルが開いたら、ファイル内のコードを MSDN のサンプル books.xml ファイルの XML に置き換えます。
<?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>
XML ファイルを保存して閉じます。
Bookstore モデルを Web API プロジェクトに追加します。このモデルには、Bookstore アプリケーションの作成、読み取り、更新、および削除 (CRUD) ロジックが含まれています。
ソリューション エクスプローラーで Models フォルダーを右クリックし、[追加]、[クラス] の順にクリックします。
[新しい項目の追加] ダイアログ ボックスが表示されたら、クラス ファイルに BookDetails.cs という名前を付け、[追加] をクリックします。
BookDetails.cs ファイルが開いたら、ファイル内のコードを次のように置き換えます。
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; } } } }
BookDetails.cs ファイルを保存して閉じます。
Bookstore コントローラーを Web API プロジェクトに追加します。
ソリューション エクスプローラーで Controllers フォルダーを右クリックし、[追加]、[コントローラー] の順にクリックします。
[スキャフォールディングを追加] ダイアログ ボックスが表示されたら、[Web API 2 コントローラー - 空] を強調表示し、[追加] をクリックします。
[コントローラーの追加] ダイアログ ボックスが表示されたら、コントローラーに BooksController という名前を付け、[追加] をクリックします。
BooksController.cs ファイルが開いたら、ファイル内のコードを次のように置き換えます。
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); } } }
BooksController.cs ファイルを保存して閉じます。
Web API アプリケーションをビルドしてエラーを確認します。
手順 2: Windows Phone 8 書店カタログ プロジェクトの追加
このエンド ツー エンド シナリオの次の手順は、Windows Phone 8 用のカタログ アプリケーションを作成することです。 このアプリケーションは、既定のユーザー インターフェイスに Windows Phone データバインド アプリ テンプレートを使用し、このチュートリアルの手順 1 で作成した Web API アプリケーションをデータ ソースとして使用します。
ソリューション エクスプローラーで BookStore ソリューションを右クリックし、[追加]、[新しいプロジェクト] の順にクリックします。
[新しいプロジェクト] ダイアログ ボックスが表示されたら、[インストール済み]、[Visual C#]、[Windows Phone] の順に展開します。
[Windows Phone データバインド アプリ] を強調表示し、名前に「BookCatalog」を入力して、[OK] をクリックします。
Json.NET NuGet パッケージを BookCatalog プロジェクトに追加します。
- ソリューション エクスプローラーで BookCatalog プロジェクトの [参照] を右クリックし、[NuGet パッケージの管理] をクリックします。
- [NuGet パッケージの管理] ダイアログ ボックスが表示されたら、[オンライン] セクションを展開し、nuget.org を強調表示します。
- 検索フィールドに「Json.NET」と入力し、検索アイコンをクリックします。
- 検索結果の Json.NET を強調表示し、[インストール] をクリックします。
- インストールが完了したら、[閉じる] をクリックします。
BookCatalog プロジェクトに BookDetails モデルを追加します。これには、bookstore クラスの汎用モデルが含まれています。
ソリューション エクスプローラーで BookCatalog プロジェクトを右クリックし、[追加]、[新しいフォルダー] の順にクリックします。
新しいフォルダーに Models という名前を付けます。
ソリューション エクスプローラーで Models フォルダーを右クリックし、[追加]、[クラス] の順にクリックします。
[新しい項目の追加] ダイアログ ボックスが表示されたら、クラス ファイルに BookDetails.cs という名前を付け、[追加] をクリックします。
BookDetails.cs ファイルが開いたら、ファイル内のコードを次のように置き換えます。
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; } } }
BookDetails.cs ファイルを保存して閉じます。
BookStore Web API アプリケーションと通信する機能を含むように、MainViewModel.cs クラスを更新します。
ソリューション エクスプローラーで ViewModels フォルダーを展開し、MainViewModel.cs ファイルをダブルクリックします。
MainViewModel.cs ファイルが開いたら、ファイル内のコードを次のコードに置き換えます。
apiUrl
定数の値を Web API の実際の URL に更新する必要があることに注意してください。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)); } } } }
MainViewModel.cs ファイルを保存して閉じます。
MainPage.xaml ファイルを更新して、アプリケーション名をカスタマイズします。
ソリューション エクスプローラーで、MainPage.xaml ファイルをダブルクリックします。
MainPage.xaml ファイルを開いたら、次のコード行を見つけます。
<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>
これらの行を次のように置き換えます。
<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>
MainPage.xaml ファイルを保存して閉じます。
DetailsPage.xaml ファイルを更新して、表示される項目をカスタマイズします。
ソリューション エクスプローラーで、DetailsPage.xaml ファイルをダブルクリックします。
DetailsPage.xaml ファイルを開いたら、次のコード行を見つけます。
<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>
これらの行を次のように置き換えます。
<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>
DetailsPage.xaml ファイルを保存して閉じます。
Windows Phone アプリケーションをビルドしてエラーを確認します。
手順 3: エンド ツー エンド ソリューションのテスト
このチュートリアルの「前提条件」セクションで説明したように、ローカル システム上の Web API と Windows Phone 8 プロジェクトの間の接続をテストする場合は、「ローカル コンピューターでの Windows Phone 8 Emulator から Web API アプリケーションへの接続」の手順に従ってテスト環境を設定する必要があります。
テスト環境を構成したら、Windows Phone アプリケーションをスタートアップ プロジェクトとして設定する必要があります。 これを行うには、ソリューション エクスプローラーで BookCatalog アプリケーションを強調表示し、[スタートアップ プロジェクトとして設定] をクリックします。
画像をクリックして展開 |
F5 キーを押すと、Visual Studio によって Windows Phone Emulator が起動され、Web API からアプリケーション データが取得されている間に "お待ちください" メッセージが表示されます。
画像をクリックして展開 |
すべてが成功すると、カタログが表示されます。
画像をクリックして展開 |
任意の書籍のタイトルをタップすると、アプリケーションに書籍の説明が表示されます。
画像をクリックして展開 |
アプリケーションが Web API と通信できない場合は、次のエラー メッセージが表示されます。
画像をクリックして展開 |
エラー メッセージをタップすると、エラーに関する追加の詳細が表示されます。
画像をクリックして展開 |