c# - net - web api response type




Devolver código de estado http desde el controlador Web Api (6)

Cambie el método GetXxx API para devolver HttpResponseMessage y luego devuelva una versión mecanografiada para la respuesta completa y la versión sin tipo para la respuesta NotModified.

    public HttpResponseMessage GetComputingDevice(string id)
    {
        ComputingDevice computingDevice =
            _db.Devices.OfType<ComputingDevice>()
                .SingleOrDefault(c => c.AssetId == id);

        if (computingDevice == null)
        {
            return this.Request.CreateResponse(HttpStatusCode.NotFound);
        }

        if (this.Request.ClientHasStaleData(computingDevice.ModifiedDate))
        {
            return this.Request.CreateResponse<ComputingDevice>(
                HttpStatusCode.OK, computingDevice);
        }
        else
        {
            return this.Request.CreateResponse(HttpStatusCode.NotModified);
        }
    }

* Los datos de ClientHasStale son mi extensión para verificar los encabezados de ETag y IfModifiedSince.

El framework MVC aún debe serializar y devolver su objeto.

NOTA

Creo que la versión genérica se eliminará en alguna versión futura de la API web.

Estoy tratando de devolver un código de estado de 304 no modificado para un método GET en un controlador de API web.

La única forma en que tuve éxito fue algo como esto:

public class TryController : ApiController
{
    public User GetUser(int userId, DateTime lastModifiedAtClient)
    {
        var user = new DataEntities().Users.First(p => p.Id == userId);
        if (user.LastModified <= lastModifiedAtClient)
        {
             throw new HttpResponseException(HttpStatusCode.NotModified);
        }
        return user;
    }
}

El problema aquí es que no es una excepción, simplemente no se modifica, por lo que la memoria caché del cliente está bien. También quiero que el tipo de devolución sea un Usuario (como todos los ejemplos de la API web muestran con GET) no devuelve HttpResponseMessage o algo así.


En MVC 5, las cosas se pusieron más fáciles:

return new StatusCodeResult(HttpStatusCode.NotModified, this);

No sabía la respuesta, así que le pregunté al equipo de ASP.NET here .

Entonces, el truco es cambiar la firma a HttpResponseMessage y usar Request.CreateResponse .

[ResponseType(typeof(User))]
public HttpResponseMessage GetUser(HttpRequestMessage request, int userId, DateTime lastModifiedAtClient)
{
    var user = new DataEntities().Users.First(p => p.Id == userId);
    if (user.LastModified <= lastModifiedAtClient)
    {
         return new HttpResponseMessage(HttpStatusCode.NotModified);
    }
    return request.CreateResponse(HttpStatusCode.OK, user);
}

Odio chocar con los artículos antiguos, pero este es el primer resultado para esto en la búsqueda de Google y tuve un gran problema con este problema (incluso con el apoyo de ustedes). Entonces aquí no pasa nada ...

Espero que mi solución ayude a aquellos que también estaban confundidos.

namespace MyApplication.WebAPI.Controllers
{
    public class BaseController : ApiController
    {
        public T SendResponse<T>(T response, HttpStatusCode statusCode = HttpStatusCode.OK)
        {
            if (statusCode != HttpStatusCode.OK)
            {
                // leave it up to microsoft to make this way more complicated than it needs to be
                // seriously i used to be able to just set the status and leave it at that but nooo... now 
                // i need to throw an exception 
                var badResponse =
                    new HttpResponseMessage(statusCode)
                    {
                        Content =  new StringContent(JsonConvert.SerializeObject(response), Encoding.UTF8, "application/json")
                    };

                throw new HttpResponseException(badResponse);
            }
            return response;
        }
    }
}

y luego simplemente heredar de BaseController

[RoutePrefix("api/devicemanagement")]
public class DeviceManagementController : BaseController
{...

y luego usarlo

[HttpGet]
[Route("device/search/{property}/{value}")]
public SearchForDeviceResponse SearchForDevice(string property, string value)
{
    //todo: limit search property here?
    var response = new SearchForDeviceResponse();

    var results = _deviceManagementBusiness.SearchForDevices(property, value);

    response.Success = true;
    response.Data = results;

    var statusCode = results == null || !results.Any() ? HttpStatusCode.NoContent : HttpStatusCode.OK;

    return SendResponse(response, statusCode);
}

Si necesita devolver un IHttpActionResult y desea devolver el código de error más un mensaje, use:

return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.NotModified, "Error message here"));

También puede hacer lo siguiente si desea conservar la firma de acción como usuario que regresa:

public User GetUser(int userId, DateTime lastModifiedAtClient) 

Si desea devolver algo que no sea 200 , HttpResponseException una HttpResponseException en su acción y pasa el HttpResponseMessage que desea enviar al cliente.





http-status-codes