c# - .Net Core MVC - 无法获得 406 - Not Acceptable ,始终使用 Json 返回 200 OK

标签 c# json model-view-controller asp.net-core http-status-code-406

如果与响应格式不匹配,我希望我的应用程序尊重浏览器接受 header 并返回 406。

我在 Mvc 配置中设置了这个选项:

    /// <summary>
    /// This method gets called by the runtime. Use this method to add services to the container.
    /// </summary>
    /// <param name="services">The collection of the services.</param>
    /// <returns>The provider of the service.</returns>
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // add mvc services
        services.AddMvc(options =>
                {
                    options.RespectBrowserAcceptHeader = true;
                    options.ReturnHttpNotAcceptable = true;

                    options.CacheProfiles.Add(
                        "CodebookCacheProfile",
                        new CacheProfile()
                        {
                            Duration = (int)TimeSpan.FromDays(1).TotalSeconds
                        });
                })
                .AddControllersAsServices()
                .AddJsonOptions(options =>
                {
                    options.SerializerSettings.Converters.Add(new StringEmptyToNullConverter());
                    options.SerializerSettings.Converters.Add(new StringEnumConverter(true));
                });

        // add response compression services
        services.AddResponseCompression(options =>
        {
            options.EnableForHttps = true;
            options.Providers.Add<GzipCompressionProvider>();
        });

        // add application services
        services.AddSwaggerDoc()
                .AddConfiguration(configuration)
                .AddModel()
                .AddDataAccess(configuration)
                .AddAuthentication(configuration)
                .AddDomainServices()
                .AddSchedulerContainer(() => serviceProvider);

        // initialize container
        serviceProvider = services.CreateServiceProvider();

        return serviceProvider;
    }

当我尝试发送这样的请求时:(无论在什么情况下都设置了 Accept header ,例如“text/xml”)

我总是得到 200 OK - 使用“application/json” Request with specified accept header and the response in json format

我的 CountriesController 看起来像这样:

/// <summary>
/// REST API controller for actions with countries.
/// </summary>    
[AllowAnonymous]
[Area(Area.Common)]
[Route("[area]/Codebooks/[controller]")]
[ResponseCache(CacheProfileName = "CodebookCacheProfile")]
public class CountriesController : ApiController
{
    private readonly ICountryService countryService;

    /// <summary>
    /// Initializes a new instance of the <see cref="CountriesController" /> class.
    /// </summary>
    /// <param name="countryService">The country service.</param>
    public CountriesController(ICountryService countryService)
    {
        this.countryService = countryService ?? throw new ArgumentNullException(nameof(countryService));
    }

    /// <summary>
    /// Gets countries by search settings.
    /// </summary>
    /// <response code="200">The countries was returned correctly.</response>
    /// <response code="401">The unauthorized access.</response>
    /// <response code="406">The not acceptable format.</response>
    /// <response code="500">The unexpected error.</response>
    /// <param name="countrySearchSettings">The search settings of the country.</param>
    /// <returns>Data page of countries.</returns>        
    [HttpGet]
    [ProducesResponseType(typeof(IDataPage<Country>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(typeof(void), StatusCodes.Status406NotAcceptable)]
    [ProducesResponseType(typeof(ApiErrorSummary), StatusCodes.Status500InternalServerError)]
    [SwaggerOperation("SearchCountries")]
    public IDataPage<Country> Get([FromQuery(Name = "")] CountrySearchSettings countrySearchSettings)
    {
        return countryService.Search(countrySearchSettings);
    }

    /// <summary>
    /// Gets a country.
    /// </summary>
    /// <response code="200">The country was returned correctly.</response>
    /// <response code="400">The country code is not valid.</response>
    /// <response code="401">The unauthorized access.</response>
    /// <response code="406">The not acceptable format.</response>
    /// <response code="500">The unexpected error.</response>
    /// <param name="countryCode">The code of the country.</param>
    /// <returns>Action result.</returns>   
    [HttpGet("{countryCode}")]
    [ProducesResponseType(typeof(Country), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiValidationErrorSummary), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(typeof(void), StatusCodes.Status406NotAcceptable)]
    [ProducesResponseType(typeof(ApiErrorSummary), StatusCodes.Status500InternalServerError)]
    [SwaggerOperation("GetCountry")]
    public IActionResult Get(string countryCode)
    {
        var country = countryService.GetByCode(countryCode);
        return Ok(country);
    }
}

您是否知道为什么请求 Accept header 总是被忽略并且响应总是 200 OK 且具有正确的 Json 数据? 我错过了什么?我认为 RespectBrowserAcceptHeaderReturnHttpNotAcceptable 的设置可以做到这一点……但显然不是。 为什么它总是退回到默认的 Json 格式化程序?

最佳答案

要使 ReturnHttpNotAcceptable 起作用,操作返回的类型必须是 ObjectResult(例如 Ok(retval))或类型没有实现 IActionResult(在这种情况下,MVC 框架将为您将其包装在 ObjectResult 中)。

这是因为 MVC 框架只检查 ObjectResultExecutor 中的 ReturnHttpNotAcceptable 的值,而不检查任何其他 IActionResultExecutor 实现(像 ViewResultExecutor)。 (参见 ObjectResultExecutorViewResultExecutor 的源代码)

简单地说,确保您返回的类型没有实现(或继承自任何实现的)IActionResult。

关于c# - .Net Core MVC - 无法获得 406 - Not Acceptable ,始终使用 Json 返回 200 OK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50793417/

相关文章:

c# - 反序列化动态 JSON

json - Gson 可选和必填字段

java - 如何用Gson反序列化这个json?

c# - 为 WPF 形状启用抗锯齿

c# - 列表不会用 protobuf 序列化

c# - 如何声明事件处理程序以传递 FxCop 规则,尤其是包含 sender 和 e 的规则?

javascript - 错误 : [ng:areq] Argument 'addCtrl' is not a function, 未定义

php - 关注点分离; MVC;为什么?

asp.net-mvc - ASP.NET MVC DropDownList 用户界面模板

c# - 在 Visual Studio 2017 中向 Xamarin.Forms 应用程序添加新内容页面时出错