IIS7 แทนที่ customErrors เมื่อตั้งค่า Response.StatusCode?


98

มีปัญหาแปลก ๆ ที่นี่ ทุกคนรู้ดีว่าหากคุณใช้customErrorsส่วนของ web.config เพื่อสร้างหน้าข้อผิดพลาดที่กำหนดเองคุณควรตั้งค่าResponse.StatusCodeเป็นอะไรก็ได้ที่เหมาะสม ตัวอย่างเช่นถ้าฉันสร้างเพจ 404 แบบกำหนดเองและตั้งชื่อว่า 404.aspx ฉันสามารถใส่<% Response.StatusCode = 404 %>เนื้อหาเพื่อให้มีส่วนหัวสถานะ 404 ที่แท้จริง

ตามมาเลย? ดี. ตอนนี้ลองทำบน IIS7 ฉันไม่สามารถไปทำงานได้ หากResponse.StatusCodeตั้งค่าไว้ในหน้าข้อผิดพลาดที่กำหนดเอง IIS7 ดูเหมือนว่าจะแทนที่หน้าข้อผิดพลาดแบบกำหนดเองทั้งหมดและแสดงหน้าสถานะของตนเอง (หากคุณกำหนดค่าไว้)

มีใครอีกบ้างที่เห็นพฤติกรรมนี้และอาจรู้วิธีแก้ไขปัญหานี้หรือไม่? มันทำงานภายใต้ IIS6 ดังนั้นฉันจึงไม่รู้ว่าทำไมสิ่งต่างๆจึงเปลี่ยนไป

หมายเหตุ: ไม่เหมือนกับปัญหาในASP.NET Custom 404 ที่ส่งคืน 200 ตกลงแทนที่จะเป็น 404 ไม่พบ


ฉันมีคำถามเดียวกัน ตอบแล้วนี่http://stackoverflow.com/questions/347281/asp-net-custom-404-returning-200-ok-instead-of-404-not-found
Bobby Cannon

บ๊อบบี้ฉันพบคำถามนั้นจริงและลองทำดู แต่ก็ไม่สามารถแก้ปัญหาได้ แต่ขอบคุณ.
Nicholas

ฉันต้องการแสดงความคิดเห็นว่าปัญหานี้เกิดขึ้นเมื่อเปลี่ยนจาก Classic เป็น Integrated pipeine ฉันใช้โซลูชัน @PavelChuchuva (โซลูชัน @RickStrahl ก็ใช้ได้เช่นกัน) ฉันเดาว่า "passthrough" ใน Classic เป็นไปโดยอัตโนมัติใน Integrated จะใช้การจัดการหน้าข้อผิดพลาดทั่วโลกของเซิร์ฟเวอร์ ..
sonjz

คำตอบ:


116

ตั้งค่า existingResponse เป็น PassThrough ในส่วน system.webServer / httpErrors:

  <system.webServer>
    <httpErrors existingResponse="PassThrough" />
  </system.webServer>

ค่าดีฟอลต์ของคุณสมบัติ existingResponse คือ Auto:

อัตโนมัติบอกให้โมดูลข้อผิดพลาดที่กำหนดเองทำในสิ่งที่ถูกต้อง ข้อความแสดงข้อผิดพลาดจริงที่ไคลเอ็นต์เห็นจะได้รับผลกระทบขึ้นอยู่กับค่าของ fTrySkipCustomErrors ที่ส่งคืนในการIHttpResponse::GetStatusโทร เมื่อตั้งค่า fTrySkipCustomErrors เป็น true โมดูลข้อผิดพลาดที่กำหนดเองจะปล่อยให้การตอบกลับผ่านไป แต่ถ้าตั้งค่าเป็นเท็จโมดูลข้อผิดพลาดที่กำหนดเองจะแทนที่ข้อความด้วยข้อความของตัวเอง

ข้อมูลเพิ่มเติม: สิ่งที่คาดหวังจากโมดูลข้อผิดพลาดแบบกำหนดเอง IIS7


3
โปรดทราบว่าการตั้งค่า existingResponse เป็น PassThrough อาจทำให้เกิดผลข้างเคียงบางอย่าง โปรดใช้ลิงก์ที่ Pavel ให้มาก่อนการเปลี่ยนแปลงใด ๆ
Lex Li

คือ<httpErrors existingResponse="PassThrough" />เทียบเท่ากับResponse.TrySkipIisCustomErrorsหรือพวกเขาทำงานแตกต่างกัน?
Asbjørn Ulsberg

