Tamam olmayan yanıt için içeriği IHttpActionResult ile döndür


185

Bir Web API 2 denetleyicisinden dönmek için, yanıt TAMAM ise (durum 200) şu şekilde yanıtla içerik döndürebilirim:

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

Mümkünse, mümkün olduğunda burada yerleşik sonuç türlerini kullanmak istiyorum: https://msdn.microsoft.com/en-us/library/system.web.http.results(v=vs.118).aspx

Benim sorum, başka bir yanıt türü için (200 değil), onunla nasıl bir mesaj (dize) döndürebilirim? Örneğin, bunu yapabilirim:

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

ama bu değil:

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

İdeal olarak IHttpActionResult uygulamalarından herhangi biriyle bir mesaj gönderebilmem için genelleştirilmesini istiyorum.

Bunu yapmam gerekiyor mu (ve kendi yanıt iletimi oluşturmam gerekiyor):

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

yoksa daha iyi bir yol var mı?



Eğer kullanamadı ApiController.InternalServerError msdn.microsoft.com/en-us/library/dn292630(v=vs.118).aspx
Ric

@Milen, teşekkür ederim. Böyle bir şey işe yarayabilir. Sevmediğim bölüm, kullanmak istediğim her mevcut uygulama için farklı bir IHttpActionResult uygulaması oluşturmayı gerektiriyor.
mayabelle

@Ric, no, parametre bir istisnadır. İletiyi dize olarak ayarlamak istiyorum. Ayrıca, kodun dahili sunucu hatası olması gerekmeyeceği daha genel bir durumu da ele almaz.
mayabelle

3
@mayabelle: Shamil Yakupov'un cevabını gördün mü? Kabul edilen cevabın çok daha basit ve özlü olması.
Isaac

Yanıtlar:


421

Bunu kullanabilirsiniz:

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

1
Kısa ve basit bir çözüm. Daha fazla koda sahip olmak daha fazla hata ve zaman alıcı bakım anlamına gelir.
Thomas.Benz

6
Bunu denerken, içinde döndürülen değeri code(burada kod bir dizedir) içinde return Content(HttpStatusCode.OK, code)"beklenmedik bir durum var, bunun herhangi bir nedeni var mı? Örneğin döndürülen değer "\"value\""mvc5 kullanıyorum
Deza

2
Bunu ApiController sınıfının dışından yapmanız gerekiyorsa şunu kullanabilirsiniz: return new NegotiatedContentResult <T> (kod, yeni T (...), kontrolör)
Etherman

bir sınıf kütüphanesinden iade edebilir miyim? Neye başvurmam gerekir?
Alet

54

HttpRequestMessagesExtensions.CreateErrorResponse ( System.Net.Httpad alanı) aşağıdaki gibi kullanabilirsiniz :

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

Web API'nın içerik pazarlığından yararlanma talebine dayalı yanıtlar oluşturmak tercih edilir.


6
Request.CreateErrorResponse, IHttpActionResult öğesini değil, bir HttpResponseMessage döndürür. Açıkladığınız bir HttpResponseMessage oluşturmak için iyi bir uygulamadır, ancak sorumu ele almıyor. Yine de teşekkürler!
mayabelle

@mayabelle IHttpActionResult beton oluşturabilir ve şu kodu bu şekilde sarabilirsiniz:
Quoc Nguyen

1
Bu benim için çalıştı ama hata Message key yerine bir dize olarak görünmesi için Request.CreateResponse kullandım.
Kimyager

Bir hata alıyorum, snippet başarısız oluyor. 'İstek' boş. Request.CreateResponse @ user1620220 kullanmaya çalışıyorum
Sheena Agrawal

@SheenaAgrawal Bu kod yalnızca bir HTTP isteği bağlamında yürütülebilir. Eğer ApiController.Requestis boş o doğru bağlamda olmadığın anlamına geliyor, ya da bir şey sizin WebAPI mimarisinde bozuldu.
user1620220

35

Sonunda şu çözümle devam ettim:

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

... şu şekilde kullanılabilir:

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

İyileştirme önerilerine açığım. :)


1
Shamil Yakupov'un cevabı en iyi cevaptır, ancak sadece ApiController sınıfının içinden - dışarıdan kullanılmak üzere "yeni NegotiatedContentResult <T> (kod, yeni T (...), kontrolör) döndür" gibi bir şeyle yeniden yazılması gerekir. denetleyici sınıfı. Bu durumda, yukarıdaki gibi bir çözelti daha okunabilir olabilir.
Etherman

16

Ayrıca şunları da yapabilirsiniz:

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

1
Evet ama bu mesaj metnini geri almak acı
verici

7

ResponseMessage döndürerek herhangi bir durum kodu ile herhangi bir şey döndürmekle ilgilenen herkes:

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

7

ASP.NET Web API 2'de, ResponseMessagebir ResponseMessageResult içinde herhangi birini kapatabilirsiniz :

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

Bazı durumlarda, istenen sonucu almanın en basit yolu olabilir, ancak genellikle System.Web.Http.Results içinde çeşitli sonuçların kullanılması tercih edilebilir .


6

Basit:

return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Your message"));

System.Net.Http ve System.Net'e başvurmayı unutmayın .



2

C # 'da tanımlanmamış HTTP kod desteği ile daha ayrıntılı bir örnek HttpStatusCode.

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

ContentApiControllerdenetleyicinin temeli olan soyut sınıfta tanımlanan sanal bir yöntemdir . Beyannameye aşağıdaki gibi bakın:

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

1

@mayabelle IHttpActionResult betonu oluşturabilir ve bu kodu aşağıdaki gibi sarabilirsiniz:

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

0

Ben de aynı problemi yaşadım. API denetleyicilerim için özel sonuç oluşturmak istiyorum. return Ok("some text");

Sonra bunu yaptım: 1) Tek tonlu özel sonuç türü oluşturun

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) Yeni yöntemle özel denetleyici oluşturun:

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

Ve sonra onları kontrolörlerimde çağırabilirim, şöyle:

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

0

bu cevap Shamil Yakupov cevabına dayanır, string yerine gerçek nesne ile.

using System.Dynamic;

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

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

1
İçerik <T> çok yararlı
LastTribunal

0

İstisnalar için genellikle

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

0

Yukarıdaki şeyler gerçekten yararlıdır.

Web hizmetleri oluştururken, tüketici hizmetleri büyük takdir alacak olursanız. Çıktının homojenliğini korumaya çalıştım. Ayrıca açıklama veya gerçek hata mesajı verebilirsiniz. Web hizmeti tüketicisi sadece IsSuccess'i doğru kontrol edebilir ya da başka bir sorun olduğundan emin olamaz ve duruma göre hareket eder.

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

Varsa öneri verebilirsiniz :)


-1

Geç cevap için özür dilerim neden basit kullanmıyorsun

return BadRequest("your message");

Tüm IHttpActionResulthatalarım için iyi çalışıyorum

İşte belgeler: https://msdn.microsoft.com/en-us/library/system.web.http.apicontroller.badrequest(v=vs.118).aspx


7
Tüm hatalar kötü isteklerin sonucu olmadığından, bir 400yanıt uygun olmaz. OP özellikle 500örnek olarak bir yanıt verdi .
user1620220

Evet, ancak BadRequest ile diğer türler bir mesaj argümanı
almazlar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.