web-dev-qa-db-fra.com

Renvoyer du contenu avec IHttpActionResult pour une réponse non-OK

Pour revenir d'un contrôleur Web API 2, je peux renvoyer le contenu avec la réponse si la réponse est OK (statut 200) comme ceci:

    public IHttpActionResult Get()
    {
        string myResult = ...
        return Ok(myResult);
    }

Si possible, je souhaite utiliser les types de résultats intégrés ici lorsque cela est possible: https://msdn.Microsoft.com/en-us/library/system.web.http.results(v=vs.118). aspx

Ma question est, pour un autre type de réponse (pas 200), comment puis-je retourner un message (chaîne) avec elle? Par exemple, je peux faire ceci:

    public IHttpActionResult Get()
    {
       return InternalServerError();
    }

mais pas ceci:

    public IHttpActionResult Get()
    {
       return InternalServerError("Message describing the error here");
    }

Idéalement, je souhaite généraliser cette opération pour pouvoir renvoyer un message avec l'une des implémentations de IHttpActionResult.

Dois-je faire cela (et créer mon propre message de réponse):

    public IHttpActionResult Get()
    {
       HttpResponseMessage responseMessage = ...
       return ResponseMessage(responseMessage);
    }

ou y a-t-il un meilleur moyen?

147
mayabelle

J'ai fini par aller avec la solution suivante:

public class HttpActionResult : IHttpActionResult
{
    private readonly string _message;
    private readonly HttpStatusCode _statusCode;

    public HttpActionResult(HttpStatusCode statusCode, string message)
    {
        _statusCode = statusCode;
        _message = message;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = new HttpResponseMessage(_statusCode)
        {
            Content = new StringContent(_message)
        };
        return Task.FromResult(response);
    }
}

... qui peut être utilisé comme ceci:

public IHttpActionResult Get()
{
   return new HttpActionResult(HttpStatusCode.InternalServerError, "error message"); // can use any HTTP status code
}

Je suis ouvert aux suggestions d'amélioration. :)

29
mayabelle

Vous pouvez utiliser ceci:

return Content(HttpStatusCode.BadRequest, "Any object");
369
Shamil Yakupov

Vous pouvez utiliser HttpRequestMessagesExtensions.CreateErrorResponse (espace de nom System.Net.Http), comme suit:

public IHttpActionResult Get()
{
   return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Message describing the error here"));
}

Il est préférable de créer des réponses en fonction de la demande pour tirer parti de la négociation de contenu de l'API Web.

49
user1620220

Vous pouvez aussi faire:

return InternalServerError(new Exception("SOME CUSTOM MESSAGE"));
15
ilans

Toute personne souhaitant renvoyer quoi que ce soit avec un code de statut avec ResponseMessage renvoyé:

//CreateResponse(HttpStatusCode, T value)
return ResponseMessage(Request.CreateResponse(HttpStatusCode.XX, object));
7
CularBytes

Dans l’API Web ASP.NET 2, vous pouvez envelopper toute ResponseMessage dans un ResponseMessageResult :

public IHttpActionResult Get()
{
   HttpResponseMessage responseMessage = ...
   return new ResponseMessageResult(responseMessage);
}

Dans certains cas, il peut s’agir du moyen le plus simple d’obtenir le résultat souhaité, bien qu’il soit généralement préférable d’utiliser les différents résultats dans System.Web.Http.Results .

6
sfuqua

Je recommanderais de lire ce post. Il existe de nombreuses façons d'utiliser la réponse HttpResponse existante, comme suggéré, mais si vous souhaitez tirer parti de Web Api 2, utilisez certaines des options intégrées d'IHttpActionResult telles que 

return Ok() 

ou 

return NotFound()

Choisissez le type de retour approprié pour les contrôleurs Web Api

1
wegunterjr

@mayabelle vous pouvez créer IHttpActionResult concret et enveloppé ces codes comme ceci:

public class NotFoundPlainTextActionResult : IHttpActionResult
{
    public NotFoundPlainTextActionResult(HttpRequestMessage request, string message)
    {
        Request = request;
        Message = message;
    }

