Cách thực hành tốt nhất để trả về lỗi trong ASP.NET Web API


384

Tôi lo ngại về cách chúng tôi trả lại lỗi cho khách hàng.

Có phải chúng tôi trả lại lỗi ngay lập tức bằng cách ném httpResponseException khi chúng tôi gặp lỗi:

public void Post(Customer customer)
{
    if (string.IsNullOrEmpty(customer.Name))
    {
        throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest) 
    }
    if (customer.Accounts.Count == 0)
    {
         throw new HttpResponseException("Customer does not have any account", HttpStatusCode.BadRequest) 
    }
}

Hoặc chúng tôi tích lũy tất cả các lỗi sau đó gửi lại cho khách hàng:

public void Post(Customer customer)
{
    List<string> errors = new List<string>();
    if (string.IsNullOrEmpty(customer.Name))
    {
        errors.Add("Customer Name cannot be empty"); 
    }
    if (customer.Accounts.Count == 0)
    {
         errors.Add("Customer does not have any account"); 
    }
    var responseMessage = new HttpResponseMessage<List<string>>(errors, HttpStatusCode.BadRequest);
    throw new HttpResponseException(responseMessage);
}

Đây chỉ là một mã mẫu, không có vấn đề gì về lỗi xác thực hoặc lỗi máy chủ, tôi chỉ muốn biết cách thực hành tốt nhất, ưu và nhược điểm của từng phương pháp.


1
Xem stackoverflow.com/a/22163675/200442 bạn nên sử dụng ModelState.
Daniel Little

1
Lưu ý rằng câu trả lời ở đây chỉ bao gồm các Ngoại lệ được ném trong chính bộ điều khiển. Nếu API của bạn trả về <Model> IQueryable chưa được thực thi, ngoại lệ không nằm trong bộ điều khiển và không bị bắt ...
Jess

3
Câu hỏi rất hay nhưng không hiểu sao tôi không nhận được bất kỳ quá trình xây dựng nào của HttpResponseExceptionlớp, trong đó có hai tham số được đề cập trong bài đăng của bạn - HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest) tức làHttpResponseException(string, HttpStatusCode)
RBT

Câu trả lời:


293

Đối với tôi, tôi thường gửi lại HttpResponseExceptionvà đặt mã trạng thái phù hợp tùy thuộc vào ngoại lệ được ném và nếu ngoại lệ đó có gây tử vong hay không sẽ xác định xem tôi có gửi lại HttpResponseExceptionngay lập tức hay không.

Vào cuối ngày, API sẽ gửi lại phản hồi chứ không phải lượt xem, vì vậy tôi nghĩ sẽ tốt hơn nếu gửi lại tin nhắn có ngoại lệ và mã trạng thái cho người tiêu dùng. Hiện tại tôi không cần phải tích lũy lỗi và gửi lại vì hầu hết các trường hợp ngoại lệ thường là do tham số hoặc cuộc gọi không chính xác, v.v.

Một ví dụ trong ứng dụng của tôi là đôi khi khách hàng sẽ yêu cầu dữ liệu, nhưng không có bất kỳ dữ liệu nào có sẵn nên tôi ném một tùy chỉnh NoDataAvailableExceptionvà để nó bong bóng cho ứng dụng API Web, trong đó, trong bộ lọc tùy chỉnh của tôi, nó sẽ gửi lại thông điệp liên quan cùng với mã trạng thái chính xác.

Tôi không chắc chắn 100% về những gì thực hành tốt nhất cho việc này, nhưng hiện tại nó đang hoạt động với tôi vì vậy đó là những gì tôi đang làm.

Cập nhật :

Vì tôi đã trả lời câu hỏi này, một vài bài viết trên blog đã được viết về chủ đề này:

https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling

(tính năng này có một số tính năng mới trong các bản dựng hàng đêm) https://docs.microsoft.com/archive/bloss/youssefm/error-handling-in-asp-net-webapi

Cập nhật 2

