【问题标题】:How do I remove the charset from Content-Type in a ASP.NET Core MVC response?如何在 ASP.NET Core MVC 响应中从 Content-Type 中删除字符集?
【发布时间】:2017-06-22 20:09:55
【问题描述】:

无论我尝试什么,我似乎都无法从回复的 Content-Type 标头中删除 ; charset=utf-8 部分。

[HttpGet("~/appid")]
// Doesn't work
//[Produces("application/fido.trusted-apps+json")]
public string GetAppId()
{
    // Doesn't work
    Response.ContentType = "application/fido.trusted-apps+json";

    // Doesn't work
    //Response.ContentType = null;
    //Response.Headers.Add("Content-Type", "application/fido.trusted-apps+json");

    return JsonConvert.SerializeObject(new
    {
        foo = true
    });
}

当我只想要application/fido.trusted-apps+json 时,我总是得到application/fido.trusted-apps+json; charset=utf-8

注意:这是为了符合 U2F 的 FIDO AppID and Facet Specification v1.0 声明:

响应必须将 MIME Con​​tent-Type 设置为“application/fido.trusted-apps+json”。

【问题讨论】:

  • 我认为[Produces]属性的内容必须是MediaTypeCollection的成员。也许将application/fido.trusted-aps+json 添加到集合中会使其工作。见docs.microsoft.com/en-us/aspnet/core/api/…
  • 从哪里添加到MediaTypeCollection?在某处启动?
  • 这看起来不太有用,因为我认为您不能修改它,除非使用自定义格式化程序。请看下面我的回答。我记得在某处读过,如果您无法修改来自控制器的响应流,而是如果您想修改它,您必须自己处理整个响应,也许使用中间件(?)。自定义格式化程序似乎是您最好的选择。
  • 我最终采用了一种更简单的方法,即使用中间件。请看下面我的回答。谢谢。

标签: asp.net asp.net-mvc


【解决方案1】:

我采用了以下方法,在退出时使用中间件替换标题。必须使用这样的中间件似乎有点 hacky:

中间件

public class AdjustHeadersMiddleware
{
    private readonly RequestDelegate _next;

    public AdjustHeadersMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext, CurrentContext currentContext)
    {
        httpContext.Response.OnStarting((state) =>
        {
            if(httpContext.Response.Headers.Count > 0 && httpContext.Response.Headers.ContainsKey("Content-Type"))
            {
                var contentType = httpContext.Response.Headers["Content-Type"].ToString();
                if(contentType.StartsWith("application/fido.trusted-apps+json"))
                {
                    httpContext.Response.Headers.Remove("Content-Type");
                    httpContext.Response.Headers.Append("Content-Type", "application/fido.trusted-apps+json");
                }
            }

            return Task.FromResult(0);
        }, null);


        await _next.Invoke(httpContext);
    }
}

Startup.cs 配置()

app.UseMiddleware<AdjustHeadersMiddleware>();

【讨论】:

    【解决方案2】:

    我发现您可以使用 ContentResult 在您的控制器中覆盖它。因此,您可以通过执行以下操作来实现您想要的目标

    string bodyJson = JsonConvert.SerializeObject(new
    {
        foo = true
    })
    
    var response = new ContentResult()
    {
        Content = bodyJson,
        ContentType = "application/fido.trusted-apps+json",
        StatusCode = (int)System.Net.HttpStatusCode.OK,
    };
    
    return response;
    

    【讨论】:

      【解决方案3】:

      如果请求您的 MVC 端点的系统发送正确的 Accept: application/fido.trusted-apps+json,那么我相信 custom formatter 就是您正在寻找的。

      见:

      看起来像这样(从第二个链接借来的):

      public class FidoTrustedAppOutputFormatter : IOutputFormatter 
      {
      
          public FidoTrustedAppOutputFormatter 
          {
              SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/fido.trusted-apps+json"));
          }
      
          public bool CanWriteResult(OutputFormatterCanWriteContext context) 
          { 
              if (context == null) throw new ArgumentNullException(nameof(context)); 
              if (context.ContentType == null || context.ContentType.ToString() == "application/fido.trusted-apps+json") 
                  return true;
      
              return false; 
          } 
      
          public async Task WriteAsync(OutputFormatterWriteContext context) 
          { 
              if (context == null) throw new ArgumentNullException(nameof(context)); 
              var response = context.HttpContext.Response; response.ContentType = "application/fido.trusted-apps+json"; 
      
              using (var writer = context.WriterFactory(response.Body, Encoding.UTF8)) 
              { 
                  // replace with Json.net implementation
                  Jil.JSON.Serialize(context.Object, writer); 
                  await writer.FlushAsync(); 
              }
          }
      
      }
      
      public class FidoTrustedAppInputFormatter : IInputFormatter 
      {
      
          public FidoTrustedAppInputFormatter 
          {
              SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/fido.trusted-apps+json"));
          }
      
          public bool CanRead(OutputFormatterCanWriteContext context) 
          { 
              if (context == null) throw new ArgumentNullException(nameof(context)); 
              if (context.ContentType == null || context.ContentType.ToString() == "application/fido.trusted-apps+json") 
                  return true;
      
              return false; 
          } 
      
          public Task<InputFormatterResult> ReadAsync(InputFormatterContext context) 
          { 
              if (context == null) throw new ArgumentNullException(nameof(context)); 
      
              var request = context.HttpContext.Request; if (request.ContentLength == 0) 
              { 
                  if (context.ModelType.GetTypeInfo().IsValueType) 
                      return InputFormatterResult.SuccessAsync(Activator.CreateInstance(context.ModelType)); 
                  else return InputFormatterResult.SuccessAsync(null); 
              } 
      
              var encoding = Encoding.UTF8;//do we need to get this from the request im not sure yet 
      
              using (var reader = new StreamReader(context.HttpContext.Request.Body)) 
              { 
                  var model = Jil.JSON.Deserialize(reader, context.ModelType); 
                  return InputFormatterResult.SuccessAsync(model); 
              } 
          } 
      
      }
      

      然后在你的启动中注册它:

      services.AddMvcCore(options =>  
      { 
          options.InputFormatters.Insert(0, new FidoTrustedAppInputFormatter ());
          options.OutputFormatters.Insert(0, new FidoTrustedAppOutputFormatter ()); 
      });
      

      【讨论】:

        猜你喜欢
        • 2019-02-18
        • 2011-12-19
        • 2018-06-06
        • 2017-10-08
        • 2021-07-29
        • 2023-03-11
        • 2018-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多