1
@sbjornu พวกเขาบรรลุสิ่งเดียวกัน แต่เมื่อResponse.TrySkipIisCustomErrorsคุณควบคุมได้ดีขึ้นว่าจะแสดงข้อผิดพลาดที่กำหนดเองของ IIS เมื่อใด
Pavel Chuchuva

ขอบคุณฉันได้เห็นข้อมูลมากมายเกี่ยวกับ response.tryskipiiscustomerrors แต่ไม่ค่อยเกี่ยวกับการตอบสนองที่มีอยู่
HBCondo

ฉันแก้ไขปัญหาเกี่ยวกับหน้าแสดงข้อผิดพลาดที่กำหนดเองไม่ทำงานบนโฮสต์เว็บของฉันที่เรียกใช้ IIS7 เพียงแค่ตั้งค่า existingResponse = "อัตโนมัติ" ซึ่งน่าแปลกใจมากเนื่องจากบทความอ้างถึงการอ้างสิทธิ์ที่เป็นค่าเริ่มต้น เห็นได้ชัดว่าไม่ใช่ ... หรือ บริษัท โฮสติ้งของฉันตั้งค่าเริ่มต้นผิดที่อื่นฉันคิดว่า อย่างใดอย่างหนึ่งผมหวังว่าวิธีการที่จะช่วยประหยัดคนไม่กี่ชั่วโมง: \
เอริค Sassaman

80

วิธีที่ง่ายที่สุดในการทำให้พฤติกรรมสอดคล้องกันคือการล้างข้อผิดพลาดและใช้Response.TrySkipIisCustomErrorsและตั้งค่าเป็นจริง สิ่งนี้จะแทนที่การจัดการเพจข้อผิดพลาดส่วนกลางของ IIS จากภายในเพจของคุณหรือตัวจัดการข้อผิดพลาดส่วนกลางใน Application_Error

Server.ClearError();
Response.TrySkipIisCustomErrors = true;

โดยทั่วไปคุณควรทำสิ่งนี้ในตัวจัดการ Application_Error ของคุณที่จัดการข้อผิดพลาดทั้งหมดที่ตัวจัดการข้อผิดพลาดของแอปพลิเคชันของคุณไม่พบ

สามารถดูข้อมูลรายละเอียดเพิ่มเติมได้ในบล็อกโพสต์นี้: http://www.west-wind.com/weblog/posts/745738.aspx


2
สิ่งนี้ใช้ไม่ได้กับฉันด้วย (IIS8) และคำแนะนำดูเหมือนจะไม่ตรงกับ OP (สมมติว่าฉันอ่านถูกต้อง) ฉันต้องการให้การcustomErrorกำหนดค่าใน Web.config ทริกเกอร์ เมื่อResponse.TrySkipIisCustomErrors = trueฉันได้รับพฤติกรรมเดียวกัน: หน้าข้อผิดพลาดที่เซิร์ฟเวอร์สร้างขึ้นจะปรากฏขึ้น เมื่อตั้งค่าให้falseไม่มีอะไรเกิดขึ้น - หน้าต่างเบราว์เซอร์ว่างเปล่า
Shawn South

ทำงานได้ดีสำหรับฉัน! แม้ว่าการตั้งค่าที่ Pavel Chuchuva กล่าวถึงในคำตอบของเขาก็ใช้ได้ผลเช่นกัน แต่ก็มีผลข้างเคียงบางอย่างที่ทำให้เกิดปัญหาอื่น ๆ การตั้งค่านี้ช่วยให้ฉันข้ามข้อผิดพลาด IIS แทนที่ในสถานการณ์เฉพาะที่ฉันต้องการในขณะที่ปล่อยให้พฤติกรรมเหมือนเดิมสำหรับทุกอย่าง
Kevin Tighe

ทำงานได้ดีใน Azure สำหรับฉัน ส่วนหัวของเซิร์ฟเวอร์Server:Microsoft-IIS/8.5 X-AspNet-Version:4.0.30319 X-AspNetMvc-Version:5.2 X-Powered-By:ASP.NET
oxfn

ฉันยังคงพบว่าฉันจำเป็นต้องตั้งค่าcustomErrors mode="Off"ให้มันใช้งานได้ ถ้าฉันทำเช่นนั้น httpErrors existingResponse = "อัตโนมัติ" (ค่าเริ่มต้น) จะทำงานอย่างถูกต้องสำหรับฉันเมื่อฉันใช้รหัสในคำตอบนี้
AaronLS

11

แก้ไขแล้ว:ปรากฎว่าต้องเปิด "ข้อผิดพลาดโดยละเอียด" เพื่อให้ IIS7 "ส่งผ่าน" หน้าข้อผิดพลาดที่คุณอาจมี ดูhttp://forums.iis.net/t/1146653.aspx


