La versione più semplice che risponde con a JsonResult
è:
// GET: api/authors
[HttpGet]
public JsonResult Get()
{
return Json(_authorRepository.List());
}
Tuttavia, questo non ti aiuterà a risolvere il problema perché non puoi gestire esplicitamente il tuo codice di risposta.
Il modo per ottenere il controllo sui risultati dello stato è che è necessario restituire un oggetto in ActionResult
cui è possibile sfruttare il StatusCodeResult
tipo.
per esempio:
// GET: api/authors/search?namelike=foo
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
var result = _authorRepository.GetByNameSubstring(namelike);
if (!result.Any())
{
return NotFound(namelike);
}
return Ok(result);
}
Si noti che entrambi questi esempi sopra riportati provengono da un'ottima guida disponibile nella documentazione Microsoft: formattazione dei dati di risposta
Cose extra
Il problema che ho riscontrato abbastanza spesso è che volevo un controllo più granulare sul mio WebAPI piuttosto che semplicemente andare con la configurazione predefinita dal modello "Nuovo progetto" in VS.
Assicuriamoci di avere alcune delle nozioni di base giù ...
Passaggio 1: configura il tuo servizio
Per fare in modo che la tua ASP.NET Core WebAPI risponda con un oggetto serializzato JSON con il pieno controllo del codice di stato, devi iniziare assicurandoti di aver incluso il AddMvc()
servizio nel tuo ConfigureServices
metodo di solito presente Startup.cs
.
È importante notare che AddMvc()
includerà automaticamente il formattatore di input / output per JSON insieme alla risposta ad altri tipi di richieste.
Se il tuo progetto richiede il pieno controllo e desideri definire rigorosamente i tuoi servizi, ad esempio come il tuo WebAPI si comporterà a vari tipi di richiesta, incluso application/json
e non risponderà ad altri tipi di richiesta (come una richiesta standard del browser), puoi definirlo manualmente con codice seguente:
public void ConfigureServices(IServiceCollection services)
{
// Build a customized MVC implementation, without using the default AddMvc(), instead use AddMvcCore().
// https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs
services
.AddMvcCore(options =>
{
options.RequireHttpsPermanent = true; // does not affect api requests
options.RespectBrowserAcceptHeader = true; // false by default
//options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
//remove these two below, but added so you know where to place them...
options.OutputFormatters.Add(new YourCustomOutputFormatter());
options.InputFormatters.Add(new YourCustomInputFormatter());
})
//.AddApiExplorer()
//.AddAuthorization()
.AddFormatterMappings()
//.AddCacheTagHelper()
//.AddDataAnnotations()
//.AddCors()
.AddJsonFormatters(); // JSON, or you can build your own custom one (above)
}
Noterai che ho anche incluso un modo per aggiungere i tuoi formattatori di input / output personalizzati, nel caso in cui potresti voler rispondere a un altro formato di serializzazione (protobuf, parsimonia, ecc.).
Il pezzo di codice sopra è principalmente un duplicato del AddMvc()
metodo. Tuttavia, stiamo implementando da soli ogni servizio "predefinito" definendo ogni singolo servizio invece di andare con quello pre-spedito con il modello. Ho aggiunto il link al repository nel blocco di codice, oppure puoi controllare AddMvc()
dal repository GitHub. .
Nota che ci sono alcune guide che proveranno a risolvere questo problema "annullando" le impostazioni predefinite, piuttosto che non implementarle in primo luogo ... Se consideri che ora stiamo lavorando con Open Source, questo è un lavoro ridondante , codice errato e francamente una vecchia abitudine che scomparirà presto.
Passaggio 2: creare un controller
Te lo mostrerò davvero semplice solo per risolvere la tua domanda.
public class FooController
{
[HttpPost]
public async Task<IActionResult> Create([FromBody] Object item)
{
if (item == null) return BadRequest();
var newItem = new Object(); // create the object to return
if (newItem != null) return Ok(newItem);
else return NotFound();
}
}
Passaggio 3: controlla il tuo Content-Type
eAccept
Devi assicurarti che tu Content-Type
e le Accept
intestazioni nella tua richiesta siano impostate correttamente. Nel tuo caso (JSON), vorrai configurarlo per essere application/json
.
Se si desidera che WebAPI risponda come JSON come impostazione predefinita, indipendentemente da ciò che l'intestazione della richiesta specifica, è possibile farlo in un paio di modi .
Modo 1
Come mostrato nell'articolo che ho raccomandato in precedenza ( Formattazione dei dati di risposta ) è possibile forzare un formato particolare a livello di controller / azione. Personalmente non mi piace questo approccio ... ma qui è per completezza:
Forzare un formato particolare Se desideri limitare i formati di risposta per un'azione specifica che puoi, puoi applicare il filtro [Produce]. Il filtro [Produce] specifica i formati di risposta per un'azione specifica (o controller). Come la maggior parte dei filtri, questo può essere applicato all'azione, al controller o all'ambito globale.
[Produces("application/json")]
public class AuthorsController
Il [Produces]
filtro imporrà a tutte le azioni all'interno
AuthorsController
di restituire risposte in formato JSON, anche se altri formattatori sono stati configurati per l'applicazione e il client ha fornito Accept
un'intestazione che richiede un formato diverso e disponibile.
Modo 2 Il
mio metodo preferito è che WebAPI risponda a tutte le richieste con il formato richiesto. Tuttavia, nel caso in cui non accetti il formato richiesto, ricorrere a un valore predefinito (es. JSON)
Innanzitutto, devi registrarlo nelle tue opzioni (dobbiamo rielaborare il comportamento predefinito, come notato in precedenza)
options.RespectBrowserAcceptHeader = true; // false by default
Infine, semplicemente riordinando l'elenco dei formatter definiti nel builder di servizi, l'host web passerà automaticamente al formatter che si posiziona in cima all'elenco (ovvero posizione 0).
Ulteriori informazioni sono disponibili in questo post sul blog Strumenti e sviluppo Web .NET
CreatedAtRoute
metodo ecc.