it-swarm.com.ru

Создание новых методов результата действия IHttpActionResult

Можно ли использовать новый интерфейс IHttpActionResult для возврата ответного сообщения HttpStatusCode.NoContent?

В настоящее время я использую return new HttpResponseMessage( HttpStatusCode.NoContent ); И хотел бы преобразовать это в return NoContent();.

У IHttpActionResult уже есть Ok(), Conflict() и NotFound(), но я не могу найти ничего для Forbidden() и NoContent(), которое мне нужно использовать в моем проекте.

Насколько легко добавить другие типы результатов?

30
Intrepid

Я нашел этот пример сайта , который показывает, как добавить собственный метод IHttpActionResult, и я использовал его для создания методов Forbidden() и NoContent() с большим успехом.

public abstract class CommonApiController : ApiController
{
    public class ForbiddenResult : IHttpActionResult
    {
        private readonly HttpRequestMessage _request;
        private readonly string _reason;

        public ForbiddenResult(HttpRequestMessage request,string reason)
        {
            _request = request;
            _reason = reason;
        }

        public ForbiddenResult(HttpRequestMessage request)
        {
            _request = request;
            _reason = "Forbidden";
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = _request.CreateResponse(HttpStatusCode.Forbidden,_reason);
            return Task.FromResult(response);
        }
    }

    public class NoContentResult : IHttpActionResult
    {
        private readonly HttpRequestMessage _request;
        private readonly string _reason;

        public NoContentResult(HttpRequestMessage request,string reason)
        {
            _request = request;
            _reason = reason;
        }

        public NoContentResult(HttpRequestMessage request)
        {
            _request = request;
            _reason = "No Content";
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = _request.CreateResponse(HttpStatusCode.NoContent,_reason);
            return Task.FromResult(response);
        }
    }
}

И тогда я могу использовать это так:

public class InvoiceController : CommonApiController
{
    public async Task<IHttpActionResult> Post([FromBody]Invoice invoice)
    {
        if(User.IsInRole("Readonly"))
        {
            return Forbidden();
        }

        // Rest of code

    }
}
23
Intrepid

Нет удобного метода для результата no-content, потому что по умолчанию, когда действие возвращает void, ответ будет иметь статус HTTP 204.

Если вы хотите явно указать, что в действии, вы также можете вернуть StatusCode(HttpStatusCode.NoContent) из вашего действия или 

ResponseMessage(new HttpResponseMessage(HttpStatusCode.NoContent)).

Удобный метод Unauthorized () дает вам статус 401, поэтому для Forbidden (403) вам также придется использовать StatusCode(HttpStatusCode.Forbidden) или

ResponseMessage(new HttpResponseMessage(HttpStatusCode.Forbidden))
43
Rafael Companhoni

Я попробовал реализацию @Intrepid и столкнулся с некоторыми проблемами. Я вижу два решения здесь:

Решение 1: Часть: return Forbidden(); не должна работать.

Компилятор не распознает это.

Вместо этого должно быть: return new ForbiddenResult(Request, "my reason");

ОБНОВЛЕНИЕ 1

Решение 2:

Я думаю, что именно это @Interpid намеревался в своей реализации, но он упустил несколько вещей.

Для использования return Forbidden(); необходимо обновить CommonApiController функциями, которые возвращают пользовательские IHttpActionResult для Forbidden и NoContent

Класс должен выглядеть так:

public abstract class CommonApiController: ApiController {

    protected ForbiddenResult Forbidden() {
     return new ForbiddenResult(this.Request);
    }

    protected ForbiddenResult Forbidden(string reason) {
     return new ForbiddenResult(this.Request, reason);
    }

    protected NoContentResult NoContent() {
     return new NoContentResult(this.Request);
    }

    public class ForbiddenResult: IHttpActionResult {
     private readonly HttpRequestMessage _request;
     private readonly string _reason;

     public ForbiddenResult(HttpRequestMessage request, string reason) {
      _request = request;
      _reason = reason;
     }

     public ForbiddenResult(HttpRequestMessage request) {
      _request = request;
      _reason = "Forbidden";
     }

     public Task < HttpResponseMessage > ExecuteAsync(CancellationToken cancellationToken) {
      var response = _request.CreateResponse(HttpStatusCode.Forbidden, _reason);
      return Task.FromResult(response);
     }
    }

    public class NoContentResult: IHttpActionResult {
     private readonly HttpRequestMessage _request;
     private readonly string _reason;

     public NoContentResult(HttpRequestMessage request, string reason) {
      _request = request;
      _reason = reason;
     }

     public NoContentResult(HttpRequestMessage request) {
      _request = request;
      _reason = "No Content";
     }

     public Task < HttpResponseMessage > ExecuteAsync(CancellationToken cancellationToken) {
      var response = _request.CreateResponse(HttpStatusCode.NoContent, _reason);
      return Task.FromResult(response);
     }
    }
   }

Во всяком случае, если я ошибаюсь, и ответ @ Interpid является правильным. Что мне здесь не хватает, чтобы заставить его реализацию работать?

8
Asaf Epelbaum

Если вы хотите включить в ответ фразу причины без добавления подкласса в ApiController, создайте объект ResponseMessage и верните его из действия методом ResponseMessage (). Попробуй это:

public class InvoiceController : ApiController
{
    public async Task<IHttpActionResult> Post([FromBody]Invoice invoice)
    {
        if(User.IsInRole("Readonly"))
        {
            var response = new HttpResponseMessage(HttpStatusCode.Forbidden);

            response.ReasonPhrase = "User has the Readonly role";
            return ResponseMessage(response);
        }

        // Rest of code

    }
}
3
kmac.mcfarlane

Теперь вы можете использовать следующее (.Net Standard):

return StatusCode(HttpStatusCode.NoContent);

или (.Net Core 2.1+)

return NoContent();
0
Scott Wendt