ข้อผิดพลาดของ web api ภายในควรได้รับการจัดการอย่างไร

ในแอปพลิเคชันของเรา เรามีชุดของ hooks การบันทึกที่ค่อนข้างตรงไปตรงมา (IExceptionFilters บนตัวควบคุม MVC และ API และ catch-all เพิ่มเติมใน Application_Error()) แต่มีข้อผิดพลาดทั้งหมวดหมู่ที่ไม่ทริกเกอร์ข้อผิดพลาดใดๆ หากข้อยกเว้นถูกส่งมาจากภายใน WebAPI เอง หรือจากสิ่งที่ใช้ภายใน (เช่น ตัวเริ่มต้นประเภทของคลาสที่ถูกสร้างขึ้นโดยตัวแก้ไขการขึ้นต่อกัน) ทั้งหมดที่ฉันได้รับก็คือการตอบกลับ 500 รายการถูกส่งไปยังไคลเอนต์

วิธีเดียวที่ฉันพบว่าสามารถบันทึกรายละเอียดข้อผิดพลาดได้คือใช้ HttpConfiguration.IncludeErrorDetailPolicy เพื่อกำหนดค่าแอปพลิเคชันให้ปล่อยรายละเอียดข้อผิดพลาด อย่างไรก็ตาม การเผยแพร่รายละเอียดข้อผิดพลาดของคุณให้โลกได้รับรู้ถือเป็นแนวปฏิบัติที่ไม่ดี ดังนั้น ฉันจึงอยากจะเปลี่ยน ปิดสิ่งนี้ทั้งหมดหรือตั้งค่าเป็นสิ่งที่มีเงื่อนไข (เช่นในเครื่องเท่านั้น) .. แต่นั่นหมายถึงการย้ายระยะไกลไปยังเซิร์ฟเวอร์ที่แอปพลิเคชันทำงานอยู่และเรียกใช้ API ในเครื่องด้วยเครื่องมือที่สามารถตรวจสอบการตอบสนอง (เช่น IE หรือ Google Chrome) เพื่อดูว่าเกิดอะไรขึ้น

ฉันเคยเห็นคำถามอื่นที่นี่ในลักษณะเดียวกัน (ที่นี่) แต่วิธีแก้ปัญหาที่นำเสนอ (โดยใช้ DelegatingHandler เพื่อตรวจสอบการตอบสนอง) ไม่ตรงกับความต้องการของเรา ไม่มีเหตุการณ์ใดที่ฉันสามารถขอส่วนขยายที่ฉันสามารถใช้ได้หรืออะไรทำนองนั้นเพื่อบันทึกข้อยกเว้นจริงที่เกิดขึ้นหรือไม่

(นอกเหนือจากนี้ ฉันคิดว่าฉันสามารถเปลี่ยน InclusiveErrorDetailPolicy เป็น Always และใช้วิธีแก้ปัญหาที่นำเสนอในเธรดอื่นเพื่อบันทึกรายละเอียดข้อผิดพลาดใน MessageHandler บันทึกและขัดมันด้วยตนเองจากการตอบกลับที่ส่งไปยังไคลเอนต์ แต่นั่น จะเป็นแฮ็คที่น่ารังเกียจ)

ความคิด? :/


person William Scalf    schedule 18.01.2013    source แหล่งที่มา
comment
เหตุใดแนวทาง MessageHandler จึงไม่เหมาะกับคุณ   -  person Youssef Moussaoui    schedule 18.01.2013
comment
ฉันอาจจะเข้าใจผิด แต่จากวิธีที่ฉันอ่าน วิธีเดียวที่จะได้รับวัตถุข้อยกเว้นที่ฉันสามารถบันทึกได้คือทำตามแฮ็คที่กล่าวถึงในตอนท้ายของคำถามของฉัน - เพื่อเปิดใช้งานการรวมรายละเอียดข้อผิดพลาดในการตอบกลับทั้งหมด จากนั้นแยกวิเคราะห์รายละเอียดข้อผิดพลาดนั้นเพื่อหาข้อผิดพลาดเพื่อพยายามสร้างข้อยกเว้นที่ถูกส่งออกไปแต่แรก จากนั้นขัดรายละเอียดเหล่านั้นจากการตอบกลับด้วยตนเองก่อนที่จะส่งไปยังไคลเอนต์ ..และถึงแม้จะได้ผล แต่ก็ฟังดูหยาบคาย เปราะ และมีแนวโน้มที่จะสูญเสียข้อมูลการวินิจฉัย และ/หรือทำให้ข้อมูลนั้นรั่วไหลไปยังลูกค้าโดยไม่ได้ตั้งใจ   -  person William Scalf    schedule 18.01.2013
comment
คุณต้องการรักษาข้อมูลการวินิจฉัย และ หลีกเลี่ยงการรั่วไหลของข้อมูลไปยังไคลเอนต์หรือไม่ คุณกำลังพยายามส่งการตอบกลับประเภทใด เหตุใดค่าเริ่มต้นจึงไม่เหมาะกับคุณ คุณจะได้รับข้อมูลการวินิจฉัยทั้งหมดบนเครื่องภายในเพื่อวัตถุประสงค์ในการแก้ไขจุดบกพร่อง และไม่มีข้อมูลใดรั่วไหลไปยังไคลเอนต์ระยะไกล   -  person Youssef Moussaoui    schedule 18.01.2013
comment
ใช่แล้ว ความตั้งใจของฉันคือเก็บข้อมูลบนเซิร์ฟเวอร์ให้ได้มากที่สุด และตอบสนองน้อยที่สุดเพื่อส่งไปยังไคลเอนต์ ปัญหาคือว่า สำหรับข้อผิดพลาดส่วนใหญ่ เราใช้กลไกในตัวในเฟรมเวิร์กเพื่อบันทึกรายละเอียดข้อบกพร่องสำหรับการบันทึก (MVC และ HTTP IExceptionFilters และเหตุการณ์ Application_Error) ซึ่งทั้งหมดนี้ถือว่าดี แต่ดูเหมือนว่าจะมีหมวดหมู่ของ ข้อผิดพลาดภายในและภายนอก web api โดยที่ไม่มีกลไกดังกล่าว - หรืออย่างน้อยก็ไม่ใช่ว่าฉันสามารถหาได้   -  person William Scalf    schedule 18.01.2013


