Trả lại nội dung với IHttpActionResult cho phản hồi không OK


184

Để trả về từ bộ điều khiển API Web 2, tôi có thể trả về nội dung với phản hồi nếu phản hồi là OK (trạng thái 200) như thế này:

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

Nếu có thể, tôi muốn sử dụng các loại kết quả tích hợp tại đây khi có thể: https://msdn.microsoft.com/en-us/l Library / system.web.http.results (v = vs.118) .aspx

Câu hỏi của tôi là, đối với một loại phản hồi khác (không phải 200), làm thế nào tôi có thể trả lại một tin nhắn (chuỗi) với nó? Ví dụ: tôi có thể làm điều này:

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

nhưng không phải cái này:

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

Lý tưởng nhất là tôi muốn điều này được khái quát hóa để tôi có thể gửi lại tin nhắn với bất kỳ triển khai nào của IHttpActionResult.

Tôi có cần phải làm điều này không (và xây dựng thông điệp phản hồi của riêng tôi):

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

đây có phải là cách tốt hơn không?


làm thế nào về điều này: stackoverflow.com/questions/10732644/ Cách
Milen 18/2/2015

bạn không thể sử dụng ApiController.InternalServerError msdn.microsoft.com/en-us/l Library / dn292630 (v = vs.118) .aspx
Ric

@Milen, Cảm ơn bạn. Một cái gì đó như thế có thể làm việc. Phần tôi không thích là nó yêu cầu tạo một triển khai IHttpActionResult khác nhau cho mỗi triển khai hiện có mà tôi muốn có thể sử dụng.
mayabelle

@Ric, không, tham số là Ngoại lệ. Tôi muốn đặt một tin nhắn dưới dạng một chuỗi. Ngoài ra, điều này không giải quyết một trường hợp tổng quát hơn trong đó mã có thể không nhất thiết là lỗi máy chủ nội bộ.
mayabelle

3
@mayabelle: Bạn có thấy câu trả lời của Shamil Yakupov không? Nó đơn giản và ngắn gọn hơn nhiều là câu trả lời được chấp nhận.
Isaac

Câu trả lời:


419

Bạn có thể sử dụng điều này:

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

1
Giải pháp ngắn gọn và đơn giản. Có nhiều mã hơn có nghĩa là nhiều lỗi hơn và tốn thời gian bảo trì.
Thomas.Benz

6
Khi tôi thử điều này, giá trị được trả về của code(trong đó mã là một chuỗi) return Content(HttpStatusCode.OK, code)được gói gọn trong "điều không mong muốn, có lý do nào cho điều này không? Ví dụ: giá trị được trả về là "\"value\""tôi đang sử dụng mvc5
Deza

2
Nếu bạn cần thực hiện việc này từ bên ngoài lớp ApiControll thì bạn có thể sử dụng: trả về thương lượng mới đàm phán <T> (mã, T (...), bộ điều khiển mới)
Etherman

tôi có thể trả lại từ thư viện lớp không? Tôi cần gì để tham khảo?
Bộ công cụ

54

Bạn có thể sử dụng HttpRequestMessagesExtensions.CreateErrorResponse ( System.Net.Httpkhông gian tên), như vậy:

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

Tốt nhất là tạo phản hồi dựa trên yêu cầu để tận dụng lợi thế đàm phán nội dung của API Web.


6
Request.CreateErrorResponse trả về một httpResponseMessage, không phải IHttpActionResult. Những gì bạn mô tả là cách thực hành tốt để tạo một httpResponseMessage nhưng không giải quyết được câu hỏi của tôi. Dẫu sao cũng xin cảm ơn!
mayabelle

@mayabelle bạn có thể tạo bê tông IHttpActionResult và bọc các mã như thế này:
Quốc Nguyễn

1
Điều này làm việc cho tôi nhưng tôi đã sử dụng Request.CreateResponse để lỗi hiển thị dưới dạng chuỗi thay vì dưới Khóa tin nhắn.
Nhà hóa học

Tôi đang gặp lỗi, đoạn mã bị lỗi. Nó nói 'yêu cầu' là null. Tôi đang cố gắng sử dụng Request.CreateResponse @ user1620220
Sheena Agrawal

@SheenaAgrawal Mã này chỉ có thể được thực thi trong ngữ cảnh của yêu cầu HTTP. Nếu ApiController.Requestlà null, điều đó có nghĩa là bạn không ở đúng ngữ cảnh hoặc có gì đó bị hỏng trong kiến ​​trúc WebAPI của bạn.
dùng1620220

