In ASP.NET Core, lo stack tecnologico su cui sono costruiti MVC e Web API è stato unificato e la classe Controller è quindi adatta sia a realizzare siti web che REST API. Tuttavia, non dobbiamo dimenticare che questi due tipi di applicazione mantengono le loro peculiarità: ciò che distingue un progetto ASP.NET Web API, ad esempio, è l'interazione con applicazioni client e il mutuo scambio di dati JSON, che deve essere adeguatamente documentato con lo standard Swagger/OpenAPI.
Dalla versione 2.1 di ASP.NET Core è stato introdotto l'attributo ApiController che configura i nostri Controller in modo che si adattino meglio alle peculiarità di un'applicazione Web API. L'attributo va posto sul Controller e usato obbligatoriamente in combinazione con l'attribute routing, come nel seguente esempio.
[ApiController, Route("[controller]")] public class ProductController : Controller { [HttpPost, Route("")] public ActionResult<ProductDto> CreateProduct(ProductCreationModel model) { //... } }
Il primo dei vantaggi l'abbiamo nella documentazione: grazie anche al tipo di ritorno ActionResult<T>, introdotto anch'esso con ASP.NET Core 2.1, riusciamo col minimo sforzo a rendere evidenti quali siano le strutture dati ricevute in input e restituite come risultato.

Di solito, le action di aggiornamento come la CreateProduct che abbiamo visto nell'esempio precedente accettano un parametro di tipo complesso come ProductCreationModel che rappresenta il contenuto JSON inviato dal client. È importante verificare che i valori contenuti in questo oggetto rispettino i vincoli definiti tramite data annotation (ad esempio, una proprietà non deve essere vuota se è stata annotata con [Required]). Perciò si esamina il valore di ModelState.IsValid e, se fosse false, si interrompe prematuramente l'esecuzione dell'action restituendo un BadRequestObjectResult.
Questa è una buona pratica da usare in quasi tutte le action di una Web API e ora, grazie all'attributo ApiController, la verifica del model viene compiuta automaticamente. Possiamo perciò eliminare il relativo codice dalle nostre action.
[HttpPost, Route("")] public ActionResult<ProductDto> CreateProduct(ProductCreationModel model) { //Se usiamo l'attributo ApiController possiamo eliminare questo codice //if (!ModelState.IsValid) //{ // return BadRequest("The model is not valid"); //} //Qui posso lavorare i dati trovati nell'oggetto ProductCreationModel }
Anche se la verifica avviene automaticamente, abbiamo comunque la possibilità di decidere cosa viene restituito al client quando ci sono errori di validazione nel model. Infatti, dal metodo ConfigureServices della classe Startup possiamo impostare le ApiBehaviorOptions e definire una logica personalizzata di generazione del risultato.
public void ConfigureServices(IServiceCollection services) { //Qui aggiunta di altri servizi... //Questa chiamata va aggiunta in fondo, DOPO services.AddMvc() services.Configure<ApiBehaviorOptions>(options => { options.InvalidModelStateResponseFactory = (ActionContext context) => { var errors = context.ModelState .SelectMany(entry => entry.Value.Errors) .Select(error => error.ErrorMessage); var result = new { Success = false, Errors = errors }; return new BadRequestObjectResult(result); }; }); }
Agendo sulle opzioni possiamo anche disabilitare selettivamente la validazione automatica ma continuare a sfruttare tutti gli altri vantaggi forniti dall'attributo ApiController.
services.Configure<ApiBehaviorOptions>(options => { options.SuppressModelStateInvalidFilter = true; });
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Recuperare automaticamente un utente e aggiungerlo ad un gruppo di Azure DevOps
Persistere la ChatHistory di Semantic Kernel in ASP.NET Core Web API per GPT
Configurare lo startup di applicazioni server e client con .NET Aspire
Potenziare la ricerca su Cosmos DB con Full Text Search
Utilizzare il nuovo modello GPT-4o con Azure OpenAI
Bloccare l'esecuzione di un pod in mancanza di un'artifact attestation di GitHub
Migliorare la sicurezza dei prompt con Azure AI Studio
Creare una libreria CSS universale: Immagini
Eseguire i worklow di GitHub su runner potenziati
Inference di dati strutturati da testo con Semantic Kernel e ASP.NET Core Web API
Utilizzare QuickGrid di Blazor con Entity Framework
Fornire parametri ad un Web component HTML
I più letti di oggi
- Organizzare i moduli sfruttando CommonJS in Javascript
- Proteggere le risorse Azure con private link e private endpoints
- Rinnovare il token di una GitHub App durante l'esecuzione di un workflow
- Utilizzare le local static function di C# 8
- Real Code Day - Firenze
- WPC 2011 - Assago (MI)
- Disponibile il codice sorgente di Moonlight
- ADO.NET Data Services Silverlight 2 Beta2 Client library Refresh
- Rilasciata la versione beta dei Windows Phone 7 Developer Tools
- WinPhoneItalia.com: dal 15 settembre tutto per sviluppare per Windows Phone e mobile