web-dev-qa-db-fra.com

Création de nouvelles méthodes de résultat d'action IHttpActionResult

Est-il possible d'utiliser la nouvelle interface IHttpActionResult pour renvoyer un message de réponse HttpStatusCode.NoContent?

J'utilise actuellement return new HttpResponseMessage( HttpStatusCode.NoContent ); Et voudrais convertir ceci en return NoContent();.

IHttpActionResult a déjà Ok(), Conflict() et NotFound(), mais je ne trouve aucun élément pour Forbidden() et NoContent() que je dois utiliser dans mon projet.

Est-il facile d'ajouter d'autres types de résultats?

30
Intrepid

J'ai trouvé ce exemple de site qui montre comment ajouter une méthode IHttpActionResult personnalisée et que j'ai utilisée pour créer les méthodes Forbidden() et NoContent() avec un grand succès.

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);
        }
    }
}

Et puis je peux l'utiliser comme ça:

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

        // Rest of code

    }
}
23
Intrepid

Il n'y a pas de méthode pratique pour le résultat no-content car, par défaut, lorsqu'une action renvoie void, la réponse aura le statut HTTP 204.

Si vous souhaitez l'indiquer explicitement sur l'action, vous pouvez également renvoyer un StatusCode(HttpStatusCode.NoContent) de votre action ou un 

ResponseMessage(new HttpResponseMessage(HttpStatusCode.NoContent)).

La méthode pratique Unauthorized () vous attribue le statut 401. Par conséquent, pour Forbidden (403), vous devez également utiliser StatusCode(HttpStatusCode.Forbidden) ou

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

J'ai essayé l'implémentation @Intrepid et j'ai rencontré quelques problèmes. Je vois deux solutions ici:

Solution 1: La partie: return Forbidden(); ne devrait pas fonctionner.

Le compilateur ne le reconnaîtrait pas.

Au lieu de cela, il devrait être: return new ForbiddenResult(Request, "my reason");

MISE À JOUR 1

Solution 2:

Je pense que c’est ce que @Interpid avait prévu dans son implémentation, mais il lui manquait quelques petites choses.

Pour utiliser return Forbidden();, la CommonApiController doit être mise à jour avec les fonctions qui renvoient la personnalisation IHttpActionResult pour Forbidden et NoContent

La classe devrait ressembler à ceci:

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);
     }
    }
   }

Quoi qu'il en soit, si je me trompe et que la réponse de @ Interpid est correcte. Qu'est-ce qui me manque ici pour que sa mise en œuvre fonctionne?

8
Asaf Epelbaum

Si vous souhaitez inclure une phrase de motif dans votre réponse sans ajouter de sous-classe à ApiController, créez un objet ResponseMessage et renvoyez-le à partir de l'action à l'aide de la méthode ResponseMessage (). Essaye ça:

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

Vous pouvez maintenant utiliser les éléments suivants (.Net Standard):

return StatusCode(HttpStatusCode.NoContent);

ou (.Net Core 2.1+)

return NoContent();
0
Scott Wendt