CSharp:WebAPI Teoria
From Aino Wiki
Cosa sono
Sono uno strumento per fornire elaborazioni ad applicazioni web e non. Le Web API risiedono su un Server e da lì sono richiamate da Clients che ne richiedono elaborazioni ricevendo ed inviando dati. Queste transazioni avvengono supportate dal protocollo HTTP ecco perché quando si richiedono delle operazioni alle Web API si specifica il metodo HTTP sottostante (chiamato anche verbo): GET, POST, PUT, PATCH, DELETE.
Le Web API NON SUPPORTANO il protocollo SOAP (leggere qui).
Architettura
Da docs.microsoft.com- Il Client è ciò che usa la Web API (browser, App mobile etc). Per testare si può usare postman
- Il Model è un oggetto che rappresenta i dati dell'applicazione. Nel grafico si vede solo il modello "To-Do".
- Il controller è un oggetto che gestisce richieste HTTP e crea le risposte (HTTP response).
Storia
Predecessori delle WebAPI sono i Web Services che sono sostanzialmente dei metodi disponibili sul WEB e come tali il loro compito è quello di comandare una elaborazione, in questo "comando" c'è un flusso di informazioni che può essere prevalentemente inviato o ricevuto che è o sarà il frutto dell'elaborazione.
Le Web API (Web Application Program Interface) sono simili a Web Services ma in architettura REST (Representational State Transfer).
REST è un'architettura per sistemi distribuiti rappresenta un sistema di trasmissione di dati attraverso il protocollo HTTP senza ulteriori livelli (quali ad esempio SOAP). I sistemi REST non prevedono il concetto di sessione (sono, come approfondito successivamente, stateless).
L'architettura REST si basa sul protocollo HTTP (link interno HTML:Teoria HTML); il funzionamento prevede una struttura degli URL ben definita (per identificare univocamente risorse) e l'utilizzo dei verbi HTTP: (GET), per la modifica (POST, PUT, PATCH, DELETE) e per altri scopi (OPTIONS, ecc.).
Sviluppare con Microsoft
Praticamente nell'implementazione secondo Microsoft seguire la guida interna Es. Soluzioni Microsoft Web API
I Metodi
Le Web API, intendendo quelle ottenute mediante applicazioni .Net Microsoft, essendo interrogabili mediante chiamate HTTP in funzione di queste possono richiedere l'esecuzione di determinate operazioni. Per esempio molti metodi HTTP possono esser usati per estrarre dati da un server o per inviare dati (Submit) per opportune elaborazioni, metodi HTTP posson esser usati per richiedere cancellazioni di elementi etc. (Da [1]) Ci sono 4 metodi che corrispondono a queste azioni (CRUD):
- C - Create - POST (in una WebAPI corrisponderà a far precedente la definizione del metodo con l'attributo
[HttpPost]
) - R - Read - GET (in una WebAPI corrisponderà a far precedente la definizione del metodo con l'attributo
[HttpGet]
) - U - Update - PUT (in una WebAPI corrisponderà a far precedente la definizione del metodo con l'attributo
[HttpPut]
) - D - Delete - DELETE
Ci sono anche altri metodo ma si useranno solo per casi particolari ed essi sono: HAED, OPTIONS, PATCH.
POST e PUT
Esempio di chiamata ad un metodo server per l'aggiunta di una entità:
[HttpPost] public IHttpActionResult Add(string title) { //Creates a Movie based on the Title return Ok(); }
Se si ha bisogno che un metodo, lato server, supporti più di un metodo HTTP, si potrà usare l'attributo [AcceptVerbs]
, es.:
[AcceptVerbs("POST", "PUT")] public IHttpActionResult Add(string title) { //Creates a Movie based on the Title return Ok(); }
Metodi POST e PUT sono molto simili, entrambi inviano dati al server di cui si richiede di immagazzinare qualcosa. Tecnicamente, si possono attivare indipendentemente scenari di creazione o aggiornamento.
PUT is idempotente. Questo vuol dire che se si fa la stessa richiesta due volte, usando la PUT, con gli stessi parametri entrambe le volte, la seconda richiesta non sortirà alcun effetto. Questo è il motivo per cui la PUT è generalmente usata per gli scenari di Update; chiamando l'Update più di una volta con stessi parametri non farà nulla di diverso da quel che ha fatto la prima chiamata.
POST non è idempotente; effettuare la stessa chiamata con POST con stessi parametri ogni volta compierà differenti comportamenti, ecco perché il POST è usualmente usato per scenari di Creazione (sottomettendo due items identici al metodo Create produrrà due entità in archivio).
Metodo di default
Secondo ASP .NET è il POST.The algorithm ASP.NET uses to calculate the "default" method for a given action goes like this:
- Se il metodo ha un attributo che specifica direttamente l'uso del metodo HTTP (es.: [HttpGet], [HttpPost], [HttpPut], [AcceptVerbs], etc), the action will accept the specified HTTP method(s).
- If the name of the controller action starts the words "Get", "Post", "Put", "Delete", "Patch", "Options", or "Head", use the corresponding HTTP method.
- Altrimenti si suppone che l'azione richiesta sia sempre sul metodo POST.
Output
HttpResponseMessage
Un HttpResponseMessage
è particolarmente utile come oggetto di output di un metodo di una Web API. Come parametro di output di un'azione, es. POST\GET etc, del protocollo HTTP (Per Esempio con le proprietà headers) consente di uniformare il tipo restituito in output.
[HttpPost] public HttpResponseMessage Post_Stampa_menu_anteprimaordini_HttpResponse(AnteprimaOrdiniFornitoriIN aof) { //... HttpResponseMessage cResponse = new HttpResponseMessage(HttpStatusCode.OK); cResponse.Content = new ByteArrayContent(streamPDF.ToArray()); cResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); cResponse.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("Content-Disposition") { FileName = string.Format("{0}{1}" , c_PDF_RelativeOutputPath, Path.GetFileName(pdfFileNameFullPath)) }; return cResponse; }
Esempi presi da c-sharpcorner.com
Content
Come accennato la HttpResponseMessage
fornisce un metodo strutturato ed uniforme per lavorare nei diversi ambiti di dominio d'uso. Infatti, mette a disposizione, oltre ad un modo standard di definire l'esito della operazione richiesta (es. l'HttpStatusCode
) l'oggetto Content per veicolare in output il risultato di una operazione.
Il Content
può essere comodamente di diverso tipo: dato scalare, vettoriale o un oggetto personalizzato.
Esempio stringa in output
L'output è una stringa contenente il testo di quel che dovrà essere il contenuto di un file CSV, si usa lo StringBuilder per costruirne il contenuto.Notare lo StringContent
che definisce il Content.
[ActionName("genera-report-previsioni-csv")] [Route("genera-report-previsioni-csv")] [HttpGet] public HttpResponseMessage Get_GeneraPrevisioniCSV(string impianto, string settimana) { StringBuilder reportString = new StringBuilder(); reportString.Append("bla, bla";\r\n"); reportString.Append("bla, bla";\r\n"); using (StringWriter sw = new StringWriter()) { using (HtmlTextWriter htw = new HtmlTextWriter(sw)) { HttpResponseMessage cResponse = new HttpResponseMessage(HttpStatusCode.OK); cResponse.Content = new StringContent(reportString.ToString(), System.Text.Encoding.Unicode); cResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-excel"); cResponse.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "file.csv" }; } } return cResponse; }
Esempio array di un File PDF
Notare loByteArrayContent
che definisce il tipo del Content. Notare anche la gestione dell'eccezione nel blocco Catch ed il ContentType Text/html
[ActionName("stampa-menu-anteprimaordini")] [Route("stampa-menu-anteprimaordini")] [HttpPost] public HttpResponseMessage Get_GeneraPrevisioniCSV(string impianto, string settimana) { HttpResponseMessage cResponse; try { using (StringWriter sw = new StringWriter()) { using (HtmlTextWriter htw = new HtmlTextWriter(sw)) { MemoryStream streamPDF = new MemoryStream(); streamPDF = CostruisciPDF_AnteprimaOrdini(aof, ref pdfFileNameFullPath); // <-- ! cResponse = new HttpResponseMessage(HttpStatusCode.OK); cResponse.Content = new ByteArrayContent(streamPDF.ToArray()); cResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); cResponse.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("Content-Disposition") { FileName = "file.pdf" }; return cResponse; } } } catch (Exception e) { string errorMessage = string.Format("Errore generico {0}, {1}", e.HResult, e.Message); log.ErrorFormat(errorMessage); cResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); cResponse.Content = new StringContent(errorMessage, System.Text.Encoding.Unicode, "text/html"); } } return cResponse; }
Esempi
Esempio di come si possa passare una dato strutturato di ritorno o un errore per entità non trovata o un errore come emerso da un blocco try catch:
// GetEmployee action public HttpResponseMessage GetEmployee(int id) { try { Employee emp = EmployeeContext.Employees.Where(e => e.Id == id).FirstOrDefault(); if (emp != null) { return Request.CreateResponse<Employee>(HttpStatusCode.OK, emp); } else { return Request.CreateErrorResponse(HttpStatusCode.NotFound, " Employee Not Found"); } } catch (Exception ex) { // Log exception code goes here return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Error occured while executing GetEmployee”); } }
Routing
Sicurezza
Autenticazione e Autorizzazione
Risorse:
- Autenticazione codeproject.com
- Autenticazione, con video tutorial, dotnetawesome
- OWIN OAuth [4]
- ! codeproject
- Soluzione WebApiSingleTenant
- [5], ASP.NET Web API 2 Basic Auth & JWT Token Demo: [6]
Basic Autentication
Esempio: technical-recipes.com
Mappa e Link
WEB API | WebAPI Esempi | WCF | C# | Teoria
Soluzioni varie | Visual Studio
Parole chiave: WebAPI, Web API