[C#] Web Api 컨트롤러에서 http 상태 코드 반환

웹 API 컨트롤러에서 GET 메소드에 대해 수정되지 않은 상태 코드 304를 반환하려고합니다.

내가 성공한 유일한 방법은 다음과 같습니다.

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;
    }
}

여기서 문제는 예외가 아니라 클라이언트 캐시가 정상이므로 수정되지 않았기 때문입니다. 또한 반환 유형이 사용자가되기를 원합니다 (모든 웹 API 예제는 GET으로 표시됨) HttpResponseMessage 또는 이와 유사한 것을 반환하지 않습니다.



답변

나는 대답을 몰랐기 때문에 여기 에서 ASP.NET 팀에 물었다 .

따라서 트릭은로 서명을 변경 HttpResponseMessage하고 사용하는 것 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);
}


답변

조치 서명을 리턴 사용자로 유지하려는 경우 다음을 수행 할 수도 있습니다.

public User GetUser(int userId, DateTime lastModifiedAtClient) 

당신이 다른 것을 반환하고 싶다면 , 당신은 당신의 행동 200을 던져서 당신이 클라이언트에게 보내고 싶은 것을 전달합니다.HttpResponseExceptionHttpResponseMessage


답변

MVC 5에서는 일이 쉬워졌습니다.

return new StatusCodeResult(HttpStatusCode.NotModified, this);


답변

GetXxx API 메소드를 변경하여 HttpResponseMessage를 리턴 한 후 전체 응답에 대한 유형화 된 버전과 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);
        }
    }

* ClientHasStale 데이터는 ETag 및 IfModifiedSince 헤더를 확인하기위한 확장입니다.

MVC 프레임 워크는 여전히 개체를 직렬화하고 반환해야합니다.

노트

향후 버전의 Web API에서 일반 버전이 제거되고 있다고 생각합니다.


답변

나는 오래된 기사를 부딪 치는 것을 싫어하지만 이것은 Google 검색 에서이 첫 번째 결과 이며이 문제에 대해 많은 시간을 보냈습니다 (여러분의 지원조차도). 그래서 여기에 아무 것도 가지 않습니다 …

내 솔루션이 혼란스러워하는 사람들을 도울 수 있기를 바랍니다.

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;
        }
    }
}

그런 다음 BaseController에서 상속받습니다.

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

그런 다음 사용

[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);
}


답변

.net core 2.2에서 304 상태 코드를 반환합니다. 이것은 ApiController를 사용하고 있습니다.

    [HttpGet]
    public ActionResult<YOUROBJECT> Get()
    {
        return StatusCode(304);
    }

선택적으로 응답과 함께 객체를 반환 할 수 있습니다

    [HttpGet]
    public ActionResult<YOUROBJECT> Get()
    {
        return StatusCode(304, YOUROBJECT);
    }


답변

ASP.NET Web Api 2의 경우 MS 의이 게시물 은 메소드의 반환 유형을로 변경하도록 제안합니다 IHttpActionResult. 그런 다음에 내장을 반환 할 수 있습니다 IHttpActionResult와 같은 구현 Ok, BadRequest등 ( 여기 참조 ) 또는 자신의 구현을 반환합니다.

코드의 경우 다음과 같이 수행 할 수 있습니다.

public IHttpActionResult GetUser(int userId, DateTime lastModifiedAtClient)
{
    var user = new DataEntities().Users.First(p => p.Id == userId);
    if (user.LastModified <= lastModifiedAtClient)
    {
        return StatusCode(HttpStatusCode.NotModified);
    }
    return Ok(user);
}