Cập nhật quy trình xử lý lỗi của chúng tôi, chúng tôi có hai trường hợp:

  1. Đối với các lỗi chung như không tìm thấy hoặc các tham số không hợp lệ được truyền cho một hành động, chúng tôi trả lại một HttpResponseExceptionđể dừng xử lý ngay lập tức. Ngoài ra, đối với các lỗi mô hình trong các hành động của chúng tôi, chúng tôi sẽ trao từ điển trạng thái mô hình cho Request.CreateErrorResponsephần mở rộng và gói nó trong một HttpResponseException. Thêm từ điển trạng thái mô hình dẫn đến một danh sách các lỗi mô hình được gửi trong phần thân phản hồi.

  2. Đối với các lỗi xảy ra ở các lớp cao hơn, lỗi máy chủ, chúng tôi để bong bóng ngoại lệ cho ứng dụng API Web, ở đây chúng tôi có bộ lọc ngoại lệ toàn cầu xem xét ngoại lệ, ghi nhật ký bằng ELMAH và cố gắng hiểu ý nghĩa của nó khi đặt HTTP chính xác mã trạng thái và một thông báo lỗi thân thiện có liên quan như cơ thể một lần nữa trong a HttpResponseException. Đối với các trường hợp ngoại lệ mà chúng tôi không mong đợi máy khách sẽ nhận được lỗi 500 máy chủ nội bộ mặc định, nhưng một thông báo chung vì lý do bảo mật.

Cập nhật 3

Gần đây, sau khi chọn API Web 2, để gửi lại các lỗi chung, giờ đây chúng tôi sử dụng giao diện IHttpActionResult , cụ thể là các lớp được tích hợp trong System.Web.Http.Resultskhông gian tên như NotFound, BadRequest khi chúng phù hợp, ví dụ như chúng không mở rộng chúng một kết quả NotFound với thông báo phản hồi:

public class NotFoundWithMessageResult : IHttpActionResult
{
    private string message;

    public NotFoundWithMessageResult(string message)
    {
        this.message = message;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NotFound);
        response.Content = new StringContent(message);
        return Task.FromResult(response);
    }
}

Cảm ơn bạn đã trả lời geepie của bạn, đó là một kinh nghiệm tốt, vì vậy bạn muốn gửi expcetion ngay lập tức?
cuongle

Như tôi đã nói nó thực sự phụ thuộc vào ngoại lệ. Một ngoại lệ nghiêm trọng, chẳng hạn như người dùng chuyển Web Api một tham số không hợp lệ đến điểm cuối, sau đó tôi sẽ tạo một HTTPResponseException và trả lại ngay cho ứng dụng đang tiêu thụ.
gdp

Các ngoại lệ trong câu hỏi thực sự nhiều hơn về xác nhận, xem stackoverflow.com/a/22163675/200442 .
Daniel Little

1
@DanielLittle Đọc lại câu hỏi của anh ấy. Tôi trích dẫn: "Đây chỉ là một mã mẫu, không có vấn đề gì về lỗi xác thực hoặc lỗi máy chủ"
gdp

@gdp Mặc dù vậy, thực sự có hai thành phần, xác thực và ngoại lệ, vì vậy tốt nhất là bao gồm cả hai.
Daniel Little

184

ASP.NET Web API 2 thực sự đơn giản hóa nó. Ví dụ: đoạn mã sau:

public HttpResponseMessage GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var message = string.Format("Product with id = {0} not found", id);
        HttpError err = new HttpError(message);
        return Request.CreateResponse(HttpStatusCode.NotFound, err);
    }
    else
    {
        return Request.CreateResponse(HttpStatusCode.OK, item);
    }
}

trả về nội dung sau cho trình duyệt khi không tìm thấy mục:

HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Date: Thu, 09 Aug 2012 23:27:18 GMT
Content-Length: 51

{
  "Message": "Product with id = 12 not found"
}

Đề xuất: Không ném Lỗi HTTP 500 trừ khi có lỗi nghiêm trọng (ví dụ: Ngoại lệ lỗi WCF). Chọn một mã trạng thái HTTP thích hợp đại diện cho trạng thái dữ liệu của bạn. (Xem liên kết apigee bên dưới.)

