2013-05-14 23 views
10

Tôi có một dịch vụ web ASP.NET Web API mà ném một SerializationException trong trường hợp nhất định. Vấn đề là tôi không thể bẫy và đăng nhập ngoại lệ phía máy chủ này - nơi duy nhất nó xuất hiện trong phần thân của phản hồi HTTP cho máy khách.Làm thế nào để bẫy một ngoại lệ Serialization trong Web API?

Tôi đã đăng ký ExceptionFilterAttribute như được mô tả trong và xác minh rằng nó hoạt động đúng khi tôi ném ngoại lệ trong bộ điều khiển của mình. Thật không may là SerializationException đang được ném trong phản hồi (sau khi bộ điều khiển) và dường như được nuốt hoàn toàn bởi ASP.NET. Tôi cũng đã thử hooking Application_Error() trong Global.asax.cs nhưng nó cũng không hiển thị ở đó.

Làm cách nào để nhận ngoại lệ SerializationException trong phản hồi API Web?

Trả lời

8

Nếu thay vì trả lại đối tượng, bạn sử dụng phương thức ApiController.CreateResponse() và trả về HttpResponseMessage, sau đó bạn có thể thực hiện response.Content.LoadIntoBufferAsync().Wait() và điều đó sẽ buộc việc tuần tự hóa xảy ra trong khi bạn vẫn đang thực hiện hành động.

+1

Hoàn hảo! Tối ưu hóa nhẹ, tôi đã thực hiện hành động không đồng bộ và chờ LoadIntoBufferAsync để không chặn luồng. – Mike

+0

@Mike Rất có thể là LoadIntoBufferAsync chỉ di chuyển byte xung quanh trong bộ nhớ trong quá trình tuần tự hóa, vì vậy bạn có thể không thực hiện bất kỳ IO nào. Do đó bằng cách làm cho nó không đồng bộ, bạn chỉ cần chuyển từ một thread thread thành thread thread thread khác, mà thực sự sẽ gây bất lợi cho perf. Tuy nhiên, ff bạn biết rằng định dạng của bạn sẽ bị chặn chờ IO sau đó async có thể giúp đỡ. –

+1

Tôi chắc chắn không phải là một chuyên gia về Wait vs await, nhưng sự hiểu biết của tôi là Wait() chặn luồng hiện tại trong khi Task thực thi trên một luồng khác. chờ đợi cũng chặn các thread hiện tại nhưng nó không như vậy không đồng bộ, giải phóng các chủ đề để làm những việc khác và sau đó tiếp tục khi nhiệm vụ hoàn thành. Cả hai trường hợp liên quan đến một chuyển đổi chủ đề vì vậy tôi nghĩ rằng hiệu suất sẽ được tương tự, nhưng cách tiếp cận async cho phép (hơi) khả năng mở rộng hơn. Như tôi đã nói, kiến ​​thức của tôi về điều này là sơ sài nên có lẽ chúng ta nên hỏi Stephen Toub. :) – Mike

1

BTW, Serialization các phản hồi thực sự xảy ra ở các lớp máy chủ (trong HttpControllerHandler, khi được lưu trữ trong IIS và trong HttpSelfhostServer, khi được lưu trữ trong SelfHost), đó là cách bên dưới ngăn xếp và không ngay sau khi phản hồi được trả về từ một hành động.

WebAPI stack Poster: http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster-grayscale.pdf

Điều đó nói rằng, tôi không thể tìm ra một cách thẳng về phía trước để đạt được điều này. Điều này là cồng kềnh, nhưng có thể ghi đè các phương thức WriteToStreamAsync Xml và Json của trình định dạng Json mặc định và cố gắng ghi lại bất kỳ ngoại lệ nào?

Hoặc, bạn có thể bật Theo dõi API Web sẽ ghi lại các ngoại lệ xảy ra trong quá trình tuần tự hóa. Nhưng yeah, nếu bạn không biết cho các yêu cầu mà gây ra các lỗi serialization, sau đó bạn có thể muốn kích hoạt truy tìm tất cả các thời gian mà tôi không chắc chắn là một cái gì đó bạn có thể muốn làm.

2

Bạn có thể bắt tất cả ngoại lệ Web Api bằng cách đăng ký triển khai IExceptionHandler.

Xem Web API Global Error Handling

có một số trường hợp ngoại lệ mà bộ lọc không thể xử lý. Ví dụ:

  • Trường hợp ngoại lệ được ném từ bộ điều khiển.
  • Trường hợp ngoại lệ được ném từ trình xử lý tin nhắn.
  • Trường hợp ngoại lệ được ném trong khi định tuyến.
  • Trường hợp ngoại lệ được ném trong quá trình tuần tự hóa nội dung phản hồi.

Một điều không được đề cập trong bài viết đó là IExceptionHandler bạn phải đăng ký qua có một số trường hợp ngoại lệ mà bộ lọc không thể xử lý. Ví dụ:

Exceptions thrown from controller constructors. 
Exceptions thrown from message handlers. 
Exceptions thrown during routing. 
Exceptions thrown during response content serialization . 

Một điều không được đề cập trong bài viết đó là IExceptionHandler của bạn phải được đăng ký, hoặc bằng cách GlobalConfiguration.Configuration.Services.Add(...) hoặc thông qua một container IoC cấu hình để được sử dụng bởi DependencyResolver.

Các vấn đề liên quan