Come visto nell'articolo "Applicazioni web basate su servizi: un approccio alternativo con ASP.NET MVC2", è possibile utilizzare ASP.NET MVC per realizzare un RESTful web service. L'esempio proposto nell'articolo evidenzia l'utilizzo dei verbi http più comuni, GET e POST, ma il paradigma REST contempla anche l'utilizzo dei verbi PUT e DELETE, tipicamente associati ad operazioni rispettivamente di aggiornamento e cancellazione.
Il vantaggio di utilizzare questi due ulteriori verbi è che ci consente di discriminare le operazioni da effettuare su una collection tramite essi, piuttosto che a livello di URL; quest'ultimo, invece, riveste semplicemente lo scopo di indentificare la risorsa che si vuole gestire. Supponendo, infatti, che l'indirizzo base per la collezione di elementi del guestbook sia, ad esempio, localhost/items, il servizio REST dovrebbe rispettare le seguenti convenzioni:
- A una richiesta in GET a localhost/items, restituire l'elenco degli elementi;
- a una richiesta in POST a localhost/items, aggiungere un elemento all'elenco;
- a una richiesta in GET a localhost/items/122, restituire l'elemento di ID 122;
- a una richiesta in PUT a localhost/items/122, aggiornare l'elemento di ID 122;
- a una richiesta in DELETE a localhost/items/122, eliminare l'elemento di ID 122;
In ASP.NET MVC, gli ActionMethod sono comunque in grado di gestire anche richieste PUT o DELETE una volta marcati gli con appositi attributi HttpPut ed HttpDelete, rispettivamente per associare il metodo al solo verbo PUT ed al solo verbo DELETE.
Ipotizziamo allora di voler eliminare un item, identificato univocamente da un id numerico, dal repository di dati del guestbook di esempio dell'articolo: decoriamo il metodo Delete del controller con l'attributo HttpDelete.
[HttpDelete][ActionName("Default")] public ActionResult Delete(int id) { string returnValue = string.Empty; try { // ... // Logica di gestione della cancellazione // ... returnValue = "OK"; } catch { // Valorizza il messaggio di risposta in caso di errore returnValue = "Si è verificato un errore interno. Non è stato possibile eliminare il post."; } return Json(retValue); }
In tal modo l'ActionMethod risponderà solo ed esclusivamente a richieste http DELETE. In tutti gli altri casi verrà restituito un errore 404. Come possiamo notare, è stato aggiunto anche l'attributo ActionName, per associare questo metodo ad una action chiamata Default. In questo modo, configurando quest'ultima come quella di default per il controller ItemsController, è possibile rispettare perfettamente la convenzione sul naming che abbiamo espresso in precedenza.
Il caso dell'aggiornamento è analogo a quello della cancellazione, ad eccezione del marcatore, e del parametro di input, che in questo caso conterrà l'intero oggetto.
[HttpPut][ActionName("Default")] public ActionResult Update(GuestbookItemModel item) { if (ModelState.IsValid) { try { // ... // Logica di gestione aggiornamento // ... item.ResponseMessage = "OK"; } catch { // Valorizza il messaggio di risposta in caso di errore item.ResponseMessage = "Si è verificato un errore interno. Non è stato possibile eliminare il post."; } } else { // Valorizza il messaggio di risposta in caso di errore // di validazione e popola una collection con i dettagli. item.ResponseMessage = "Uno o più campi non sono validi"; item.ErrorDetails = new ArrayList(); foreach (var key in ModelState.Keys) { var error = ModelState[key].Errors.FirstOrDefault(); if (error != null) item.ErrorDetails.Add(error.ErrorMessage); } } return Json(item); }
Per verificarne il funzionamento, anche in questo caso è possibile simulare le chiamate e vederne gli effetti utilizzando jQuery, prestando però attenzione ad un aspetto importante: jQuery supporta perfettamente i verbi PUT e DELETE, come pure i principali browser (Internet Explorer, Firefox, Chrome e Opera), ma in generale non tutti i browser sono in grado di gestire questi verbi.
Nel caso della cancellazione, ad esempio, possiamo effettuare una chiamata al metodo ajax() impostando il verbo DELETE tramite il parametro type, ed associando all'URL l'id dell'elemento da eliminare serializzato in JSON.
function submitDelete() { // Legge i dati var id = $('#id).val(); // Invia il DELETE $.ajax({ url: '/Items/' + id, type: "DELETE", dataType: "json", success: function (result) { if (result.ResponseMessage == "OK") { // ... // Gestisce la risposta corretta // ... } else { // ... // Gestisce l'errore // ... } } }); }
Il caso dell'aggiornamento è assolutamente analogo al precedente, dal quale differisce per il parametro type della chiamata, impostato a PUT, e per i dati inviati, serializzati in JSON, che comprendono in questo caso l'intero oggetto del modello.
function submitUpdate() { // Legge i dati dal form var id = $('#id').val(); var title = $('#Title').val(); var body = $('#Body').val(); var authorName = $('#AuthorName').val(); var authorEmail = $('#AuthorEmail').val(); // Costruisce la struttura JSON var putData = '{ "item" : { "ID" : "' + id + '", "Title" : "' + title + '", "Body" : "' + body + '", "AuthorName" : "' + authorName + '", "AuthorEmail" : "' + authorEmail + '" } }'; // Invia il PUT $.ajax({ url: '/Items/' + id, type: "PUT", data: putData , dataType: "json", contentType: "application/json", success: function (result) { if (result.ResponseMessage == "OK") { // ... // Gestisce la risposta corretta // ... } else { // ... // Gestisce l'errore // ... } } }); }
Un'ultima nota riguarda il requisito, anch'esso convenzionale, che invocazioni PUT e DELETE siano idempotenti. Pertanto, è necessario implementare i rispettivi metodi sul servizio in modo che, anche in presenza di esecuzioni multiple, il risultato sia sempre il medesimo.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Eseguire task temporizzati tramite hosted service in ASP.NET Core
Leggere il valore di un header della richiesta in ASP.NET Core 6
Utilizzare le Promise in Javascript - prima parte
Iniettare servizi in un hosted service di ASP.NET Core
Le novità di Angular 13 e del suo ecosistema
Generare un QR Code da ASP.NET Web API
Eseguire uno scroll all'interno di una pagina Blazor
Creare Higher-Order functions in JavaScript
Gestire query string lunghe in ASP.NET Core
Utilizzare la keyword with in JavaScript
Dichiarare una variabile in JavaScript con le parole chiave var, let e const
Web3, Smart Contract, Metamask e Web Application
I più letti di oggi
- Eseguire uno scroll all'interno di una pagina Blazor
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- Gestire il timing sugli eventi all'interno di un'applicazione Blazor
- Specificare un attributo in JSX
- Collegare la ListView di jQuery Mobile ad una fonte dati con ASP.NET