写入HttpResponse

时间:2018-10-31 14:20:33

标签: c# asp.net-mvc .net-core

我有一个看起来像这样的控制器

IHttpWrite httpWrite;

[HttpPost]
public async Task<HttpResponse> Post(Request req)
{
    return await httpWrite.Write(req, Response);
}
称为

public async Task<HttpResponse> Write(object data, HttpResponse httpResponse)
{
    var json = JsonConvert.SerializeObject(data);

    httpResponse.OnStarting(() =>
    {
        httpResponse.Clear();
        httpResponse.ContentType = "application/json";
        return Task.CompletedTask;
    });

    await httpResponse.WriteAsync(json);
    return httpResponse;
}

但是调用它会得到这个异常

System.InvalidOperationException: Headers are read-only, response has already started.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ThrowHeadersReadOnlyException()

我知道一旦将数据写入响应中就无法设置标头,但最终我要在HttpResponse中设置标头,然后再向其中写入任何内容。

从我完成的调试中,仅在控制器返回HttpResponse之后才引发标头的异常。这向我表明,尝试在我的代码之外的某些内容上更改标头。

我正在使用Visual Studio设置的大多数样板代码。这是默认程序

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
               .UseStartup<Startup>();

哪个调用的是默认情况下的启动

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseMvc();
}

我认为解决方案要么在于更改配置中的某些内容,以使我在返回HttpResponse之后不自动设置响应标头,要么有可能返回其他对象,从而不必手动设置标头。在写HttpResponse之后无法得知试图设置标头的原因,我不确定如何继续。

1 个答案:

答案 0 :(得分:0)

为什么不只在写响应之前写标题?甚至更好:为什么不手动设置响应,为什么不将返回声明为更抽象的东西,然后让框架处理呢?

无论如何,这是一段有关如何添加自定义标头的代码:

using System;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication.Controllers
{
    [Route("api")]
    public class ValuesController : Controller
    {
        [HttpGet]
        [Route("values/{top}")]
        public IActionResult Get(int top)
        {
            // Generate dummy values
            var list = Enumerable.Range(0, DateTime.Now.Second)
                             .Select(i => $"Value {i}")
                             .ToList();
            list.Reverse();

            var result = new ObjectResult(list.Take(top))
            {
                StatusCode = (int)HttpStatusCode.OK
            };

            Request.HttpContext.Response.Headers.Add("X-Total-Count", list.Count.ToString());

            return result;
        }
    }
}