Liên kết:


4
Tôi sẽ tiến thêm một bước và ném ResourceNotFoundException từ DAL / Repo mà tôi kiểm tra trong Web Api 2.2 ExceptionHandler cho Type ResourceNotFoundException và sau đó tôi trả lại "Không tìm thấy sản phẩm có id xxx". Bằng cách đó, nó thường neo trong kiến ​​trúc thay vì từng hành động.
Pascal

1
Có cách sử dụng cụ thể nào cho return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState); sự khác biệt giữa CreateResponseCreateErrorResponse
Zapnologica

10
Theo, w3.org/Prot Protocol / rfc2616 / rfc2616-sec10.html , lỗi máy khách là mã 400 cấp và lỗi máy chủ là mã cấp 500. Vì vậy, mã lỗi 500 có thể rất phù hợp trong nhiều trường hợp đối với API Web, không chỉ là lỗi "thảm khốc".
Jess

2
Bạn cần using System.Net.Http;cho CreateResponse()phương thức mở rộng để hiển thị.
Adam Szabo

Điều tôi không thích khi sử dụng Request.CreateResponse () là nó trả về thông tin tuần tự hóa không cần thiết của Microsoft như "<string xmlns =" schemas.microsoft.com/2003/10/Serialization/ " > Lỗi của tôi ở đây </ string > ". Đối với các tình huống khi 400 trạng thái phù hợp, tôi thấy rằng ApiControll.BadRequest (thông báo chuỗi) trả về chuỗi "<Error> <Message> Lỗi của tôi ở đây </ Message> </ Error>" tốt hơn. Nhưng tôi không thể tìm thấy tương đương của nó để trả lại 500 trạng thái với một tin nhắn đơn giản.
vkelman

76

Có vẻ như bạn gặp nhiều rắc rối với Xác thực hơn là lỗi / ngoại lệ nên tôi sẽ nói một chút về cả hai.

Thẩm định

Các hành động của bộ điều khiển thường lấy Mô hình đầu vào trong đó xác thực được khai báo trực tiếp trên mô hình.

public class Customer
{ 
    [Require]
    public string Name { get; set; }
}

Sau đó, bạn có thể sử dụng một ActionFiltertự động gửi tin nhắn xác nhận lại cho khách hàng.

public class ValidationActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var modelState = actionContext.ModelState;

        if (!modelState.IsValid) {
            actionContext.Response = actionContext.Request
                 .CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
        }
    }
} 

Để biết thêm thông tin về điều này, hãy xem http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc

Xử lý lỗi

Tốt nhất là trả lại tin nhắn cho khách hàng đại diện cho ngoại lệ đã xảy ra (với mã trạng thái có liên quan).

Ra khỏi hộp bạn phải sử dụng Request.CreateErrorResponse(HttpStatusCode, message)nếu bạn muốn chỉ định một tin nhắn. Tuy nhiên, điều này liên kết mã vớiRequest đối tượng, mà bạn không cần phải làm.

Tôi thường tạo loại ngoại lệ "an toàn" của riêng mình mà tôi mong khách hàng sẽ biết cách xử lý và bọc tất cả các lỗi khác với 500 lỗi chung.

Sử dụng bộ lọc hành động để xử lý các ngoại lệ sẽ như thế này:

public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        var exception = context.Exception as ApiException;
        if (exception != null) {
            context.Response = context.Request.CreateErrorResponse(exception.StatusCode, exception.Message);
        }
    }
}

Sau đó, bạn có thể đăng ký nó trên toàn cầu.

GlobalConfiguration.Configuration.Filters.Add(new ApiExceptionFilterAttribute());

Đây là loại ngoại lệ tùy chỉnh của tôi.

using System;
using System.Net;

namespace WebApi
{
    public class ApiException : Exception
    {
        private readonly HttpStatusCode statusCode;

        public ApiException (HttpStatusCode statusCode, string message, Exception ex)
            : base(message, ex)
        {
            this.statusCode = statusCode;
        }

