Как сделать так, чтобы ASP.NET Core возвращал метод void / Task action 204 Нет содержимого - PullRequest
0 голосов
/ 14 мая 2018

Как настроить тип ответа метода действия void / Task на 204 No Content вместо 200 OK?

Например, рассмотрим простой контроллер:

public class MyController : Controller
{
    [HttpPost("foo")]
    public async Task Foo() {
        await Task.CompletedTask;
    }

    [HttpPost("bar")]
    public async Task<IActionResult> Bar() {
        await Task.CompletedTask;
        return NoContent();
    }
}

Я бы хотел, чтобы оба метода возвращали 204 No Content, но по умолчанию (и, следовательно, то, что возвращает /foo), похоже, 200 OK.Я пробовал разные вещи, такие как добавление атрибута [ProducesResponseType(204)] к /foo, но я не нашел ничего, что могло бы оказать какое-либо влияние.

Ответы [ 3 ]

0 голосов
/ 14 мая 2018

Работоспособное решение, предоставленное Nish26.Но если вы не хотите засорять контроллер избыточным кодом, другой вариант - создать ResultFilter:

public class ResponseCodeAttribute : Attribute, IResultFilter
{
    private readonly int _statusCode;
    public ResponseCode(int statusCode)
    {
        this._statusCode = statusCode;
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
    }
    public void OnResultExecuted(ResultExecutedContext context)
    {
        context.HttpContext.Response.StatusCode = _statusCode;
    }
}

, а затем использовать его с методом действия:

[ResponseCode(204)]
[HttpPost("foo")]
public async Task Foo() {
    await Task.CompletedTask;
}

Кстати, ProducesResponseType - это просто атрибут, который помогает создавать метаданные API.

0 голосов
/ 14 мая 2018

Прежде всего, я не думаю, что это хорошая идея. Действия контроллера должны быть тестируемыми без создания всего конвейера. Вы можете проверить Bar(), чтобы убедиться, что он возвращает 204, просто проверив возвращаемый результат. Вы не можете сделать это с действием, которое изменяет возвращаемый результат через фильтры.

Тем не менее, можно изменить результат, используя Фильтры результатов , атрибуты, которые реализуют интерфейсы IResultFilter, IAsyncResultFilter. Также имеется абстрактный класс ResultFilterAttribute , который реализует оба интерфейса, предоставляет реализацию для IAsyncResultFilter, которая вызывает методы IResultFilter.

Вы можете создать атрибут, который изменяет код состояния следующим образом:

public class ResponseCodeAttribute : ResultFilterAttribute
{
    //Public property to enable reflection, inspection
    public int StatusCode {get;}

    public ResponseCodeAttribute(int statusCode)=>StatusCode=statusCode;

    public override void OnResultExecuted(ResultExecutedContext context)
    {
        context.HttpContext.Response.StatusCode = StatusCode;
    }
}

И используйте его с:

[HttpPost,ResponseCode(204)]
public async Task Foo() {
    await Task.CompletedTask;
}

Этого недостаточно, хотя .

Вызывающие этот метод не могут знать, что он вернет 204 вместо ожидаемого 200. Вот где появляется атрибут только для метаданных ProducesResponseTypeAttribute . Этот атрибут реализует IApiResponseMetadataProvider, который используется для предоставления метаданных API Explorer и инструментам прокси / документации, таким как Swagger. По крайней мере, вы должны использовать оба атрибута, например:

[HttpPost,ResponseCode(204),ProducesResponseType(204)]
public async Task Foo() {
    await Task.CompletedTask;
}

Еще лучше объединить ResponseCodeAttribute с IApiResponseMetadataProvider:

public class ResponseCodeAttribute : ResultFilterAttribute,IApiResponseMetadataProvider
{
    public int StatusCode {get;}

    public Type Type { get; }=typeof(void);

    public ResponseCodeAttribute(int statusCode)=>StatusCode=statusCode;

    public override void OnResultExecuted(ResultExecutedContext context)
    {
        context.HttpContext.Response.StatusCode = StatusCode;
    }

    void IApiResponseMetadataProvider.SetContentTypes(MediaTypeCollection contentTypes)
    {            
    }
}

И примените его с начальным:

[HttpPost,ResponseCode(204)]
public async Task Foo() {
    await Task.CompletedTask;
}
0 голосов
/ 14 мая 2018

Базовый класс контроллера имеет свойство Response типа HttpResponse . Вы можете напрямую установить:

 Response.StatusCode = 204 ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...