Saltar al contenido

ASP.NET Core devuelve JSON con código de estado

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 las StatusCodeResult 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 queAddMvc() 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ó un Accept 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) devoluciones 200 con respuesta
  • CreatedAtRoute devoluciones 201 + URL de nuevo recurso
  • NotFound devoluciones 404
  • BadRequest devoluciones 400 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

  1. Vuelve con 200 OK código de estado (es un Ok tipo de ObjectResult)
  2. Realiza negociación de contenido, es decir, volverá en función de Accept encabezado en solicitud. Si Accept: application/xml se envía en solicitud, volverá como XML. 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

  1. Ambos hace cumplir JSON de dos formas diferentes.
  2. Ambos ignoran la negociación de contenido.
  3. El primer método aplica JSON con un serializador específico Json(object).
  4. El segundo método hace lo mismo usando Produces() attribute (el cual es un ResultFilter) con contentType = 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 .

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *