ASP.NET Web API Debugowanie z Fiddler Potrafisz zbudować WEB API używając frameworka ASP.NET. Niestety to tylko początek. Po stworzenie WEB API musimy go przetestować. Wysyłać do niego żądania i sprawdzać wiadomości zwrotne

Istnieje parę narzędzi, które mogą ci pomóc w testowaniu twojego WEB API.

Sam przeglądarki mogą wysyłać żądanie GET. Istnieją dodatki do przeglądarki FireFox i Chrome, które potrafią wysłać żądania HTTP (GET,POST,PUT,DELETE). Zrobiłem o nich osobny wpis.Restowy klient do testów w przeglądarce Google Chrome i FireFox

W tym wpisie skoncentruje się bardziej na narzędziu Fiddler.

Fiddler jest narzędziem do debugowania wywołań sieciowych. Analizuje on żądania HTTP i HTTPS pomiędzy komputerem na którym jest uruchomiony Fiddler a serwerem wystawionym na zewnątrz.

Fiddler ma też funkcję budowy żądań do WEB API. Instalacja Fiddlera jest prosta. Muszę przyznać, że dużo się zmieniło od mojej ostatniej instalacji Fiddler. Widzę, że został on wykupiony przez firmę Telerick.

Fiddlera

Fiddler jest .NET przyjaznym wynalazkiem i widać, że radzi on sobie z łapaniem przekazów z aplikacji Moder UI Windows 8.

Windows 8 Fiddler

Fiddler wygląda trochę przerażająco. Tona zakładek i przycisków. Od czego tutaj zacząć.

Fiddler Web Debugger

Może od przechwytywania ruchu związanego z naszymi API.

W poprzednich wpisach stworzyliśmy proste WEB API. Stworzymy teraz prostą aplikację wysyłającą żądanie do WEB API i prześledźmy ruch aplikacji używając Fiddler-a.

Konsolowa aplikacja do wysyłania żądania

Kliknij na solucje prawym przyciskiem myszki i wybierz “Add->New Project”.

New Project

Z okna nowego projektu wybierz “Console Application”.

Console Application

Postanowiłem zmodyfikować adres portu localhost projektu WEB API. W opcjach projektu w zakładce WEB zmień port na 4000.

image

W aplikacji konsolowe dodaje następujący kod. Klasa WebClient pobierze zawartość tekstową zwróconą przez serwer. Konsola będzie wykonywać to żądania dopóki użytkownik nie wybierze klawisza “A”.

localhost.fiddler

Alternate Text Zauważ, że do adres w zmiennej URI zawiera w sobie także specjalne odwołanie do Fiddlera. Fiddler domyślnie nie przechwytuje wywołań wykonanych przy pomocą klasy WebClient. Fiddler ma także problemy z śledzeniem ruchu w adresie localhost, ale nie jest to zasada. Zależne jest to też od wersji Fiddler jaką używasz.

Pamiętaj o porcie adresu do WEB API ja celowo zmieniłem go na 4000. Jeśli port będzie zły WebClient nic nie pobierze.

using System;
using System.Net;

namespace GameAPITester
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                string uri = "http://localhost.fiddler:4000/api/games/1234";

                using (WebClient client = new WebClient())
                {
                    Console.WriteLine(client.DownloadString(uri));
                }

                if (Console.ReadKey().Key == ConsoleKey.A)
                    break;
            }
        }
    }
}

Jesteśmy prawie gotowi do testowania usługi. Musimy jeszcze ustalić kolejność uruchamiania projektu. Konsola jest bezużyteczna jeśli lokalny serwer WEB API nie jest uruchomiony.

Kolejność projektów

W poprzednim wpisie bardzo zmodyfikowałem WEB API. Do testowania będą potrzebne tylko podstawowe metody.

public class GamesController : ApiController
{
    private static IList<Game> list = new List<Game>()
{
    new Game(){Id = 1234,Name="Mortal Kombat"},
    new Game(){Id = 1235,Name="Defender of Crown"},
    new Game(){Id = 1236,Name="Shadow of The Beast"},
    new Game(){Id = 1237,Name="Dune II"},
    new Game(){Id = 1238,Name="The Settlers"}
};

    // GET api/Games
    [AcceptVerbs("GET")]
    public IEnumerable<Game> AllGames()
    {
        return list;
    }

    [AcceptVerbs("GET", "POST")]
    public Game RetriveGame(int id)
    {
        return list.First(e => e.Id == id);
    }

    // POST api/Games
    [HttpPost]
    public void AddGame(Game Game)
    {
        int maxId = list.Max(e => e.Id);
        Game.Id = maxId + 1;
        list.Add(Game);
    }
    // PUT api/Games/12345
    [HttpPut]
    public void UpdateGame(int id, Game Game)
    {
        int index = list.ToList().FindIndex(e => e.Id == id);
        list[index] = Game;
    }
    // DELETE api/Games/12345
    [HttpDelete]
    public void DestroyGame(int id)
    {
        Game Game = RetriveGame(id);
        list.Remove(Game);
    }
}

