2009-05-25 15 views
7

Tôi có một dịch vụ WCF được lưu trữ trong IIS/ASP.NET chấp nhận HTTP Post (không phải là hình thức đăng) của các đối tượng được tuần tự hóa.Ghi lại dữ liệu POST HTTP thô trong khi ngoại lệ

Nếu khách hàng gửi yêu cầu không đúng định dạng (ví dụ: họ không sắp xếp chính xác đối tượng) Tôi muốn đăng nhập thư được gửi lên.

Chúng tôi đã sử dụng ELMAH để nắm bắt các ngoại lệ chưa được giải quyết, vì vậy chỉ cần đính kèm dữ liệu bài đăng sẽ là tùy chọn dễ dàng nhất.

Tôi có thể nhận HttpContext hiện tại trong một ngoại lệ, tuy nhiên điều này chỉ chứa thông tin Tiêu đề HTTP.

Câu hỏi của tôi là: Có cách nào để chụp cơ thể yêu cầu HTTP POST gốc không? Hoặc, thất bại đó - một cách tốt hơn (không có một proxy ngược) của việc thu thập các đầu vào gây ra lỗi?

Chỉnh sửa: Chỉ cần làm rõ, việc chạy chụp ở mức gói không phải lúc nào cũng thực sự phù hợp. Tôi là một giải pháp mà tôi có thể triển khai cho các máy chủ Sản xuất và sẽ có khách hàng ngoài tầm kiểm soát hoặc khả năng giám sát của chúng tôi.

Chỉnh sửa # 2: Một gợi ý đã được thực hiện để truy cập Request.InputStream - điều này không hoạt động nếu bạn đang cố gắng đọc sau khi WCF đã đọc yêu cầu ngoài luồng.

Một đoạn mã mẫu để xem cách tôi đã thử sử dụng tính năng này ở đây.

 StringBuilder log = new StringBuilder(); 

     var request = HttpContext.Current.Request; 

     if (request.InputStream != null) 
     { 
      log.AppendLine(string.Format("request.InputStream.Position = \"{0}\"", request.InputStream.Position)); 
      if (request.InputStream.Position != 0) 
      { 
       request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
      } 

      using (StreamReader sr = new StreamReader(request.InputStream)) 
      { 
       log.AppendLine(string.Format("Original Input: \"{0}\"", sr.ReadToEnd())); 
      } 
     } 
     else 
     { 
      log.AppendLine("request.Inputstream = null"); 
     } 


     log.ToString(); 

Các ouput của log.ToString() là:

 
    request.InputStream.Position = "0" 
    Original Input: "" 
+1

Các "sử dụng" với StreamReader sẽ dẫn đến System.Web.Request.InputStream đang được xử lý (có nghĩa là dữ liệu bị mất). – Jeff

+0

Dữ liệu đã bị mất. –

Trả lời

3

Khi đến dịch vụ của bạn, yêu cầu được xử lý và không có sẵn cho bạn.

Tuy nhiên ... bạn có thể đính kèm message inspector. Message Inspectors cho phép bạn fiddle với tin nhắn trước khi nó đạt đến triển khai hoạt động của bạn. Bạn có thể tạo một bản sao đệm của thư, và sao chép nó vào trong OperationContext.Current.

Tội lỗi xấu của khóa học và điều đó sẽ có nghĩa là phí trên bộ nhớ vì hiện tại hai bản sao của thư đang nổi về mọi yêu cầu.

+0

Cảm ơn - nó không phải là một giải pháp đặc biệt tuyệt vời, nhưng hy sinh một số bộ nhớ có thể sẽ có giá trị nó. –

-2

Sử dụng cáy. Miễn phí từ MS. Hoạt động tuyệt vời.

+1

Tôi đang nói về các lỗi đã xảy ra khi không có Fiddler, Wireshark hoặc bất cứ thứ gì đang chạy để nắm bắt nó. ví dụ: trên máy chủ Sản xuất hoặc Dàn xếp nơi không thể chạy gói dữ liệu mọi lúc. –

-1

Bạn đã xem thuộc tính System.Web.Request.InputStream chưa? Nó phải có chính xác những gì bạn muốn.

Cách "tua lại" thuộc tính InputStream.

if (Request.InputStream.Position != 0) 
    { 
     Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
    } 

Một tùy chọn khác bạn nên xem xét là thu thập thông tin này với HTTPModule trên sự kiện BeginRequest. Các dữ liệu nên có tại sự kiện BeginRequest bởi vì tôi không tin rằng WCF chọn lên yêu cầu cho đến sau khi PostAuthenticateEvent.

+1

Tôi đã xem xét thuộc tính đó - tiếc là luồng đó chỉ chứa dữ liệu chưa đọc. Vào thời điểm ngoại lệ đã xảy ra, dữ liệu đầu vào đã được WCF đọc. Bạn không thể tua lại/đặt lại vị trí. –

+0

Xem cập nhật của tôi ... Vì Request.InputStream.CanSeek là đúng, bạn có thể đặt lại vị trí về 0 bằng cách sử dụng phương thức Tìm kiếm. – Jeff

+0

Cảm ơn bạn đã cập nhật - CanSeek là đúng, tuy nhiên vẫn không có gì trong luồng được đọc. Xem văn bản cập nhật ví dụ về những gì tôi đã làm để thử và kiểm tra này. –

-1

từ dưới ASP.NET (dịch vụ web ASP dưới IIS) đoạn mã sau giúp:

if (request.InputStream.Position != 0) 
{ 
    request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
} 

WCF có thể khác nhau (có nghĩa là nó disposes InputStream sau khi đọc nó)

+0

Đây là câu trả lời giống như câu trả lời của Jeff. Nó cũng không hoạt động vì luồng không thể tìm kiếm được. –