Esercizio - Aggiungere un controller
Un controller è una classe pubblica con uno o più metodi pubblici chiamati azioni. Per convenzione, un controller viene posizionato nella directory Controllers della radice del progetto. Le azioni vengono esposte come endpoint HTTP all'interno del controller dell'API Web.
Creare un controller
Selezionare la cartella Controllers in Visual Studio Code e aggiungere un nuovo file denominato Pizza.cs.
Viene creato un file di classe vuoto denominato PizzaController.cs nella directory Controllers. Il nome di directory Controllers è una convenzione. Il nome della directory deriva dall'architettura Model-View-Controller usata dall'API Web.
Nota
Per convenzione, i nomi delle classi dei controller hanno il suffisso Controller.
Aggiungere il codice seguente a Controllers/PizzaController.cs. Salva le modifiche.
using ContosoPizza.Models; using ContosoPizza.Services; using Microsoft.AspNetCore.Mvc; namespace ContosoPizza.Controllers; [ApiController] [Route("[controller]")] public class PizzaController : ControllerBase { public PizzaController() { } // GET all action // GET by Id action // POST action // PUT action // DELETE action }
Come si è appreso in precedenza, questa classe deriva da
ControllerBase
, la classe di base per l'uso delle richieste HTTP in ASP.NET Core. Include anche i due attributi standard già illustrati:[ApiController]
e[Route]
. Come in precedenza, l'attributo[Route]
definisce un mapping con il token[controller]
. Poiché questa classe controller è denominataPizzaController
, questo controller gestisce le richieste ahttps://localhost:{PORT}/pizza
.
Ottenere tutte le pizze
Il primo verbo REST da implementare è GET
, con il quale un client può recuperare tutte le pizze dall'API. Si può usare l'attributo [HttpGet]
predefinito per definire un metodo che restituirà le pizze dal servizio.
Sostituire il commento // GET all action
in Controllers/PizzaController.cs con il codice seguente:
[HttpGet]
public ActionResult<List<Pizza>> GetAll() =>
PizzaService.GetAll();
L'azione precedente:
- Risponde solo al verbo HTTP
GET
, come indicato dall'attributo[HttpGet]
. - Restituisce un'istanza
ActionResult
di tipoList<Pizza>
. Il tipoActionResult
è la classe di base per tutti i risultati dell'azione in ASP.NET Core. - Esegue una query sul servizio per tutte le pizze e restituisce automaticamente i dati con un valore
Content-Type
diapplication/json
.
Recuperare una singola pizza
Il client potrebbe anche richiedere di ottenere informazioni su una pizza specifica anziché l'intero elenco. È possibile implementare un'altra azione GET
che richiede un parametro id
. Si può usare l'attributo [HttpGet("{id}")]
predefinito per definire un metodo che restituirà le pizze dal servizio. La logica di routing registra [HttpGet]
(senza id
) e [HttpGet("{id}")]
(con id
) come due route diverse. È quindi possibile scrivere un'azione separata per recuperare un singolo elemento.
Sostituire il commento // GET by Id action
in Controllers/PizzaController.cs con il codice seguente:
[HttpGet("{id}")]
public ActionResult<Pizza> Get(int id)
{
var pizza = PizzaService.Get(id);
if(pizza == null)
return NotFound();
return pizza;
}
L'azione precedente:
- Risponde solo al verbo HTTP
GET
, come indicato dall'attributo[HttpGet]
. - Richiede che il valore del parametro
id
sia incluso nel segmento dell'URL dopopizza/
. Tenere presente che l'attributo[Route]
a livello del controller ha definito il modello/pizza
. - Esegue una query sul database per cercare una pizza corrispondente al parametro
id
specificato.
Viene eseguito il mapping di ogni istanza di ActionResult
usata nell'azione precedente al codice di stato HTTP corrispondente nella tabella seguente:
ASP.NET Core ASP.NET Core |
Codice di stato HTTP | Descrizione |
---|---|---|
Ok è implicito |
200 | La cache in memoria contiene un prodotto corrispondente al parametro id specificato.Il prodotto è incluso nel corpo della risposta nel tipo di supporto definito nell'intestazione della richiesta HTTP accept (JSON per impostazione predefinita). |
NotFound |
404 | La cache in memoria non contiene un prodotto corrispondente al parametro id specificato. |
Compilare ed eseguire il nuovo controller
Compilare e avviare l'API Web eseguendo il comando seguente:
dotnet run
Testare il controller con un file HTTP
Aprire ContosoPizza.http
Aggiungere una nuova chiamata GET per chiamare l'endpoint
Pizza
sotto il separatore ###:GET {{ContosoPizza_HostAddress}}/pizza/ Accept: application/json ###
Selezionare il comando Invia richiesta sopra questa nuova chiamata GET.
Il comando precedente restituisce un elenco di tutte le pizze in JSON:
HTTP/1.1 200 OK Connection: close Content-Type: application/json; charset=utf-8 Date: Wed, 17 Jan 2024 16:57:09 GMT Server: Kestrel Transfer-Encoding: chunked [ { "id": 1, "name": "Classic Italian", "isGlutenFree": false }, { "id": 2, "name": "Veggie", "isGlutenFree": true } ]
Per eseguire una query per una singola pizza è possibile effettuare un'altra richiesta
GET
, passando però un parametroid
con il comando seguente:GET {{ContosoPizza_HostAddress}}/pizza/1 Accept: application/json ###
Il comando precedente restituisce
Classic Italian
con l'output seguente:HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Fri, 02 Apr 2021 21:57:57 GMT Server: Kestrel Transfer-Encoding: chunked { "id": 1, "name": "Classic Italian", "isGlutenFree": false }
L'API gestisce anche le situazioni in cui l'elemento non esiste. Chiamare di nuovo l'API, ma passare un parametro
id
di pizza non valido con il comando seguente:GET {{ContosoPizza_HostAddress}}/pizza/5 Accept: application/json ###
Il comando precedente restituisce un errore
404 Not Found
con l'output seguente:HTTP/1.1 404 Not Found Content-Type: application/problem+json; charset=utf-8 Date: Fri, 02 Apr 2021 22:03:06 GMT Server: Kestrel Transfer-Encoding: chunked { "type": "https://tools.ietf.org/html/rfc7231#section-6.5.4", "title": "Not Found", "status": 404, "traceId": "00-ec263e401ec554b6a2f3e216a1d1fac5-4b40b8023d56762c-00" }
A questo punto è stata completata l'implementazione dei verbi GET
. Nell'unità successiva sarà possibile aggiungere altre azioni a PizzaController
per supportare operazioni CRUD sui dati per le pizze.
Facoltativo: Testare il controller con HTTP REPL (Read-Eval-Print Loop) da riga di comando
Aprire il terminale
httprepl
esistente o aprire un nuovo terminale integrato da Visual Studio Code scegliendo Terminale>Nuovo terminale dal menu principale.Connettersi all'API Web eseguendo il comando seguente:
httprepl https://localhost:{PORT}
In alternativa, eseguire questo comando in qualsiasi momento durante l'esecuzione di
HttpRepl
:connect https://localhost:{PORT}
Per visualizzare il nuovo endpoint
Pizza
disponibile, eseguire il comando seguente:ls
Il comando precedente rileva tutte le API disponibili nell'endpoint connesso. Verrà visualizzato il codice seguente:
https://localhost:{PORT}/> ls . [] Pizza [GET] WeatherForecast [GET]
Passare all'endpoint
Pizza
eseguendo questo comando:cd Pizza
Il comando precedente mostra un output di API disponibili per l'endpoint
Pizza
:https://localhost:{PORT}/> cd Pizza /Pizza [GET]
Effettuare una richiesta
GET
inHttpRepl
usando questo comando:get
Il comando precedente restituisce un elenco di tutte le pizze in JSON:
HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Fri, 02 Apr 2021 21:55:53 GMT Server: Kestrel Transfer-Encoding: chunked [ { "id": 1, "name": "Classic Italian", "isGlutenFree": false }, { "id": 2, "name": "Veggie", "isGlutenFree": true } ]
Per eseguire una query per una singola pizza è possibile effettuare un'altra richiesta
GET
, passando però un parametroid
con il comando seguente:get 1
Il comando precedente restituisce
Classic Italian
con l'output seguente:HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Fri, 02 Apr 2021 21:57:57 GMT Server: Kestrel Transfer-Encoding: chunked { "id": 1, "name": "Classic Italian", "isGlutenFree": false }
L'API gestisce anche le situazioni in cui l'elemento non esiste. Chiamare di nuovo l'API, ma passare un parametro
id
di pizza non valido con il comando seguente:get 5
Il comando precedente restituisce un errore
404 Not Found
con l'output seguente:HTTP/1.1 404 Not Found Content-Type: application/problem+json; charset=utf-8 Date: Fri, 02 Apr 2021 22:03:06 GMT Server: Kestrel Transfer-Encoding: chunked { "type": "https://tools.ietf.org/html/rfc7231#section-6.5.4", "title": "Not Found", "status": 404, "traceId": "00-ec263e401ec554b6a2f3e216a1d1fac5-4b40b8023d56762c-00" }
Tornare al terminale
dotnet
nell'elenco a discesa in Visual Studio Code e arrestare l'API Web premendo CTRL+C sulla tastiera.
A questo punto è stata completata l'implementazione dei verbi GET
. Nell'unità successiva sarà possibile aggiungere altre azioni a PizzaController
per supportare operazioni CRUD sui dati per le pizze.