我试图返回一个状态代码304未修改的web api控制器中的GET方法。
我成功的唯一方法是这样的:
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;
}
}
这里的问题是,它不是一个异常,它只是没有修改,所以客户端缓存是OK的。
我还希望返回类型是一个用户(所有的web api示例显示与GET)不返回HttpResponseMessage或类似的东西。
我知道这里有几个很好的答案,但这是我需要的,所以我想我应该添加这个代码,以防任何人需要返回任何状态代码和响应体,他们想在4.7。x与webAPI。
public class DuplicateResponseResult<TResponse> : IHttpActionResult
{
private TResponse _response;
private HttpStatusCode _statusCode;
private HttpRequestMessage _httpRequestMessage;
public DuplicateResponseResult(HttpRequestMessage httpRequestMessage, TResponse response, HttpStatusCode statusCode)
{
_httpRequestMessage = httpRequestMessage;
_response = response;
_statusCode = statusCode;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage(_statusCode);
return Task.FromResult(_httpRequestMessage.CreateResponse(_statusCode, _response));
}
}
我不喜欢改变我的签名来使用HttpCreateResponse类型,所以我提出了一个扩展的解决方案来隐藏它。
public class HttpActionResult : IHttpActionResult
{
public HttpActionResult(HttpRequestMessage request) : this(request, HttpStatusCode.OK)
{
}
public HttpActionResult(HttpRequestMessage request, HttpStatusCode code) : this(request, code, null)
{
}
public HttpActionResult(HttpRequestMessage request, HttpStatusCode code, object result)
{
Request = request;
Code = code;
Result = result;
}
public HttpRequestMessage Request { get; }
public HttpStatusCode Code { get; }
public object Result { get; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Request.CreateResponse(Code, Result));
}
}
然后你可以添加一个方法到你的ApiController(或者更好的是你的基本控制器),像这样:
protected IHttpActionResult CustomResult(HttpStatusCode code, object data)
{
// Request here is the property on the controller.
return new HttpActionResult(Request, code, data);
}
然后你可以像任何内置方法一样返回它:
[HttpPost]
public IHttpActionResult Post(Model model)
{
return model.Id == 1 ?
Ok() :
CustomResult(HttpStatusCode.NotAcceptable, new {
data = model,
error = "The ID needs to be 1."
});
}
更改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框架仍然应该序列化并返回您的对象。
NOTE
我认为通用版本将在未来的Web API版本中被删除。