Прежде всего, я не думаю, что это хорошая идея. Действия контроллера должны быть тестируемыми без создания всего конвейера. Вы можете проверить 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;
}