Catalogo di Fumetti – La prima Web API con Swagger

Sin da piccolo sono sempre stato un grande amante di Fumetti. In effetti ne ho collezionati parecchi, principalmente Marvel, e mi piacerebbe avere una maniera facile di catalogarli e poterci accedere magari anche da dispositivi mobili. Proviamo quindi a creare un app per catalogarli e navigarli. Cominciamo con il definire la struttura dove salvare questi dati: una semplicissima tabella di database (SQL Server) come segue:

  • ID: Identificatore univoco
  • Series: la testata del fumetto
  • Title: il titolo del numero
  • Number: il numero del fumetto all’interno della testata

Partiamo quindi creandoci un catalogo vuoto e definiamo la tabella “Comic” come segue

Comic Table

Apriamo quindi VisualStudio 2019 IDE e creaiamo un nuovo progetto come “Web API Project”

ASP NET Core Web API Template

Chiamerò il progetto XinCataLogSwaggerWebAPI perchè voglio che l’API abbia anche l’interfaccia Swagger

Create Project

Come Framework identifico il 5.0 che è l’ultimo disponibile sulla mi macchina, per il momento lascio Authentication Type a None (ho visto parecchie esempi sul web e viene sempre lasciata a None nel caso servisse ci penseremo)

Framework and Authentication

A questo punto un progetto vuoto con la classe di esempio WeatherForecast è creato per mostrarne il buon funzionamento. Eseguiamo a questo punto il progetto e otteniamo:

Swagger API interface

Abbiamo la pagina Swagger per la nostra WebAPI, certo i metodi non sono che quello di default ma come inizio non è per nulla male.

Aggiungo il progetto a GitHub (lo potete trovare qui [1] se volete curiosarci). Ovviamente il suggerimento come sempre è avere un repository in cui poter salvare modifiche e recuperare i vostri errori nel caso li commettiate. Dato che dobbiamo utilizzare l’EntityFramework per implementare le CRUD da SQL Server aggiungiamo i seguenti pacchetti via NuGet (fate attenzione alla compatibilità con il vostro Framework)

EntityFrameworkCore 5.0.15

La lista finale di pacchetti che dobbiamo installare è la seguente:

NuGet Packages

Ricordo in passato di aver lavorato con un utilissimo wizard per generare il modello dati da un DB SQL con l’approcio Database First, sfortunatamente non sono riuscito a ritrovarlo e sembra che ciò sia dovuto al fatto che con .NET Core non si possono aggiungere oggetti ADO Entity Model [1]. Ad ogni modo è possibile sfruttare un comando dal Package Console Manager che fa qualcosa di similare:

Scaffold-DBContext "Server=WIN-7O15VR47QA6;Database=XinCataLog;Trusted_Connection=True;"  Microsoft.EntityFrameworkCore.SqlServer -OutputDir "Models" -Tables XinComic -f  

Il comando dice quale tabella/entità (in questo caso XinComic) su quale effettuare lo scaffold dell’oggetto e generare la classe model corrispettiva.

Package Manager Command
Models Folder

La classe XinCataLogContext è quella che effettua la comunicazione effettiva con il DB, mentre XinComic è il modello che rappresenta la tabella XinComic nel DB.

Ora passiamo a vedere come esporre le tipiche funzionalità che una API offre: i metodi HTTP di base sono normalmente 4 e si basano sulle operazioni CRUD (GET, PUT, POST, e DELETE vedi anche qui [2]).

  • GET ritorna la risorsa richiesta allo specifico URI. GET on ha effetti sul server (è una lettura).
  • PUT modifica una risorsa esistente allo specifico URI. PUT in alcuni casi può anche supportare la creazione se specificatamente prevista.
  • POST crea una nuova risorsa.
  • DELETE cancella una risorsa relativamente all’URI fornito.

Dato che noi abbiamo già creato un modello negli steps precedenti a cui associare le CRUD non serve fare altro che aggiungere un nuovo Controller alla folder Controller scegliendo specificatamente l’opzione sotto

API Controller with Actions using EntityFramework

Nella finestra modale che si apre non dobbiamo fare altro che scegliere le due classi che abbiamo creato allo step precedente come Model Class e Data Context Class

XinComicsController

Fatto ciò, dopo aver tritato per qualche secondo magicamente VisualStudio vi genererà il controller con tutti i metodi base funzionanti.

Devo dire che la prima volta che ho generato il controller mi sono beccato uno strano errore “Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly ‘Microsoft.VisualStudio.Web.CodeGeneration.Utils, Version=5.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60’. The system cannot find the file specified. File name: ‘Microsoft.VisualStudio.Web.CodeGeneration.Utils, Version=5.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60′” che ho risolto con il provvidenziale intervento di StackOverflow [4]. Qualora vi succedesse provateci, a me ha risolto il problema.

Ecco qui dunque il controller bello che pronto:

XinComicsController

In effetti se lanciamo ora il progetto i nuovi metodi sono presenti

XinComics methods

ma se ad esempio proviamo a lanciare la GET ci becchiamo un bel errore:

System.InvalidOperationException: Unable to resolve service for type 'XinCataLogSwaggerWebAPI.Models.XinCataLogContext' while attempting to activate 'XinCataLogSwaggerWebAPI.Controllers.XinComicsController'.

che ci dice in maniera abbastanza esplicita che abbiamo commesso qualche errore nell’inizializzazione del DB context XinCataLogContext. In effetti non lo abbiamo proprio registrato [5].

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<XinCataLogContext>(options =>
              options.UseSqlServer(Configuration.GetConnectionString("DefaultSQLServerConnection")));

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "XinCataLogSwaggerWebAPI", Version = "v1" });
            });
        }

La prima linea di codice del metodo registra il DB context che abbiamo creato prima. Adesso dobbiamo semplicemente referenziare la Connection String nel file appsettings.

  "ConnectionStrings": {
    "DefaultSQLServerConnection": "Server=WIN-7O15VR47QA6;Database=XinCataLog;Trusted_Connection=True;"
  }

E questo è tutto! Se ora lanciate l’applicazione scoprirete che i metodi funzionano come ci attendevamo. Abbiamo ottenuto la prima WebAPI (con Swagger) scrivendo al più un paio di linee di codice visto che la gran parte delle azioni le fa in toto Visual Studio That’s.

Get method from Database

[1] https://github.com/stepperxin/XinCataLogSwaggerWebAPI

[2] https://docs.microsoft.com/en-us/answers/questions/357012/can39t-find-adonet-entity-data-model-missing-visua.html

[3] https://docs.microsoft.com/en-us/aspnet/web-api/overview/older-versions/creating-a-web-api-that-supports-crud-operations

[4] https://stackoverflow.com/questions/45139243/asp-net-core-scaffolding-does-not-work-in-vs-2017

[5] https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-6.0#register-the-schoolcontext