使用IHttpActionResult时如何设置自定义标题?

ehd*_*hdv 41 c# asp.net asp.net-web-api

在ASP.NET Web API 2中,它IHttpActionResult在简化控制器代码方面提供了很多价值,我不愿意停止使用它,但我遇到了问题.

我需要在传出响应上设置一个ETag,我找不到任何可以访问响应头的属性.目前我正在使用Ok<T>(T content)来自的helper方法ApiController,它返回一个OkNegotiatedContentResult<T>对象.这似乎没有暴露任何可以让我修改标题的东西.

我错过了什么,或者在使用股票IHttpActionResult类型时是否真的没有办法做到这一点?我考虑过一个消息处理程序,但后来我必须弄清楚如何将ETag从动作中传出(对于不同的动作,ETag的生成方式不同,所以这不是为所有动作制作通用处理程序的问题).

我想避免使用原始的HttpResponseMessage,但此刻看起来很难.

Kir*_*lla 34

对于您的方案,您需要创建自定义IHttpActionResult.以下是我OkNegotiatedContentResult<T>在运行时派生Content-Negotiation并设置Ok状态代码的示例.

public class CustomOkResult<T> : OkNegotiatedContentResult<T>
{
    public CustomOkResult(T content, ApiController controller)
        : base(content, controller) { }

    public CustomOkResult(T content, IContentNegotiator contentNegotiator, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters) 
        : base(content, contentNegotiator, request, formatters) { }

    public string ETagValue { get; set; }

    public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = await base.ExecuteAsync(cancellationToken);

        response.Headers.ETag = new EntityTagHeaderValue(this.ETagValue);

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

控制器:

public class ValuesController : ApiController
{
    public IHttpActionResult Get()
    {
        return new CustomOkResult<string>(content: "Hello World!", controller: this)
            {
                    ETagValue = "You ETag value"
            };
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您也可以从中派生NegotiatedContentResult<T>,在这种情况下,您需要自己提供StatusCode.希望这可以帮助.

你可以找到的源代码OkNegotiatedContentResult<T>NegotiatedContentResult<T>,正如你可以想像是简单的实际.

  • 正确的答案是使用此处找到的“ResponseMessageResult”:http://stackoverflow.com/a/41459475/1644019 (2认同)

小智 29

您可以HttpResponseMessage根据需要创建,添加标头,然后ResponseMessageResult从中创建:

HttpResponseMessage response =new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.Add("MyHeader", "MyHeaderValue");
return ResponseMessage(response);
Run Code Online (Sandbox Code Playgroud)

  • 海报明确要求使用IHttpActionResult解决方案 (11认同)
  • @ AdrianHope-Bailie这是一个X/Y问题,*任何人*试图做海报所要求的做错了.此解决方案是框架编写者希望您做的预期解决方案,用于对响应进行细粒度控制. (8认同)

Dav*_*son 9

这是我没有ActionFilterAttributes的简单实现,类似于AlexACD的响应.我的解决方案使用ResponseMessageResult来实现IHttpActionResult接口.

HttpResponseMessage responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
responseMessage.Headers.Add("Headername", "Value");
ResponseMessageResult response = new ResponseMessageResult(responseMessage);
return response;
Run Code Online (Sandbox Code Playgroud)

  • `ResponseMessage`返回`ResponseMessageResult` (2认同)

And*_*toy 5

public static class HttpExtentions
{
    public static IHttpActionResult AddHeader(this IHttpActionResult action,
        string headerName, IEnumerable<string> headerValues)
    {
        return new HeaderActionResult(action, headerName, headerValues);
    }

    public static IHttpActionResult AddHeader(this IHttpActionResult action,
        string headerName, string header)
    {
        return AddHeader(action, headerName, new[] {header});
    }

    private class HeaderActionResult : IHttpActionResult
    {
        private readonly IHttpActionResult action;

        private readonly Tuple<string, IEnumerable<string>> header;

        public HeaderActionResult(IHttpActionResult action, string headerName,
            IEnumerable<string> headerValues)
        {
            this.action = action;

            header = Tuple.Create(headerName, headerValues);
        }

        public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = await action.ExecuteAsync(cancellationToken);

            response.Headers.Add(header.Item1, header.Item2);

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


bat*_*aci 5

很老的问题。当时其他答案可能是有意义的,但今天您可以简单地添加这一行,而无需更改或扩展IHttpActionResult。它完美地在您的响应中添加标头。还要确保格式化为RFC 1123标准,如下所示。否则,虽然 Last-Modified 出现在标头中,但客户端无法使用HttpClient.

    System.Web.HttpContext.Current.Response.Headers.
Add(Microsoft.Net.Http.Headers.HeaderNames.LastModified, DBdateModified.Value.ToString("r"));
Run Code Online (Sandbox Code Playgroud)