如何提供返回IHttpActionResult的额外方法?

时间:2017-05-31 16:05:17

标签: asp.net inheritance asp.net-web-api asp.net-web-api2

我有一个ApiController,它返回OkNegotiatedContentResult<T>一个资源集合,分页。当然,会有更多方法返回分页集合。

所有这些操作的结果中的content看起来大致如下:

  • 包含当前项目的Data媒体资源
  • 具有分页元数据的PagingMeta属性,例如总页数和总项目数
  • 包含指向first / prev / next / last pages
  • 的链接的PagingLinks属性

我的后端返回一个自定义PagedList<T>对象,我有另一个包含上述属性的PagedListResponse<T>。这是从一个到另一个的简单转换。

现在,在Web API中,ApiController提供了几种方便的方法来返回IHttpActionResult,例如:

  • Ok<T>(T value)
  • Content<T>(HttpStatusCode statusCode, T value)

我希望控制器能够轻松地返回分页结果。

目前我有一个提供它的扩展方法,具有以下签名:

public static OkNegotiatedContentResult<PagedListResult<T>> OkPaged<T>(this ApiController controller, /* other parameters */)

“丑陋”是指您只能通过添加this关键字来调用扩展方法:

return this.OkPaged(myResult);

我能看到的唯一其他选项是实现一个基本控制器类,但我通常会尝试避免这种继承结构,因为它们往往会在以后遇到麻烦。

ASP.NET在扩展点方面提供了什么来做我想做的事情?

1 个答案:

答案 0 :(得分:0)

您始终可以创建一个继承自IHttpActionResult的类,并将其用作返回值,例如

public class HttpStatusCodeResultWithContent<T> : IHttpActionResult
{
    private readonly HttpRequestMessage httpRequestMessage;

    private readonly HttpStatusCode statusCode;

    public HttpStatusCodeResultWithContent(HttpRequestMessage httpRequestMessage, HttpStatusCode statusCode, T model)
    {
        this.httpRequestMessage = httpRequestMessage;
        this.statusCode = statusCode;
        ResponseModel = model;
    }

    public T ResponseModel { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = httpRequestMessage.CreateResponse(statusCode, ResponseModel);
        return Task.FromResult(response);
    }
}

这为您提供了一个HttpStatusCodeResultWithContent中易于测试的类,它允许您使用任何HTTP状态代码返回任何内容。

然后从您的控制器代码

var pagedListResult = someObject.GetPagedList();
return new HttpStatusCodeResultWithContent<PagedListResult<T>(Request, HttpStatusCode.OK, pagedListResult);

然后你可以使用扩展方法,如果你喜欢在ApiController上包含对它的访问 - 这几乎就是ApiController内部的所有内容,例如:这是ApiController上的'Ok'方法。

protected internal virtual OkNegotiatedContentResult<T> Ok<T>(T content)
{
    return new OkNegotiatedContentResult<T>(content, this);
}