1
แม้ว่าคำตอบนี้จะถูกระบุว่าเป็นคำตอบ แต่ฉันคิดว่ามันก็คุ้มค่าที่จะอ่านคำตอบอื่น ๆ เพื่อรับข้อมูลเชิงลึกเกี่ยวกับหัวข้อนี้
Lex Li

นอกจากนี้อาจเป็นการดีที่จะลบออก HandleErrorAttribute ใน FilterConfig
ต่อ G

4

ฉันไม่แน่ใจว่าสิ่งนี้มีลักษณะคล้ายกันหรือไม่ แต่ฉันได้แก้ไขปัญหาที่ฟังดูคล้ายกันบนพื้นผิวและนี่คือวิธีที่ฉันจัดการ

ก่อนอื่นค่าดีฟอลต์สำหรับ existingResponse (อัตโนมัติ) คือคำตอบที่ถูกต้องในกรณีของฉันเนื่องจากฉันมี 404, 400 และ 500 ที่กำหนดเอง (ฉันสามารถสร้างคนอื่นได้ แต่ทั้งสามนี้จะเพียงพอสำหรับสิ่งที่ฉันกำลังทำอยู่) นี่คือส่วนที่เกี่ยวข้องที่ช่วยฉันได้

จาก web.config:

<customErrors mode="Off" />

และ

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/errors/404.aspx" responseMode="ExecuteURL" />
  <error statusCode="500" path="/errors/500.aspx" responseMode="ExecuteURL" />
  <error statusCode="400" path="/errors/400.aspx" responseMode="ExecuteURL" />
</httpErrors>

จากนั้นฉันเพิ่มสิ่งนี้ลงใน Application_Error บน global.asax:

    Response.TrySkipIisCustomErrors = True

ในแต่ละหน้าข้อผิดพลาดที่กำหนดเองของฉันฉันต้องใส่รหัสสถานะการตอบกลับที่ถูกต้อง ในกรณีของฉันฉันใช้ 404 ที่กำหนดเองเพื่อส่งผู้ใช้ไปยังส่วนต่างๆในไซต์ของฉันดังนั้นฉันจึงไม่ต้องการให้รหัสสถานะ 404 ส่งคืนเว้นแต่ว่ามันจะเป็นหน้าที่ตายจริงๆ

อย่างไรก็ตามนั่นเป็นวิธีที่ฉันทำ หวังว่าจะช่วยใครบางคน


3

ปัญหานี้ได้รับการปวดหัวที่สำคัญ ไม่มีข้อเสนอแนะใดที่กล่าวถึงก่อนหน้านี้เพียงอย่างเดียวที่แก้ไขได้สำหรับฉันดังนั้นฉันจึงรวมวิธีแก้ปัญหาไว้ด้วย สำหรับการบันทึกสภาพแวดล้อม / แพลตฟอร์มของเราใช้:

  • .NET Framework 4
  • MVC 3
  • IIS8 (เวิร์กสเตชัน) และ IIS7 (เว็บเซิร์ฟเวอร์)

โดยเฉพาะอย่างยิ่งฉันพยายามรับการตอบสนอง HTTP 404 ที่จะเปลี่ยนเส้นทางผู้ใช้ไปยังหน้า 404 ที่กำหนดเองของเรา (ผ่านการตั้งค่า Web.config)

ก่อนอื่นรหัสของฉันต้องโยนHttpExceptionไฟล์. การส่งคืน a NotFoundResultจากคอนโทรลเลอร์ไม่ได้ผลลัพธ์ตามที่ฉันต้องการ

throw new HttpException(404, "There is no class with that subject");

แล้วฉันจะต้องกำหนดค่าทั้งcustomErrorsและhttpErrorโหนดใน Web.config

<customErrors mode="On" defaultRedirect="/classes/Error.aspx">
  <error statusCode="404" redirect="/classes/404.html" />
</customErrors>

...

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/classes/404.aspx" responseMode="ExecuteURL" />
</httpErrors>

โปรดทราบว่าฉันปล่อยให้existingResponseเป็นAutoซึ่งแตกต่างจากโซลูชันที่ @sefl ให้ไว้

การcustomErrorsตั้งค่าดูเหมือนว่าจำเป็นสำหรับการจัดการกับการโยนของฉันอย่างชัดเจนHttpExceptionในขณะที่httpErrorsโหนดจัดการ URL ที่อยู่นอกรูปแบบเส้นทางที่ระบุใน Globals.asax.cs