        public ApiException (HttpStatusCode statusCode, string message)
            : base(message)
        {
            this.statusCode = statusCode;
        }

        public ApiException (HttpStatusCode statusCode)
        {
            this.statusCode = statusCode;
        }

        public HttpStatusCode StatusCode
        {
            get { return this.statusCode; }
        }
    }
}

Một ngoại lệ ví dụ mà API của tôi có thể ném.

public class NotAuthenticatedException : ApiException
{
    public NotAuthenticatedException()
        : base(HttpStatusCode.Forbidden)
    {
    }
}

Tôi có một vấn đề liên quan đến câu trả lời xử lý lỗi tại định nghĩa lớp ApiExceptionFilterAttribution. Trong phương thức OnException, ngoại lệ.StatusCode không hợp lệ vì ngoại lệ là một WebException. Tôi có thể làm gì trong trường hợp này?
razp26

1
@ razp26 nếu bạn đang đề cập đến như thế var exception = context.Exception as WebException;là một lỗi đánh máy, thì nó đáng lẽ phải thếApiException
Daniel Little

2
Bạn có thể vui lòng thêm một ví dụ về cách sử dụng lớp ApiExceptionFilterAttribution không?
razp26

36

Bạn có thể ném một httpResponseException

HttpResponseMessage response = 
    this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "your message");
throw new HttpResponseException(response);

23

Đối với API Web 2, các phương thức của tôi luôn trả về IHttpActionResult vì vậy tôi sử dụng ...

public IHttpActionResult Save(MyEntity entity)
{
  ....

    return ResponseMessage(
        Request.CreateResponse(
            HttpStatusCode.BadRequest, 
            validationErrors));
}

Câu trả lời này là ổn, trong khi bạn nên thêm tham chiếu vàoSystem.Net.Http
Bellash

19

Nếu bạn đang sử dụng ASP.NET Web API 2, cách dễ nhất là sử dụng Phương pháp ngắn ApiControll. Điều này sẽ dẫn đến một BadRequestResult.

return BadRequest("message");

Nghiêm khắc đối với các lỗi xác thực mô hình Tôi sử dụng quá tải BadRequest () chấp nhận đối tượng ModelState:return BadRequest(ModelState);
timmi4sa

4

bạn có thể sử dụng ActionFilter tùy chỉnh trong Web Api để xác thực mô hình

public class DRFValidationFilters : ActionFilterAttribute
{

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            actionContext.Response = actionContext.Request
                 .CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);

            //BadRequest(actionContext.ModelState);
        }
    }
    public override Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {

        return Task.Factory.StartNew(() => {

            if (!actionContext.ModelState.IsValid)
            {
                actionContext.Response = actionContext.Request
                     .CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);                    
            }
        });

    }

public class AspirantModel
{
    public int AspirantId { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }        
    public string LastName { get; set; }
    public string AspirantType { get; set; }       
    [RegularExpression(@"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Not a valid Phone number")]
    public string MobileNumber { get; set; }
    public int StateId { get; set; }
    public int CityId { get; set; }
    public int CenterId { get; set; }

}

    [HttpPost]
    [Route("AspirantCreate")]
    [DRFValidationFilters]
    public IHttpActionResult Create(AspirantModel aspirant)
    {
            if (aspirant != null)
            {

            }
            else
            {
                return Conflict();
            }
          return Ok();

}

Đăng ký lớp CustomAttribution trong webApiConfig.cs config.Filters.Add (new DRFValidationFilters ());


4

Xây dựng dựa trên Manish Jaincâu trả lời (có nghĩa là API Web 2 giúp đơn giản hóa mọi thứ):

1) Sử dụng các cấu trúc xác nhận để phản hồi càng nhiều lỗi xác nhận càng tốt. Các cấu trúc này cũng có thể được sử dụng để đáp ứng các yêu cầu đến từ các biểu mẫu.

public class FieldError
{
    public String FieldName { get; set; }
    public String FieldMessage { get; set; }
}

// a result will be able to inform API client about some general error/information and details information (related to invalid parameter values etc.)
public class ValidationResult<T>
{
    public bool IsError { get; set; }