Usunąłem także nie potrzebne schematy ścieżek do WEB API.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
        name: "DefaultApi2",

            routeTemplate: "api/{controller}/{id}",
            defaults: new
            {
                id = RouteParameter.Optional,
            }
        );

        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(
            new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));
    }
}

Teraz możemy przejść do debugowania WEB API i klienta używając Fiddlera. Kompletny projekt z tego rozdziału możesz pobrać tutaj.

Działamy z Fiddler i łapiemy przekazy

Fiddler domyślnie śledzi wszystkie procesy. Co jest nie wygodne jeśli masz otwarte wiele aplikacji generujący ruch sieciowi. Na dolnym lewym rogu możesz zobaczyć czy Fiddler rzeczywiście śledzi procesy i jak je filtruje.

Filtrowanie

Klikając na ikonę filtracji możesz zmienić listę aplikacji, które będą filtrowane. Opcja “Non-Browser” jest pożyteczna, ale możemy działać jeszcze lepiej.

Filtrowanie można ograniczyć do jednego procesu. Klikając na ikonkę tarczy strzelniczej i przeciągnij kursor na uruchomioną konsole.

Any process

Teraz będziesz mógł śledzić tylko proces aplikacji konsolowej.

Łapiemy proces w Fiddler

Wybierając z listy interesującą nas zwrotkę jesteśmy wstanie przenalizować zwróconą wiadomość.

Inspectors

W zakładce “Inspectors” możesz zobaczyć dane o zapytaniu jak i o wiadomości zwrotnej. Przykładowo możesz podejrzeć jakie dane w formacie JSON zostały zwrócone przez WEB API.

Zakładka “Statistics” jak sama nazwa mówi w tej zakładce są statystyki działań żądań HTTP.

Tworzenie i wykonywania zapytania HTTP w Fiddler

Pamiętasz aplikację konsolową, którą przed chwilą stworzyliśmy. Nie będzie ona nam potrzebna.

Fiddler ma wbudowany mechanizm tworzenia żądań HTTP i my go użyjemy. Mechanizm ten znajduje się w zakładce “Composer”.

Composer

Przetestujmy wywołania POST na naszym WEB API. Wykonany tą metodę.

// POST api/Games
    [HttpPost]
    public void AddGame(Game Game)
    {
        int maxId = list.Max(e => e.Id);
        Game.Id = maxId + 1;
        list.Add(Game);
    }

Uruchom WEB API. Do nagłówków określonych w Request Headers dopisz “Content-Type:application/json”.

Web API w ten sposób będzie wiedziało, że przesyłasz dane do niej w formacie JSON.

Composer POST

Do ciała zapytania określonego w oknie “Request-Body” napisz encję gry w formacie JSON. Oto przykład.

{"Id":1239,"Name":"Cannon Fodder"}

Naciśnij przycisk Request.

Do nagłówków zostanie dodany jeszcze “Content – Lenght” który określa długość żądania Jest on automatycznie uzupełniany przez Fiddler.

Na liście powinna się pojawić nowa informacja o ruchu naszego żądania. Ma ono status 204 gdyż samo zapytanie nie zwróciło żadnej wiadomości zwrotnej.

Odpowiedź serwera

Metoda post powinna dodać nową grę. Zmień metodę HTTP z POST na GET. Żądanie GET nie ma ciała dlatego Fiddler podkreśla ten obszar na czerwono. Nie będzie on użyty,

Composer GET

Klikając podwójnie na nową informacje o ruchu żądania HTTP możesz zauważyć, że faktycznie gra została dodana do listy. U mnie nawet dwa razy gdyż wywołałem żądanie POST dwa razy dla pewności.

Odpowiedź GET

Analogicznie możesz przetestować metody PUT i DELETE. Pamiętaj tylko o zmianie adresu URL.

Composer PUT

Tak ja mówiłem w części pierwszej tego cyklu.To co przesyłamy w ciele żądania jest później serializowane na obiekty klasy Game w C#.

Break Point ASP.NET WEB API

Anatomia wiadomości HTTP – dla początkujących

Alternate TextZapytanie HTTP zaczyna się od pierwszej linki która określa metodę HTTP oraz adres URL do pytanego zasobu. Potem po spacji jest określona wersja protokołu HTTP.

W następnych linijka znajdują się nagłówki HTTP. Określają one klienta wywołującego wywołanie HTTP jak i format treści jaką one akceptują.

Opcjonalnie jeśli jest to metoda POST,PUT,DELETE HTTP później mamy ciało zapytania.

Obrazek poniżej pokazuje wywołanie GET przeglądarki Netscape za czasów Windows 98.

Request Line Request Header

Odpowiedź HTML w pierwszej linijce mamy określenie wersji protokołu HTTP jak i status HTTP.

Status HTTP jest określony przez 3 cyfrową liczbę. Listę tych statusów odczytać można na Wikipedii znaleźć tutaj.

Podobnie jak zapytaniem odpowiedź ma także nagłówki HTTP. Po nagłówkach znajduje się ciało odpowiedzi. W przypadku naszego WEB API jest obiekt w formacie JSON lub XML.

Response Header Response Body