คำตอบ (2)


เราเปิดคำขอรับการสนับสนุนจาก Microsoft Partner Network และพวกเขากลับมาพร้อมกับสิ่งที่ฉันรู้สึกว่าเป็นคำตอบที่ดีกว่า

แนวคิดคือการแทนที่การใช้งาน IHttpControllerActivator เริ่มต้นของแพลตฟอร์มด้วยสิ่งที่ล้อมรอบพฤติกรรมการสร้างคอนโทรลเลอร์เริ่มต้นด้วยพฤติกรรมที่ต้องการเพิ่มเติม

ในกรณีของเรา นั่นหมายถึงการรวมเมธอด Create ของ DefaultHttpControllerActivator ด้วยโครงสร้าง try/catch/throw และการเรียกไปยังบริการบันทึกของเรา นั่นอาจไม่ครอบคลุม 100% แต่ข้อยกเว้นส่วนใหญ่ที่เราขาดหายไปเกี่ยวข้องกับการสร้างคอนโทรลเลอร์ ดังนั้นจึงน่าจะช่วยได้มาก

ฉันชอบที่จะเชื่อมต่อกับเมธอด HandleException ภายใน HttpControllerDispatcher ได้จริงๆ แต่มันมีทั้งแบบส่วนตัวและแบบคงที่ ดังนั้น meh

person William Scalf    schedule 26.02.2013
comment
+1 และเพียงหมายเหตุ: แทนที่ด้วย IHttpControllerSelector, IHttpActionSelectorและ IHttActionInvoker เพื่อควบคุมข้อผิดพลาดภายในเหล่านี้ได้อย่างสมบูรณ์ - person Konamiman; 05.11.2014

โอเค ฉันเข้าใจสิ่งที่คุณกำลังพยายามทำ ขอบคุณสำหรับการชี้แจง WebAPI มีโมเดลที่การตอบสนองข้อผิดพลาดไม่จำเป็นต้องเกิดจากข้อยกเว้น ใครๆ ก็สามารถส่งคืน HttpResponseMessage ด้วย 400 ได้โดยไม่ต้องส่งข้อยกเว้นจริงๆ และในหลายกรณี ข้อผิดพลาดของเฟรมเวิร์กในตัวทำงานในลักษณะเดียวกันโดยไม่มีข้อยกเว้น

ตอนนี้ ฉันคิดว่าสิ่งที่คุณแนะนำฟังดูดีสำหรับฉัน คุณสามารถตั้งค่า ErrorDetailPolicy เป็น Always และใช้ตัวจัดการข้อความที่บันทึกข้อผิดพลาดและใช้ HttpError อื่นที่มีเฉพาะข้อความเท่านั้น นี่คือสิ่งที่อาจมีลักษณะดังนี้:

public class ErrorHandlingMessageHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
        HttpError error;
        if (response.TryGetContentValue(out error))
        {
            LogError(error)
            // Use an HttpError that doesn't leak internal information
            (response.Content as ObjectContent).Value = new HttpError(error.Message);
        }

        return response;
    }
}

โปรดสังเกตว่าเราไม่ได้ขัดถูข้อผิดพลาดที่มีอยู่ เรากำลังสร้างอันใหม่เพื่อลดความเสี่ยงของการรั่วไหลของข้อมูล ข้อความควรจะปลอดภัยเสมอในการส่งกลับ สิ่งนี้ไม่ครอบคลุมถึงการส่ง Model State กลับ แต่หากคุณต้องการ คุณสามารถคัดลอกไปยังข้อผิดพลาดใหม่ได้ตลอดเวลา

วิธีคิดอย่างหนึ่งเกี่ยวกับเรื่องนี้ก็คือ คุณสามารถบันทึกการตอบกลับที่คุณจะส่งไปยังไคลเอ็นต์ในเครื่องได้ จากนั้นจึงส่งข้อความที่ปลอดภัยไปยังไคลเอ็นต์ระยะไกลโดยไม่มีรายละเอียดข้อผิดพลาด

person Youssef Moussaoui    schedule 18.01.2013