    /// <summary>
    /// validation message. It is used as a success message if IsError is false, otherwise it is an error message
    /// </summary>
    public string Message { get; set; } = string.Empty;

    public List<FieldError> FieldErrors { get; set; } = new List<FieldError>();

    public T Payload { get; set; }

    public void AddFieldError(string fieldName, string fieldMessage)
    {
        if (string.IsNullOrWhiteSpace(fieldName))
            throw new ArgumentException("Empty field name");

        if (string.IsNullOrWhiteSpace(fieldMessage))
            throw new ArgumentException("Empty field message");

        // appending error to existing one, if field already contains a message
        var existingFieldError = FieldErrors.FirstOrDefault(e => e.FieldName.Equals(fieldName));
        if (existingFieldError == null)
            FieldErrors.Add(new FieldError {FieldName = fieldName, FieldMessage = fieldMessage});
        else
            existingFieldError.FieldMessage = $"{existingFieldError.FieldMessage}. {fieldMessage}";

        IsError = true;
    }

    public void AddEmptyFieldError(string fieldName, string contextInfo = null)
    {
        AddFieldError(fieldName, $"No value provided for field. Context info: {contextInfo}");
    }
}

public class ValidationResult : ValidationResult<object>
{

}

2) Lớp dịch vụ sẽ trả về ValidationResults, bất kể hoạt động có thành công hay không. Ví dụ:

    public ValidationResult DoSomeAction(RequestFilters filters)
    {
        var ret = new ValidationResult();

        if (filters.SomeProp1 == null) ret.AddEmptyFieldError(nameof(filters.SomeProp1));
        if (filters.SomeOtherProp2 == null) ret.AddFieldError(nameof(filters.SomeOtherProp2 ), $"Failed to parse {filters.SomeOtherProp2} into integer list");

        if (filters.MinProp == null) ret.AddEmptyFieldError(nameof(filters.MinProp));
        if (filters.MaxProp == null) ret.AddEmptyFieldError(nameof(filters.MaxProp));


        // validation affecting multiple input parameters
        if (filters.MinProp > filters.MaxProp)
        {
            ret.AddFieldError(nameof(filters.MinProp, "Min prop cannot be greater than max prop"));
            ret.AddFieldError(nameof(filters.MaxProp, "Check"));
        }

        // also specify a global error message, if we have at least one error
        if (ret.IsError)
        {
            ret.Message = "Failed to perform DoSomeAction";
            return ret;
        }

        ret.Message = "Successfully performed DoSomeAction";
        return ret;
    }

3) Trình điều khiển API sẽ xây dựng phản hồi dựa trên kết quả chức năng dịch vụ

Một tùy chọn là đặt hầu như tất cả các tham số là tùy chọn và thực hiện xác nhận tùy chỉnh để trả về phản hồi có ý nghĩa hơn. Ngoài ra, tôi chú ý không cho phép bất kỳ ngoại lệ nào vượt ra ngoài ranh giới dịch vụ.

    [Route("DoSomeAction")]
    [HttpPost]
    public HttpResponseMessage DoSomeAction(int? someProp1 = null, string someOtherProp2 = null, int? minProp = null, int? maxProp = null)
    {
        try
        {
            var filters = new RequestFilters 
            {
                SomeProp1 = someProp1 ,
                SomeOtherProp2 = someOtherProp2.TrySplitIntegerList() ,
                MinProp = minProp, 
                MaxProp = maxProp
            };

            var result = theService.DoSomeAction(filters);
            return !result.IsError ? Request.CreateResponse(HttpStatusCode.OK, result) : Request.CreateResponse(HttpStatusCode.BadRequest, result);
        }
        catch (Exception exc)
        {
            Logger.Log(LogLevel.Error, exc, "Failed to DoSomeAction");
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, new HttpError("Failed to DoSomeAction - internal error"));
        }
    }

3

Sử dụng phương thức "InternalServerError" tích hợp (có sẵn trong ApiControll):

return InternalServerError();
//or...
return InternalServerError(new YourException("your message"));

