.Net Core MVC - не может получить 406 - Недопустимо, всегда возвращает 200 OK с Json - PullRequest
0 голосов
/ 11 июня 2018

Я хочу, чтобы мое приложение уважало браузер, принял заголовок и возвратил 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, установленным на что угодно, например, «text / xml»)

Я всегда получаю 200 OK - с «application / json» Request with specified accept header and the response in json format

Мой CountryController выглядит следующим образом:

/// <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 запроса всегда игнорируется и ответ всегда 200 OK с правильнымДанные Json?Чего мне не хватает?Я думал, что установка RespectBrowserAcceptHeader и ReturnHttpNotAcceptable сделает это ... но, видимо, нет.Почему всегда используется стандартный формататор Json?

1 Ответ

0 голосов
/ 11 января 2019

Чтобы ReturnHttpNotAcceptable работал, тип, возвращаемый действием, должен быть либо ObjectResult (например, Ok(retval)), либо типом, который не реализует IActionResult (в этом случае среда MVC обернет его вObjectResult для вас).

Это связано с тем, что инфраструктура MVC проверяет только значение ReturnHttpNotAcceptable в ObjectResultExecutor, а не в других реализациях IActionResultExecutor (например, ViewResultExecutor).(См. Исходный код ObjectResultExecutor и ViewResultExecutor )

Проще говоря, убедитесь, что возвращаемый вами тип не реализует (или не наследует от чего-либо, что реализует)IActionResult.

...