【问题标题】:How do I configure the status code returned by my ASP.NET Web API service when the request has an unsupported Content-Type?当请求具有不受支持的 Content-Type 时,如何配置 ASP.NET Web API 服务返回的状态代码?
【发布时间】:2012-08-23 18:42:34
【问题描述】:

如果向我的 Web API 服务发出一个请求,该服务的 Content-Type 标头包含该服务不支持的类型,它会返回一个 500 Internal Server Error 状态代码以及类似于以下内容的消息:

{"Message":"An error has occurred.","ExceptionMessage":"No MediaTypeFormatter is available to read an object of type 'MyDto' from content with media type 'application/UnsupportedContentType'.","ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)
   at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)
   at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)
   at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
   at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(HttpParameterBinding parameterBinder)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken)"}

我更愿意按照建议返回415 Unsupported Media Type 状态代码,例如here

如何配置我的服务来执行此操作?

【问题讨论】:

    标签: asp.net-web-api content-negotiation


    【解决方案1】:

    这是我针对这个问题提出的解决方案。

    它广泛地基于here 所描述的用于在没有可接受的响应内容类型时发送 406 Not Acceptable 状态代码。

    public class UnsupportedMediaTypeConnegHandler : DelegatingHandler {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
                                                               CancellationToken cancellationToken) {
            var contentType = request.Content.Headers.ContentType;
            var formatters = request.GetConfiguration().Formatters;
            var hasFormetterForContentType = formatters //
                .Any(formatter => formatter.SupportedMediaTypes.Contains(contentType));
    
            if (!hasFormetterForContentType) {
                return Task<HttpResponseMessage>.Factory //
                    .StartNew(() => new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType));
            }
    
            return base.SendAsync(request, cancellationToken);
        }
    }
    

    在设置服务配置时:

    config.MessageHandlers.Add(new UnsupportedMediaTypeConnegHandler());
    

    请注意,这要求字符集也匹配。您可以通过仅检查标头的 MediaType 属性来放松此限制。

    【讨论】:

    • 我采用了这个解决方案,但遇到了一个小问题。对于 GET 请求,代码仍会运行,并且找不到“null”内容类型(或我的应用程序中的“text/plain”)的格式化程序。因此,要修复,我只需检查它是否是 GET 请求,如果是,则跳过格式化程序检查...
    【解决方案2】:

    没有会自动更改状态代码的配置标志。您可以创建一个 MessageHandler,它可能会检查“正在发送的响应”并将状态代码修改为 415。

    【讨论】:

      【解决方案3】:

      返回状态码的标准方法是从您的操作中返回一个 HttpResponseMessage。您可以将内容包装在 HttpResponseMessage 对象中,而不是原始内容,并像这样设置状态:

      public System.Net.Http.HttpResponseMessage Getresponse()
          {
              return new System.Net.Http.HttpResponseMessage() { Content = new System.Net.Http.StringContent(done.ToString()), StatusCode = System.Net.HttpStatusCode.Conflict };
          }
      

      【讨论】:

        猜你喜欢
        • 2012-08-20
        • 2012-08-12
        • 2018-02-15
        • 1970-01-01
        • 2020-01-27
        • 1970-01-01
        • 1970-01-01
        • 2020-09-25
        • 2016-11-04
        相关资源
        最近更新 更多