WebApi2 IHttpActionResult强类型返回值

Mar*_*rkD 5 c# generics httpresponse asp.net-web-api2

这样做可能是不理想的:(一个大大简化的示例!)

[Serializable]
public class MyRecord
{
    public string key {get; set;}
    public string data {get; set;}
}

public async Task<IHttpActionResult> Get(string SomeKey)
{
    if(ExistsInDB(SomeKey))
    {
        return Ok(SomeRecordFromDB(SomeKey));  //SomeRecord() returns a POCO MyRecord.
    }
    else
    {
        //I know I can return NotFound() but not the focus of my Q
        return Ok(false);  //returns "False"
    }
}
Run Code Online (Sandbox Code Playgroud)

有效地表明对返回类型没有编译时错误检查。这个例子将返回一个JSon序列化的POCO类(在我的accept标头上设置了JSon),或者返回文本“ False”,这给客户端增加了类型检查的负担。

我不是故意设计的,但是我的团队正在从asmx / svc 重构大量代码,并且错误不断蔓延。当编译器帮助捕获这类错误而不是等待模块或单元测试时,我喜欢它。

返回使用强类型方法签名的正确方法(避免使用IHttpActionResult和Ok(),NotFound()等帮助器IHttpActionResult<T>吗?还是可以使用诸如a之类的 方法来确保返回正确的类型?

M.

Raf*_*ues 3

首先,返回IHttpActionResult,表明相应的是一个很好的做法http status。就像是:

public async Task<IHttpActionResult> Get(string SomeKey)
{
    if(ExistsInDB(SomeKey))
        return Ok(SomeRecordFromDB(SomeKey));

    return NotFound();
}
Run Code Online (Sandbox Code Playgroud)

但如果你真的想要一个强类型的 api,你可以这样做:

 public async Task<StronglyTypeResponse> Get()
 {
     return new StronglyTypeResponse();
 }
Run Code Online (Sandbox Code Playgroud)

或者,创建一个键入的响应,您将在响应中保留 http 状态代码等:

public class StronglyTypeResponse
{

}

public class StronglyTypedResult<T> : IHttpActionResult
{
    HttpConfiguration _configuration;
    T _content;
    HttpStatusCode _statusCode;
    HttpRequestMessage _request;

    public StronglyTypedResult(T content, HttpStatusCode statusCode, HttpRequestMessage request, HttpConfiguration configuration)
    {
        _content = content;
        _request = request;
        _configuration = configuration;
        _statusCode = statusCode;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(_statusCode)
        {
            Content = new ObjectContent<dynamic>(_content, _configuration.Formatters.JsonFormatter),
            RequestMessage = _request,
            ReasonPhrase = "some phrase"
        };

        return Task.FromResult(response);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以创建你的方法:

public async Task<StronglyTypedResult<StronglyTypeResponse>> Get()
{
    return new StronglyTypedResult<StronglyTypeResponse>(new StronglyTypeResponse(), HttpStatusCode.OK, Request, Configuration);
}
Run Code Online (Sandbox Code Playgroud)

创建您自己的自定义通用 IHttpActionResult

基本上是一样的:

public class IHttpActionResult<T> : System.Web.Http.IHttpActionResult
{
    HttpConfiguration _configuration;
    T _content;
    HttpStatusCode _statusCode;
    HttpRequestMessage _request;

    public IHttpActionResult(T content, HttpStatusCode statusCode, HttpRequestMessage request, HttpConfiguration configuration)
    {
        _content = content;
        _request = request;
        _configuration = configuration;
        _statusCode = statusCode;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(_statusCode)
        {
            Content = new ObjectContent<dynamic>(_content, _configuration.Formatters.JsonFormatter),
            RequestMessage = _request,
            ReasonPhrase = "some phrase"
        };

        return Task.FromResult(response);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以用类型返回你想要的类IHttpActionResult

public async Task<IHttpActionResult<YourClass>> Get()
{
    var yourclass = new YourClass();

    return new IHttpActionResult<YourClass>(yourclass, HttpStatusCode.OK, Request, Configuration);
}
Run Code Online (Sandbox Code Playgroud)