Wywoływanie wzorca Web API z aplikacji Windows Phone 8 (C#)
Autor : Robert McMurray
Z tego samouczka dowiesz się, jak utworzyć kompletny scenariusz składający się z aplikacji internetowego interfejsu API ASP.NET, która udostępnia katalog książek do aplikacji Windows Phone 8.
Omówienie
Usługi RESTful, takie jak ASP.NET internetowy interfejs API, upraszczają tworzenie aplikacji opartych na protokole HTTP dla deweloperów, abstrahując architekturę aplikacji po stronie serwera i po stronie klienta. Zamiast tworzyć zastrzeżony protokół oparty na gniazdach na potrzeby komunikacji, deweloperzy interfejsu API sieci Web muszą po prostu opublikować wymagane metody HTTP dla swojej aplikacji (na przykład: GET, POST, PUT, DELETE) i deweloperzy aplikacji klienckich muszą korzystać tylko z metod HTTP, które są niezbędne dla ich aplikacji.
Z tego kompleksowego samouczka dowiesz się, jak używać internetowego interfejsu API do tworzenia następujących projektów:
- W pierwszej części tego samouczka utworzysz aplikację internetowego interfejsu API ASP.NET, która obsługuje wszystkie operacje tworzenia, odczytu, aktualizacji i usuwania (CRUD) w celu zarządzania katalogiem książek. Ta aplikacja będzie używać przykładowego pliku XML (books.xml) z witryny MSDN.
- W drugiej części tego samouczka utworzysz interaktywną aplikację Windows Phone 8, która pobiera dane z aplikacji internetowego interfejsu API.
Wymagania wstępne
- Visual Studio 2013 z zainstalowanym zestawem SDK Windows Phone 8
- System Windows 8 lub nowszy w 64-bitowym systemie z zainstalowaną funkcją Hyper-V
- Aby uzyskać listę dodatkowych wymagań, zobacz sekcję Wymagania systemowe na stronie pobierania zestawu SDK 8.0 Windows Phone.
Uwaga
Jeśli zamierzasz przetestować łączność między internetowym interfejsem API i Windows Phone 8 projektów w systemie lokalnym, należy wykonać instrukcje opisane w artykule Łączenie emulatora Windows Phone 8 z aplikacjami internetowego interfejsu API na komputerze lokalnym w celu skonfigurowania środowiska testowego.
Krok 1. Tworzenie projektu księgarni internetowego interfejsu API
Pierwszym krokiem tego kompleksowego samouczka jest utworzenie projektu internetowego interfejsu API, który obsługuje wszystkie operacje CRUD; Pamiętaj, że dodasz projekt aplikacji Windows Phone do tego rozwiązania w kroku 2 tego samouczka.
Otwórz Visual Studio 2013.
Kliknij pozycję Plik, a następnie pozycję Nowy, a następnie pozycję Projekt.
Po wyświetleniu okna dialogowego Nowy projekt rozwiń węzeł Zainstalowane, a następnie pozycję Szablony, Visual C#, a następnie Sieć Web.
Kliknij obraz, aby rozwinąć Wyróżnij ASP.NET aplikacji internetowej, wprowadź ciąg BookStore jako nazwę projektu, a następnie kliknij przycisk OK.
Po wyświetleniu okna dialogowego Nowy projekt ASP.NET wybierz szablon internetowego interfejsu API , a następnie kliknij przycisk OK.
Kliknij obraz, aby rozwinąć Po otwarciu projektu internetowego interfejsu API usuń przykładowy kontroler z projektu:
- Rozwiń folder Controllers w Eksploratorze rozwiązań.
- Kliknij prawym przyciskiem myszy plik ValuesController.cs , a następnie kliknij przycisk Usuń.
- Po wyświetleniu monitu kliknij przycisk OK , aby potwierdzić usunięcie.
Dodaj plik danych XML do projektu internetowego interfejsu API; ten plik zawiera zawartość katalogu księgarni:
Kliknij prawym przyciskiem myszy folder App_Data w Eksploratorze rozwiązań, a następnie kliknij polecenie Dodaj, a następnie kliknij pozycję Nowy element.
Po wyświetleniu okna dialogowego Dodawanie nowego elementu wyróżnij szablon Plik XML .
Nadaj plikowi nazwęBooks.xml, a następnie kliknij przycisk Dodaj.
Po otwarciu pliku Books.xml zastąp kod w pliku kodem XML z przykładowego pliku books.xml w witrynie 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>
Zapisz i zamknij plik XML.
Dodaj model księgarni do projektu internetowego interfejsu API; Ten model zawiera logikę tworzenia, odczytu, aktualizacji i usuwania (CRUD) dla aplikacji księgarni:
Kliknij prawym przyciskiem myszy folder Models w Eksploratorze rozwiązań, a następnie kliknij przycisk Dodaj, a następnie kliknij pozycję Klasa.
Po wyświetleniu okna dialogowego Dodawanie nowego elementu nadaj plikowi klasy nazwę BookDetails.cs, a następnie kliknij przycisk Dodaj.
Po otwarciu pliku BookDetails.cs zastąp kod w pliku następującym kodem:
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; } } } }
Zapisz i zamknij plik BookDetails.cs .
Dodaj kontroler księgarni do projektu internetowego interfejsu API:
Kliknij prawym przyciskiem myszy folder Controllers w Eksploratorze rozwiązań, a następnie kliknij przycisk Dodaj, a następnie kliknij przycisk Kontroler.
Po wyświetleniu okna dialogowego Dodawanie szkieletu wyróżnij pozycję Kontroler internetowego interfejsu API 2 — pusty, a następnie kliknij przycisk Dodaj.
Gdy zostanie wyświetlone okno dialogowe Dodawanie kontrolera , nadaj kontrolerowi nazwę BooksController, a następnie kliknij przycisk Dodaj.
Po otwarciu pliku BooksController.cs zastąp kod w pliku następującym kodem:
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); } } }
Zapisz i zamknij plik BooksController.cs .
Skompiluj aplikację internetowego interfejsu API, aby sprawdzić błędy.
Krok 2. Dodawanie projektu wykazu księgarni Windows Phone 8
Następnym krokiem tego kompleksowego scenariusza jest utworzenie aplikacji wykazu dla Windows Phone 8. Ta aplikacja będzie używać szablonu aplikacji Windows Phone databound dla domyślnego interfejsu użytkownika i będzie używać aplikacji internetowego interfejsu API utworzonej w kroku 1 tego samouczka jako źródła danych.
Kliknij prawym przyciskiem myszy rozwiązanie BookStore w eksploratorze rozwiązań, a następnie kliknij pozycję Dodaj, a następnie pozycję Nowy projekt.
Po wyświetleniu okna dialogowego Nowy projekt rozwiń węzeł Zainstalowane, a następnie pozycję Visual C#, a następnie Windows Phone.
Wyróżnij Windows Phone aplikacji dla danych, wprowadź nazwę BookCatalog, a następnie kliknij przycisk OK.
Dodaj pakiet NuGet Json.NET do projektu BookCatalog :
- Kliknij prawym przyciskiem myszy pozycję Odwołania dla projektu BookCatalog w Eksploratorze rozwiązań, a następnie kliknij polecenie Zarządzaj pakietami NuGet.
- Po wyświetleniu okna dialogowego Zarządzanie pakietami NuGet rozwiń sekcję Online i wyróżnij nuget.org.
- Wprowadź Json.NET w polu wyszukiwania i kliknij ikonę wyszukiwania.
- Wyróżnij Json.NET w wynikach wyszukiwania, a następnie kliknij przycisk Zainstaluj.
- Po zakończeniu instalacji kliknij przycisk Zamknij.
Dodaj model BookDetails do projektu BookCatalog ; zawiera ogólny model klasy księgarni:
Kliknij prawym przyciskiem myszy projekt BookCatalog w Eksploratorze rozwiązań, a następnie kliknij polecenie Dodaj, a następnie kliknij pozycję Nowy folder.
Nazwij nowy folder Models.
Kliknij prawym przyciskiem myszy folder Models w Eksploratorze rozwiązań, a następnie kliknij przycisk Dodaj, a następnie kliknij pozycję Klasa.
Po wyświetleniu okna dialogowego Dodawanie nowego elementu nadaj plikowi klasy nazwę BookDetails.cs, a następnie kliknij przycisk Dodaj.
Po otwarciu pliku BookDetails.cs zastąp kod w pliku następującym kodem:
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; } } }
Zapisz i zamknij plik BookDetails.cs .
Zaktualizuj klasę MainViewModel.cs , aby zawierała funkcje komunikacji z aplikacją internetowego interfejsu API BookStore:
Rozwiń folder ViewModels w Eksploratorze rozwiązań, a następnie kliknij dwukrotnie plik MainViewModel.cs .
Po otwarciu pliku MainViewModel.cs zastąp kod w pliku następującym kodem; Należy pamiętać, że należy zaktualizować wartość
apiUrl
stałej za pomocą rzeczywistego adresu URL internetowego interfejsu 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)); } } } }
Zapisz i zamknij plik MainViewModel.cs .
Zaktualizuj plik MainPage.xaml , aby dostosować nazwę aplikacji:
Kliknij dwukrotnie plik MainPage.xaml w Eksploratorze rozwiązań.
Po otwarciu pliku MainPage.xaml znajdź następujące wiersze kodu:
<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>
Zastąp te wiersze następującymi wierszami:
<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>
Zapisz i zamknij plik MainPage.xaml .
Zaktualizuj plik DetailsPage.xaml , aby dostosować wyświetlane elementy:
Kliknij dwukrotnie plik DetailsPage.xaml w Eksploratorze rozwiązań.
Po otwarciu pliku DetailsPage.xaml znajdź następujące wiersze kodu:
<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>
Zastąp te wiersze następującymi wierszami:
<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>
Zapisz i zamknij plik DetailsPage.xaml .
Skompiluj aplikację Windows Phone, aby sprawdzić, czy występują błędy.
Krok 3. Testowanie kompleksowego rozwiązania
Jak wspomniano w sekcji Wymagania wstępne tego samouczka, podczas testowania łączności między internetowym interfejsem API i Windows Phone 8 projektów w systemie lokalnym należy wykonać instrukcje opisane w artykule Łączenie emulatora Windows Phone 8 z aplikacjami internetowego interfejsu API na komputerze lokalnym w celu skonfigurowania środowiska testowego.
Po skonfigurowaniu środowiska testowego należy ustawić aplikację Windows Phone jako projekt startowy. W tym celu wyróżnij aplikację BookCatalog w Eksploratorze rozwiązań, a następnie kliknij pozycję Ustaw jako projekt startowy:
Kliknij obraz, aby rozwinąć |
Po naciśnięciu klawisza F5 program Visual Studio uruchomi zarówno emulator Windows Phone, który wyświetli komunikat "Czekaj", gdy dane aplikacji zostaną pobrane z internetowego interfejsu API:
Kliknij obraz, aby rozwinąć |
Jeśli wszystko zakończy się pomyślnie, powinien zostać wyświetlony katalog:
Kliknij obraz, aby rozwinąć |
Po naciśnięciu dowolnego tytułu książki aplikacja wyświetli opis książki:
Kliknij obraz, aby rozwinąć |
Jeśli aplikacja nie może komunikować się z internetowym interfejsem API, zostanie wyświetlony komunikat o błędzie:
Kliknij obraz, aby rozwinąć |
Po naciśnięciu komunikatu o błędzie zostaną wyświetlone dodatkowe szczegóły dotyczące błędu:
Kliknij obraz, aby rozwinąć |