Ik'ben op zoek naar de juiste manier om JSON terug te sturen met een HTTP status code in mijn .NET Core Web API controller. Ik gebruikte het als volgt:
public IHttpActionResult GetResourceData()
{
return this.Content(HttpStatusCode.OK, new { response = "Hello"});
}
Dit was in een 4.6 MVC applicatie maar nu met .NET Core lijk ik deze IHttpActionResult
niet meer te hebben ik heb ActionResult
en gebruik het als volgt:
public ActionResult IsAuthenticated()
{
return Ok(Json("123"));
}
Maar het antwoord van de server is raar, zoals in de afbeelding hieronder:
Ik wil gewoon dat de Web API controller JSON terugstuurt met een HTTP status code zoals ik deed in Web API 2.
De meest eenvoudige versie die reageert met een JsonResult
is:
// GET: api/authors
[HttpGet]
public JsonResult Get()
{
return Json(_authorRepository.List());
}
Dit gaat echter'niet helpen met je probleem omdat je niet expliciet om kunt gaan met je eigen response code.
De manier om controle te krijgen over de statusresultaten, is dat je een
ActionResult
moet retourneren, waar je dan gebruik kunt maken van hetStatusCodeResult
type.
Bijvoorbeeld:
// 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);
}
Merk op dat beide bovenstaande voorbeelden afkomstig zijn van een geweldige gids die beschikbaar is bij Microsoft Documentation: Opmaak van responsgegevens
Het probleem dat ik vaak tegenkom is dat ik meer granulaire controle wilde over mijn WebAPI in plaats van gewoon de standaard configuratie te gebruiken van het "New Project" sjabloon in VS.
Laten we ervoor zorgen dat je een aantal van de basisprincipes onder de knie hebt...
Om je ASP.NET Core WebAPI te laten reageren met een JSON Serialized Object samen met volledige controle over de status code, moet je beginnen met ervoor te zorgen dat je de AddMvc()
service hebt opgenomen in je ConfigureServices
methode die meestal te vinden is in Startup.cs
.
Het is belangrijk op te merken dat
AddMvc()
automatisch de Input/Output Formatter voor JSON zal opnemen, samen met het reageren op andere request types.
Als uw project volledige controle vereist en u wilt uw diensten strikt definiëren, zoals hoe uw WebAPI zich zal gedragen naar verschillende verzoektypes waaronder application/json
en niet zal reageren op andere verzoektypes (zoals een standaard browser verzoek), dan kunt u dit handmatig definiëren met de volgende code:
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)
}
U zult merken dat ik ook een manier heb toegevoegd om uw eigen aangepaste Input/Output formatters toe te voegen, in het geval dat u wilt reageren op een ander serialisatie formaat (protobuf, thrift, etc).
Het stuk code hierboven is grotendeels een duplicaat van de AddMvc()
methode. Echter, we implementeren elke "default" service op onze eigen manier door elke service te definiëren in plaats van gebruik te maken van de vooraf geleverde service met de template. Ik heb de link naar de repository in het codeblok toegevoegd, of je kunt AddMvc()
bekijken vanuit de GitHub repository..
Merk op dat er sommige gidsen zijn die dit proberen op te lossen door "undoing" de defaults, in plaats van het gewoon niet te implementeren in de eerste plaats... Als je er rekening mee houdt dat we'nu met Open Source werken, is dit overbodig werk, slechte code en eerlijk gezegd een oude gewoonte die binnenkort zal verdwijnen.
Ik'ga je een heel eenvoudige laten zien om je vraag op te lossen.
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();
}
}
Content-Type
en Accept
Je moet ervoor zorgen dat je Content-Type
en Accept
headers in je request goed zijn ingesteld. In uw geval (JSON), zult u willen instellen dat het application/json
is.
Als u wilt dat uw WebAPI standaard reageert als JSON, ongeacht wat de request header specificeert, kunt u dat op een paar manieren doen.
Manier 1 Zoals aangetoond in het artikel dat ik eerder heb aanbevolen (Formatting Response Data) kun je een bepaald formaat afdwingen op Controller/Action niveau. Ik persoonlijk hou niet van deze aanpak ... maar hier is het voor de volledigheid:
Forcing a Particular Format Als je de responsformaten voor een specifieke actie zou willen beperken kan dat, je kunt de [Produceert] filter toepassen. Het [Produceert] filter specificeert de response formaten voor een specifieke actie (of controller). Zoals de meeste Filters, kan dit kan worden toegepast op de actie, controller, of globale scope.
[Produces("application/json")] public class AuthorsController
Het
[Produces]
filter dwingt alle acties binnen deAuthorsController
om JSON-geformatteerde antwoorden te retourneren, zelfs als andere formatters waren geconfigureerd voor de applicatie en de client een eenAccept
header die om een ander, beschikbaar formaat vraagt.
Manier 2 Mijn voorkeursmethode is dat de WebAPI op alle verzoeken reageert met het gevraagde formaat. Echter, in het geval dat het niet het gevraagde formaat accepteren, dan terugvallen naar een standaard (dat wil zeggen JSON)
Eerst moet je dat registreren in je opties (we moeten het standaard gedrag herwerken, zoals eerder opgemerkt)
options.RespectBrowserAcceptHeader = true; // false by default
Tenslotte, door eenvoudigweg de lijst van de formatters te herschikken die in de services builder zijn gedefinieerd, zal de web host standaard de formatter gebruiken die bovenaan de lijst staat (d.w.z. positie 0).
Meer informatie is te vinden in deze .NET Web Development and Tools Blog entry
U beschikt over voorgedefinieerde methodes voor de meest voorkomende statuscodes.
Ok(result)
retourneert 200
met antwoordCreatedAtRoute
retourneert 201
+ nieuwe resource URLNotFound
retourneert 404
BadRequest
retourneert 400
enz.Zie BaseController.cs
en Controller.cs
voor een lijst van alle methodes.
Maar als je er echt op staat kun je StatusCode
gebruiken om een aangepaste code in te stellen, maar dat moet je echt niet doen omdat het de code minder leesbaar maakt en je'code moet herhalen om headers in te stellen (zoals voor CreatedAtRoute
).
public ActionResult IsAuthenticated()
{
return StatusCode(200, "123");
}
Zie onderstaande code, U kunt meerdere status codes beheren met verschillende type JSON
public async Task<HttpResponseMessage> GetAsync()
{
try
{
using (var entities = new DbEntities())
{
var resourceModelList = entities.Resources.Select(r=> new ResourceModel{Build Your Resource Model}).ToList();
if (resourceModelList.Count == 0)
{
return this.Request.CreateResponse<string>(HttpStatusCode.NotFound, "No resources found.");
}
return this.Request.CreateResponse<List<ResourceModel>>(HttpStatusCode.OK, resourceModelList, "application/json");
}
}
catch (Exception ex)
{
return this.Request.CreateResponse<string>(HttpStatusCode.InternalServerError, "Something went wrong.");
}
}