    public string Message { get; private set; }
    public HttpRequestMessage Request { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(ExecuteResult());
    }

    public HttpResponseMessage ExecuteResult()
    {
        var response = new HttpResponseMessage();

        if (!string.IsNullOrWhiteSpace(Message))
            //response.Content = new StringContent(Message);
            response = Request.CreateErrorResponse(HttpStatusCode.NotFound, new Exception(Message));

        response.RequestMessage = Request;
        return response;
    }
}
1
Quoc Nguyen

Pour les exceptions, je fais habituellement

 catch (Exception ex)
        {
            return InternalServerError(new ApplicationException("Something went wrong in this request. internal exception: " + ex.Message));
        }
0
ahsant

cette réponse est basée sur la réponse de Shamil Yakupov, avec un objet réel au lieu d'une chaîne.

using System.Dynamic;

dynamic response = new ExpandoObject();
response.message = "Email address already exist";

return Content<object>(HttpStatusCode.BadRequest, response);
0
Kugan Kumar

J'ai eu le même problème. Je veux créer un résultat personnalisé pour mes contrôleurs d'api, pour les appeler comme return Ok("some text");

Ensuite, j'ai fait ceci: 1) Créer un type de résultat personnalisé avec singletone

public sealed class EmptyResult : IHttpActionResult
{
    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.NoContent) { Content = new StringContent("Empty result") });
    }
}

2) Créer un contrôleur personnalisé avec une nouvelle méthode:

public class CustomApiController : ApiController
{
    public IHttpActionResult EmptyResult()
    {
        return new EmptyResult();
    }
}

Et puis je peux les appeler dans mes contrôleurs, comme ceci:

public IHttpActionResult SomeMethod()
    {
       return EmptyResult();
    }
0
Merchezatter

Un exemple plus détaillé prenant en charge le code HTTP non défini dans C # HttpStatusCode.

public class MyController : ApiController
{
    public IHttpActionResult Get()
    {
        HttpStatusCode codeNotDefined = (HttpStatusCode)429;
        return Content(codeNotDefined, "message to be sent in response body");
    }
}

Content est une méthode virtuelle définie dans la classe abstraite ApiController, la base du contrôleur. Voir la déclaration ci-dessous:

protected internal virtual NegotiatedContentResult<T> Content<T>(HttpStatusCode statusCode, T value);
0
themefield

Les choses ci-dessus sont vraiment utiles.

Lors de la création de services Web, si vous prenez des cas de services, le consommateur sera grandement apprécié. J'ai essayé de maintenir l'uniformité de la sortie. Vous pouvez aussi donner une remarque ou un message d'erreur. Le consommateur de services Web ne peut que vérifier que IsSuccess est vrai ou non, sinon il sera sûr qu'il y a un problème et agit comme il convient 

  public class Response
    {
        /// <summary>
        /// Gets or sets a value indicating whether this instance is success.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is success; otherwise, <c>false</c>.
        /// </value>
        public bool IsSuccess { get; set; } = false;

        /// <summary>
        /// Actual response if succeed 
        /// </summary>
        /// <value>
        /// Actual response if succeed 
        /// </value>
        public object Data { get; set; } = null;

        /// <summary>
        /// Remark if anythig to convey
        /// </summary>
        /// <value>
        /// Remark if anythig to convey
        /// </value>
        public string Remark { get; set; } = string.Empty;
        /// <summary>
        /// Gets or sets the error message.
        /// </summary>
        /// <value>
        /// The error message.
        /// </value>
        public object ErrorMessage { get; set; } = null;


    }  




[HttpGet]
        public IHttpActionResult Employees()
        {
            Response _res = new Response();
            try
            { 
                DalTest objDal = new DalTest(); 
                _res.Data = objDal.GetTestData();
                _res.IsSuccess = true;
                return Ok<Response>(_res);
            }
            catch (Exception ex)
            {
                _res.IsSuccess = false;
                _res.ErrorMessage = ex;
                return ResponseMessage(Request.CreateResponse(HttpStatusCode.InternalServerError, _res )); 
            } 
        }

Vous êtes le bienvenu pour donner des suggestions s'il y en a :)

0
Amol Khandagale