Solución:
La versión más básica que responde con un JsonResult
es:
// GET: api/authors
[HttpGet]
public JsonResult Get()
return Json(_authorRepository.List());
Sin embargo, esto no ayudará con su problema porque no puede manejar explícitamente su propio código de respuesta.
La forma de tener control sobre los resultados de estado es que debe devolver un
ActionResult
que es donde puede aprovechar lasStatusCodeResult
escribe.
por ejemplo:
// 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);
Tenga en cuenta que los dos ejemplos anteriores provienen de una excelente guía disponible en la documentación de Microsoft: Formateo de datos de respuesta
Cosas extra
El problema con el que me encuentro con bastante frecuencia es que quería un control más granular sobre mi WebAPI en lugar de simplemente ir con la configuración predeterminada de la plantilla “Nuevo proyecto” en VS.
Asegurémonos de conocer algunos de los conceptos básicos …
Paso 1: configura tu servicio
Para que su ASP.NET Core WebAPI responda con un objeto serializado JSON junto con el control total del código de estado, debe comenzar asegurándose de haber incluido el AddMvc()
servicio en tu ConfigureServices
método generalmente encontrado en Startup.cs
.
Es importante tener en cuenta que
AddMvc()
incluirá automáticamente el formateador de entrada / salida para JSON junto con la respuesta a otros tipos de solicitudes.
Si su proyecto requiere control total y desea definir estrictamente sus servicios, por ejemplo, cómo se comportará su WebAPI ante varios tipos de solicitudes, incluidas application/json
y no responder a otros tipos de solicitud (como una solicitud estándar del navegador), puede definirla manualmente con el siguiente código:
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();
//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)
Notará que también he incluido una forma de agregar sus propios formateadores de entrada / salida personalizados, en caso de que desee responder a otro formato de serialización (protobuf, thrift, etc.).
El fragmento de código anterior es principalmente un duplicado del AddMvc()
método. Sin embargo, estamos implementando cada servicio “predeterminado” por nuestra cuenta definiendo todos y cada uno de los servicios en lugar de ir con el pre-enviado con la plantilla. He agregado el enlace del repositorio en el bloque de código, o puede consultar AddMvc()
desde el repositorio de GitHub.
Tenga en cuenta que hay algunas guías que intentarán resolver esto “deshaciendo” los valores predeterminados, en lugar de simplemente no implementarlo en primer lugar … Si tiene en cuenta que ahora estamos trabajando con código abierto, este es un trabajo redundante. , mal código y francamente un viejo hábito que desaparecerá pronto.
Paso 2: crea un controlador
Voy a mostrarte uno realmente sencillo solo para resolver tu pregunta.
public class FooController
[HttpPost]
public async Task 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();
Paso 3: revisa tu Content-Type
y Accept
Debe asegurarse de que su Content-Type
y Accept
encabezados en tu solicitud están configurados correctamente. En su caso (JSON), querrá configurarlo para que sea application/json
.
Si desea que su WebAPI responda como JSON de forma predeterminada, independientemente de lo que especifique el encabezado de la solicitud, puede hacerlo en un par de formas.
Camino 1
Como se muestra en el artículo que recomendé anteriormente (Formateo de datos de respuesta), puede forzar un formato particular en el nivel de Controlador / Acción. Personalmente no me gusta este enfoque … pero aquí está para completar:
Forzar un formato particular Si desea restringir los formatos de respuesta para una acción específica, puede aplicar la
[Produces] filtrar. los [Produces] filter especifica los formatos de respuesta para una acción específica (o controlador). Como la mayoría de los filtros, esto se puede aplicar en la acción, el controlador o el ámbito global.[Produces("application/json")] public class AuthorsController
los
[Produces]
El filtro forzará todas las acciones dentro del
AuthorsController
para devolver respuestas con formato JSON, incluso si se configuraron otros formateadores para la aplicación y el cliente proporcionó unAccept
encabezado solicitando un formato diferente disponible.
Camino 2
Mi método preferido es que WebAPI responda a todas las solicitudes con el formato solicitado. Sin embargo, en el caso de que no acepte el formato solicitado, entonces retroceder a un valor predeterminado (es decir, JSON)
Primero, deberá registrar eso en sus opciones (necesitamos reelaborar el comportamiento predeterminado, como se señaló anteriormente)
options.RespectBrowserAcceptHeader = true; // false by default
Finalmente, simplemente reordenando la lista de formateadores que se definieron en el generador de servicios, el servidor web tomará por defecto el formateador que usted coloca en la parte superior de la lista (es decir, posición 0).
Puede encontrar más información en esta entrada del Blog de herramientas y desarrollo web de .NET
Tiene métodos predefinidos para los códigos de estado más comunes.
Ok(result)
devoluciones200
con respuestaCreatedAtRoute
devoluciones201
+ URL de nuevo recursoNotFound
devoluciones404
BadRequest
devoluciones400
etc.
Ver BaseController.cs
y Controller.cs
para obtener una lista de todos los métodos.
Pero si realmente insistes, puedes usar StatusCode
para configurar un código personalizado, pero realmente no debería hacerlo, ya que hace que el código sea menos legible y tendrá que repetir el código para configurar los encabezados (como para CreatedAtRoute
).
public ActionResult IsAuthenticated()
return StatusCode(200, "123");
Con ASP.NET Core 2.0, la forma ideal de devolver un objeto de Web API
(que está unificado con MVC y usa la misma clase base Controller
) es
public IActionResult Get()
return new OkObjectResult(new Item Id = 123, Name = "Hero" );
Darse cuenta de
- Vuelve con
200 OK
código de estado (es unOk
tipo deObjectResult
) - Realiza negociación de contenido, es decir, volverá en función de
Accept
encabezado en solicitud. SiAccept: application/xml
se envía en solicitud, volverá comoXML
. Si no se envía nada,JSON
es predeterminado.
Si necesita enviar con código de estado específico, usar ObjectResult
o StatusCode
en lugar de. Ambos hacen lo mismo y admiten la negociación de contenido.
return new ObjectResult(new Item Id = 123, Name = "Hero" ) StatusCode = 200 ;
return StatusCode( 200, new Item Id = 123, Name = "Hero" );
o incluso más detallado con ObjectResult:
Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection myContentTypes = new Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection System.Net.Mime.MediaTypeNames.Application.Json ;
String hardCodedJson = ""Id":"123","DateOfRegistration":"2012-10-21T00:00:00+05:30","Status":0";
return new ObjectResult(hardCodedJson) StatusCode = 200, ContentTypes = myContentTypes ;
Si específicamente quieres volver como JSON, hay un par de formas
//GET http://example.com/api/test/asjson
[HttpGet("AsJson")]
public JsonResult GetAsJson()
return Json(new Item Id = 123, Name = "Hero" );
//GET http://example.com/api/test/withproduces
[HttpGet("WithProduces")]
[Produces("application/json")]
public Item GetWithProduces()
return new Item Id = 123, Name = "Hero" ;
Darse cuenta de
- Ambos hace cumplir
JSON
de dos formas diferentes. - Ambos ignoran la negociación de contenido.
- El primer método aplica JSON con un serializador específico
Json(object)
. - El segundo método hace lo mismo usando
Produces()
attribute (el cual es unResultFilter
) concontentType = application/json
Lea más sobre ellos en los documentos oficiales. Obtenga más información sobre los filtros aquí.
La clase de modelo simple que se usa en las muestras
public class Item
public int Id get; set;
public string Name get; set;
Puntuaciones y reseñas
Recuerda algo, que te brindamos la opción de interpretar tu experiencia si tropezaste tu escollo .