ปล. ด้วยการตั้งค่าเหล่านี้ฉันไม่จำเป็นต้องตั้งค่า Response.TrySkipIisCustomErrors


2

TrySkipIisCustomErrorsเป็นเพียงส่วนหนึ่งของปริศนา หากคุณใช้ Custom Error Pages แต่คุณต้องการส่งเนื้อหา RESTful ตามสถานะ 4xx แสดงว่าคุณมีปัญหา การตั้งค่า httpErrors.existingResponse ของ web.config เป็น "อัตโนมัติ" ไม่ทำงานเนื่องจาก. net ดูเหมือนว่าจะส่งเนื้อหาบางหน้าไปยัง IIS อยู่เสมอดังนั้นการใช้ "อัตโนมัติ" จึงทำให้หน้าข้อผิดพลาดที่กำหนดเองทั้งหมด (หรืออย่างน้อยบางหน้า) ไม่ได้ใช้ การใช้ "แทนที่" จะไม่ได้ผลเช่นกันเนื่องจากการตอบกลับจะมีรหัสสถานะ http ของคุณ แต่เนื้อหาจะว่างเปล่าหรือเต็มไปด้วยหน้าข้อผิดพลาดที่กำหนดเอง และในความเป็นจริงแล้ว "PassThrough" จะปิด CEP ดังนั้นจึงไม่สามารถใช้งานได้

ดังนั้นหากคุณต้องการข้าม CEP ในบางกรณี (โดยการข้ามฉันหมายถึงการส่งคืนสถานะ 4xx พร้อมเนื้อหาบางส่วน) คุณจะต้องมีขั้นตอนเพิ่มเติม: ทำความสะอาดข้อผิดพลาด:

void Application_Error(object sender, EventArgs e)
{
    var httpException = Context.Server.GetLastError() as HttpException;
    var statusCode = httpException != null ? httpException.GetHttpCode() : (int)HttpStatusCode.InternalServerError;

    Context.Server.ClearError();
    Context.Response.StatusCode = statusCode;
}

ดังนั้นหากคุณต้องการใช้การตอบกลับ REST (เช่น 400 - คำขอที่ไม่ถูกต้อง) และส่งเนื้อหาบางส่วนไปด้วยคุณจะต้องตั้งค่าTrySkipIisCustomErrorsการดำเนินการที่ใดที่หนึ่งและตั้งค่าexistingResponseเป็น "อัตโนมัติ" ในส่วน httpErrors ใน web.config ตอนนี้:

  • เมื่อไม่มีข้อผิดพลาด (การดำเนินการส่งคืน 4xx หรือ 5xx) และมีการส่งคืนเนื้อหาบางส่วนจะไม่มีการใช้ CEP และเนื้อหาจะถูกส่งไปยังไคลเอนต์
  • เมื่อเกิดข้อผิดพลาด (ข้อยกเว้นถูกโยนทิ้ง) เนื้อหาที่ส่งคืนโดยตัวจัดการข้อผิดพลาดจะถูกลบออกดังนั้นจึงใช้ CEP

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


0

ตามค่าเริ่มต้น IIS 7 จะใช้ข้อความแสดงข้อผิดพลาดที่กำหนดเองโดยละเอียดดังนั้นฉันจะถือว่า Response.StatusCode จะเท่ากับ 404.XX แทนที่จะเป็นแค่ 404

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

ดูข้อมูลเพิ่มเติมได้ที่นี่: http://blogs.iis.net/rakkimk/archive/2008/10/03/iis7-enabling-custom-error-pages.aspx

การตรวจสอบเพิ่มเติมพบว่าฉันทำผิดวิธี - ข้อความโดยละเอียดไม่ได้เป็นค่าเริ่มต้น แต่บางทีอาจถูกเปิดอยู่บนกล่องของคุณหากคุณเห็นข้อความแสดงข้อผิดพลาดต่างๆที่คุณได้กล่าวถึง


Response.StatusCode เป็นจำนวนเต็มดังนั้นฉันจึงไม่เห็นวิธีการตั้งค่าโค้ดที่เฉพาะเจาะจงมากไปกว่า "404" ฉันได้กำหนดค่า IIS7 ให้ใช้ / แสดงหน้าข้อผิดพลาดที่กำหนดเองเช่นที่ URL ของคุณระบุ
Nicholas

อืม ... น่าเสียดายที่ฉันไม่สามารถทดสอบได้ในขณะนี้เนื่องจากฉันไม่ได้อยู่ในพีซีที่บ้าน ถ้าคุณไม่มีทางแก้ - คืนนี้ฉันจะดู
nullnvoid
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.