0

Chỉ cần cập nhật về trạng thái hiện tại của ASP.NET WebAPI. Giao diện hiện được gọi IActionResultvà triển khai không thay đổi nhiều:

[JsonObject(IsReference = true)]
public class DuplicateEntityException : IActionResult
{        
    public DuplicateEntityException(object duplicateEntity, object entityId)
    {
        this.EntityType = duplicateEntity.GetType().Name;
        this.EntityId = entityId;
    }

    /// <summary>
    ///     Id of the duplicate (new) entity
    /// </summary>
    public object EntityId { get; set; }

    /// <summary>
    ///     Type of the duplicate (new) entity
    /// </summary>
    public string EntityType { get; set; }

    public Task ExecuteResultAsync(ActionContext context)
    {
        var message = new StringContent($"{this.EntityType ?? "Entity"} with id {this.EntityId ?? "(no id)"} already exist in the database");

        var response = new HttpResponseMessage(HttpStatusCode.Ambiguous) { Content = message };

        return Task.FromResult(response);
    }

    #endregion
}

Điều này có vẻ thú vị, nhưng cụ thể ở đâu trong dự án là mã này được đặt? Tôi đang làm dự án api 2 web của tôi trong vb.net.
Tắt vàng

Nó chỉ là một mô hình để trả lại lỗi và có thể cư trú ở bất cứ đâu. Bạn sẽ trả về một thể hiện mới của lớp trên trong Trình điều khiển của bạn. Nhưng thành thật mà nói, tôi cố gắng sử dụng các lớp dựng sẵn bất cứ khi nào có thể: this.Ok (), createdAtRoute (), NotFound (). Chữ ký của phương thức sẽ là IHttpActionResult. Không biết họ có thay đổi tất cả điều này với NetCore không
Thomas Hagström

-2

Đối với những lỗi trong đó modelstate.isvalid là sai, tôi thường gửi lỗi vì nó bị ném bởi mã. Thật dễ hiểu cho nhà phát triển đang tiêu thụ dịch vụ của tôi. Tôi thường gửi kết quả bằng cách sử dụng mã dưới đây.

     if(!ModelState.IsValid) {
                List<string> errorlist=new List<string>();
                foreach (var value in ModelState.Values)
                {
                    foreach(var error in value.Errors)
                    errorlist.Add( error.Exception.ToString());
                    //errorlist.Add(value.Errors);
                }
                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.BadRequest,errorlist);}

Điều này sẽ gửi lỗi đến máy khách ở định dạng bên dưới, về cơ bản là danh sách các lỗi:

    [  
    "Newtonsoft.Json.JsonReaderException: **Could not convert string to integer: abc. Path 'Country',** line 6, position 16.\r\n   
at Newtonsoft.Json.JsonReader.ReadAsInt32Internal()\r\n   
at Newtonsoft.Json.JsonTextReader.ReadAsInt32()\r\n   
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter, Boolean inArray)\r\n   
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)",

       "Newtonsoft.Json.JsonReaderException: **Could not convert string to integer: ab. Path 'State'**, line 7, position 13.\r\n   
at Newtonsoft.Json.JsonReader.ReadAsInt32Internal()\r\n   
at Newtonsoft.Json.JsonTextReader.ReadAsInt32()\r\n   
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter, Boolean inArray)\r\n   
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)"
    ]

Tôi không khuyên bạn nên gửi lại mức độ chi tiết này trong trường hợp ngoại lệ nếu đây là API bên ngoài (tức là tiếp xúc với internet công cộng). Bạn nên thực hiện thêm một số công việc trong bộ lọc và gửi lại một đối tượng JSON (hoặc XML nếu đó là định dạng được chọn) nêu chi tiết lỗi thay vì chỉ là một ngoại lệ.
Sudhanshu Mishra

Đúng không gửi ngoại lệ này cho API bên ngoài. Nhưng bạn có thể sử dụng nó để gỡ lỗi các vấn đề trong API nội bộ và trong quá trình thử nghiệm.
Ashish Sahu
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.