Kembalikan konten dengan IHttpActionResult untuk respons yang tidak OK


185

Untuk kembali dari pengontrol Web API 2, saya dapat mengembalikan konten dengan respons jika responsnya OK (status 200) seperti ini:

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

Jika memungkinkan, saya ingin menggunakan tipe hasil bawaan di sini jika memungkinkan: https://msdn.microsoft.com/en-us/library/system.web.http.results(v=vs.118).aspx

Pertanyaan saya adalah, untuk jenis respons lain (bukan 200), bagaimana saya bisa mengembalikan pesan (string) dengannya? Sebagai contoh, saya bisa melakukan ini:

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

tapi bukan ini:

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

Idealnya saya ingin ini digeneralisasi sehingga saya dapat mengirim pesan kembali dengan salah satu implementasi dari IHttpActionResult.

Apakah saya perlu melakukan ini (dan membuat pesan respons sendiri):

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

atau adakah cara yang lebih baik?



tidak bisakah kamu tidak menggunakan ApiController.InternalServerError msdn.microsoft.com/en-us/library/dn292630(v=vs.118).aspx
Ric

@ Milen, Terima kasih. Sesuatu seperti itu mungkin berhasil. Bagian yang saya tidak suka adalah itu membutuhkan membuat implementasi IHttpActionResult berbeda untuk setiap implementasi yang ada saya ingin dapat menggunakan.
mayabelle

@Ric, tidak, parameternya adalah Pengecualian. Saya ingin mengatur pesan sebagai string. Juga, ini tidak membahas kasus yang lebih umum di mana kode mungkin tidak selalu merupakan kesalahan server internal.
mayabelle

3
@ Mayabelle: Apakah Anda melihat jawaban Shamil Yakupov? Jauh lebih simpel dan ringkas jawaban yang diterima.
Isaac

Jawaban:


420

Anda bisa menggunakan ini:

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

1
Solusi singkat dan sederhana. Memiliki lebih banyak kode berarti lebih banyak bug dan perawatan yang memakan waktu.
Thomas.Benz

6
Ketika saya mencoba ini, nilai yang dikembalikan dari code(di mana kode adalah string) di return Content(HttpStatusCode.OK, code)enkapsulasi dalam "yang tidak terduga, apakah ada alasan untuk ini? Misalnya nilai yang dikembalikan adalah "\"value\""saya menggunakan mvc5
Deza

2
Jika Anda perlu melakukan ini dari luar kelas ApiController maka Anda dapat menggunakan: mengembalikan NegotiatedContentResult <T> (kode, T baru (...), pengontrol)
Etherman

dapatkah saya mengembalikannya dari perpustakaan kelas? Apa yang perlu saya rujuk?
Toolkit

54

Anda dapat menggunakan HttpRequestMessagesExtensions.CreateErrorResponse ( System.Net.Httpnamespace), seperti:

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

Lebih disukai membuat tanggapan berdasarkan permintaan untuk memanfaatkan negosiasi konten API Web.


6
Request.CreateErrorResponse mengembalikan HttpResponseMessage, bukan IHttpActionResult. Apa yang Anda gambarkan adalah praktik yang baik untuk membuat HttpResponseMessage tetapi tidak menjawab pertanyaan saya. Bagaimanapun, terima kasih!
mayabelle

@abelabelle Anda dapat membuat beton IHttpActionResult dan membungkus kode-kode seperti ini:
Quoc Nguyen

1
Ini bekerja untuk saya tetapi saya menggunakan Request.CreateResponse sehingga kesalahan ditampilkan sebagai string alih-alih di bawah tombol Pesan.
Kimiawan

Saya mendapatkan kesalahan, cuplikan gagal. Dikatakan 'permintaan' adalah nol. Saya mencoba menggunakan Request.CreateResponse @ user1620220
Sheena Agrawal

@SheenaAgrawal Kode ini hanya dapat dieksekusi dalam konteks permintaan HTTP. Jika ApiController.Requestnol, berarti Anda tidak berada dalam konteks yang benar, atau ada sesuatu yang rusak dalam arsitektur WebAPI Anda.
user1620220

35

Saya akhirnya pergi dengan solusi berikut:

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

... yang bisa digunakan seperti ini:

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

Saya terbuka untuk saran untuk perbaikan. :)


1
Jawaban Shamil Yakupov adalah jawaban terbaik tetapi hanya dari dalam kelas ApiController - perlu ditulis ulang sebagai sesuatu seperti "kembalikan Negosiasi baruKontensiResult <T> (kode, T baru (...), pengontrol)" untuk digunakan dari luar kelas pengontrol. Dalam hal ini solusi seperti ini di atas mungkin lebih mudah dibaca.
Etherman

16

Anda juga dapat melakukan:

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

1
Ya tapi itu
susah

7

Siapa pun yang tertarik mengembalikan apa pun dengan kode status apa pun dengan mengembalikan ResponseMessage:

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

7

Di ASP.NET Web API 2, Anda bisa membungkusnya ResponseMessagedengan ResponseMessageResult :

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

Dalam beberapa kasus ini mungkin cara paling sederhana untuk mendapatkan hasil yang diinginkan, meskipun umumnya lebih baik menggunakan berbagai hasil di System.Web.Http.Hasil .


6

Sederhana:

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

Ingatlah untuk merujuk System.Net.Http dan System.Net .



2

Contoh yang lebih rinci dengan dukungan kode HTTP yang tidak didefinisikan dalam C # HttpStatusCode.

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

Contentadalah metode virtual yang didefinisikan dalam kelas abstrak ApiController, basis controller. Lihat deklarasi seperti di bawah ini:

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

1

@abelabelle Anda dapat membuat beton IHttpActionResult dan membungkus kode-kode seperti ini:

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

Saya memiliki masalah yang sama. Saya ingin membuat hasil khusus untuk pengontrol api saya, untuk memanggil mereka suka return Ok("some text");

Lalu saya melakukan ini: 1) Buat jenis hasil khusus dengan 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) Buat pengontrol khusus dengan metode baru:

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

Dan kemudian saya dapat memanggil mereka di pengontrol saya, seperti ini:

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

0

jawaban ini didasarkan pada jawaban Shamil Yakupov, dengan objek nyata bukan string.

using System.Dynamic;

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

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

1
Konten <T> sangat berguna
LastTribunal

0

Sebagai pengecualian, saya biasanya melakukannya

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

0

Hal-hal di atas sangat membantu.

Saat membuat layanan web, Jika Anda mengambil kasus layanan konsumen akan sangat dihargai. Saya berusaha menjaga keseragaman output. Anda juga dapat memberikan komentar atau pesan kesalahan aktual. Konsumen layanan web hanya dapat memeriksa apakah IsSuccess benar atau tidak, yang lain akan yakin ada masalah, dan bertindak sesuai situasi.

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

Anda dipersilakan untuk memberikan saran jika ada :)


-1

Maaf untuk jawaban yang terlambat kenapa tidak Anda gunakan sederhana

return BadRequest("your message");

Saya menggunakannya untuk semua milik saya IHttpActionResult kesalahan ini berfungsi dengan baik

di sini adalah dokumentasi: https://msdn.microsoft.com/en-us/library/system.web.http.apicontroller.badrequest(v=vs.118).aspx


7
Karena tidak semua kesalahan adalah hasil dari permintaan yang buruk, jadi 400jawaban tidak pantas. OP secara khusus memberi 500tanggapan sebagai contoh.
user1620220

Ya itu hanya mungkin dengan BadRequest, tipe-tipe lain tidak menerima argumen pesan
benraay
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.