35

Tôi đã kết thúc với giải pháp sau đây:

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

... có thể được sử dụng như thế này:

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

Tôi đang mở để đề xuất cải tiến. :)


1
Câu trả lời của Shamil Yakupov là câu trả lời hay nhất nhưng chỉ từ bên trong lớp ApiControll - nó cần phải được viết lại dưới dạng một cái gì đó như "trả lại Thỏa thuận mới có nội dung <T> (mã, T mới ()), bộ điều khiển)" được sử dụng từ bên ngoài lớp điều khiển. Trong trường hợp đó, một giải pháp như giải pháp này ở trên có thể dễ đọc hơn.
Etherman

16

Bạn cũng có thể làm:

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

1
Có nhưng thật khó để lấy lại tin nhắn đó
userSteve

7

Bất cứ ai quan tâm đến việc trả lại bất cứ điều gì với bất kỳ mã trạng thái nào khi trả về Phản hồi:

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

7

Trong ASP.NET Web API 2, bạn có thể gói bất kỳ ResponseMessagetrong FeedbackMessageResult :

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

Trong một số trường hợp, đây có thể là cách đơn giản nhất để có được kết quả mong muốn, mặc dù nhìn chung có thể sử dụng các kết quả khác nhau trong System.Web.Http.Results .


6

Đơn giản:

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

Hãy nhớ tham khảo System.Net.HttpSystem.Net .


2

Tôi khuyên bạn nên đọc bài viết này. Có rất nhiều cách để sử dụng HttpResponse hiện tại như được đề xuất, nhưng nếu bạn muốn tận dụng Web Api 2, thì hãy xem xét sử dụng một số tùy chọn IHttpActionResult tích hợp như

return Ok() 

hoặc là

return NotFound()

Chọn loại trả về đúng cho Bộ điều khiển Api Web


2

Một ví dụ chi tiết hơn với sự hỗ trợ của mã HTTP không được xác định trong C # HttpStatusCode.

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

Contentlà một phương thức ảo được định nghĩa trong lớp trừu tượng ApiController, cơ sở của bộ điều khiển. Xem tờ khai như dưới đây:

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

1

@mayabelle bạn có thể tạo bê tông IHttpActionResult và bọc các mã như thế này:

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

Tôi đã từng gặp vấn đề tương tự. Tôi muốn tạo kết quả tùy chỉnh cho bộ điều khiển api của mình, để gọi chúng như return Ok("some text");

Sau đó, tôi đã làm điều này: 1) Tạo loại kết quả tùy chỉnh với 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) Tạo bộ điều khiển tùy chỉnh với phương thức mới:

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

Và sau đó tôi có thể gọi chúng trong bộ điều khiển của mình, như thế này:

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

0

câu trả lời này dựa trên câu trả lời của Shamil Yakupov, với vật thật thay vì chuỗi.

using System.Dynamic;

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

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

1
Nội dung <T> rất hữu ích
LastTribunal 17/07/18

0

Đối với trường hợp ngoại lệ, tôi thường làm

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

0

Trên đây là những điều thực sự hữu ích.

Trong khi tạo dịch vụ web, Nếu bạn có trường hợp dịch vụ, người tiêu dùng sẽ đánh giá rất cao. Tôi đã cố gắng duy trì tính đồng nhất của đầu ra. Ngoài ra, bạn có thể đưa ra nhận xét hoặc thông báo lỗi thực tế. Người tiêu dùng dịch vụ web chỉ có thể kiểm tra IsSuccess đúng hay không, chắc chắn sẽ có vấn đề và hoạt động theo tình huống.

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

Bạn được chào đón để đưa ra gợi ý nếu có :)


-1

Xin lỗi vì câu trả lời muộn tại sao bạn không sử dụng đơn giản

return BadRequest("your message");

Tôi sử dụng nó cho tất cả các IHttpActionResultlỗi của tôi nó hoạt động tốt

đây là tài liệu: https://msdn.microsoft.com/en-us/l Library / system.web.http.apicontler.badrequest (v = vs.118) .aspx


7
Bởi vì không phải tất cả các lỗi là kết quả của các yêu cầu xấu, vì vậy một 400phản hồi sẽ không phù hợp. OP đặc biệt đã đưa ra một 500phản ứng như một ví dụ.
dùng1620220

Có, chỉ có thể với BadRequest, các loại khác không tranh luận về tin nhắn
benraay
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.