ASP.NET MVC自定義錯(cuò)誤頁(yè)面真的簡(jiǎn)單嗎?
如果你在設(shè)置asp.net mvc自定義錯(cuò)誤頁(yè)面時(shí)遇到問(wèn)題,這并不止你一個(gè)人。驚訝之余你的做法是正確的,沒(méi)有起到作用的原因是其一部分錯(cuò)誤是由asp.net管道處理的,另一部分是由iis直接處理。
通常情況 (我期望是這種情況,在一些其他框架/服務(wù)器上) 我們只需要在一個(gè)地方配置自定義錯(cuò)誤頁(yè)就可以了,無(wú)論怎么哪兒引發(fā)的錯(cuò)誤。就像這樣︰
<customErrors mode="On"> <error code="404" path="404.html" /> <error code="500" path="500.html" /> </customErrors>
自定義404錯(cuò)誤頁(yè)面
當(dāng)一個(gè)資源不存在時(shí)(包含靜態(tài)和動(dòng)態(tài)),我們需要返回一個(gè)404狀態(tài)的頁(yè)面,通常我們需要提供一些稍微友好的信息替代asp.net/iis生成的默認(rèn)錯(cuò)誤頁(yè)呈現(xiàn)給我們的網(wǎng)站訪問(wèn)者,可能是提出一些忠告 為什么該資源可能不存在或提供選擇要搜索的網(wǎng)站。
這里僅作演示簡(jiǎn)單設(shè)置如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <title>404 Page Not Found</title> </head> <body> <h1>404 Page Not Found</h1> </body> </html>
我創(chuàng)建了一個(gè)新的ASP.NET MVC 5應(yīng)用程序,包含vs自帶的標(biāo)準(zhǔn)模版。如果我運(yùn)行它嘗試導(dǎo)航到一個(gè)不存在的路徑 e.g. /foo/bar,就會(huì)得到一個(gè)包含如下信息的標(biāo)準(zhǔn) ASP.NET 404 頁(yè)面:、

不太友好不是?
這種情況的錯(cuò)誤是由ASP.NET MVC引發(fā)因?yàn)樗鼪](méi)有找到與url相匹配的controller或action。
為了自定義404錯(cuò)誤頁(yè)面,在web.config 的 <system.web></system.web>配置節(jié):
<customErrors mode="On"> <error statusCode="404" redirect="~/404.html"/> </customErrors>
mode="On" 這樣我們就能在本地看到錯(cuò)誤頁(yè)面。一般你可能只想在投入使用時(shí)呈現(xiàn)而設(shè)置為 mode="RemoteOnly"。
現(xiàn)在如果我再次導(dǎo)航到/foo/bar 就能看到我剛剛定義的錯(cuò)誤頁(yè)面.
然而正如我所料,此時(shí)的url路徑并不是 /foo/bar ASP.NET 將其重定向?yàn)?404.html?aspxerrorpath=/foo/bar,而且我檢查響應(yīng)的HTTP狀態(tài)碼也為正常狀態(tài)的200。
這是非常糟糕的,返回http code 200不僅會(huì)引起誤解,也不利于SEO。簡(jiǎn)單來(lái)講,如果指定路徑的資源不存在應(yīng)該返回404如果是資源被移動(dòng)應(yīng)該重定向到新路徑。
要修復(fù)這個(gè)問(wèn)題我們可以更改ASP.NET默認(rèn)行為 重定向錯(cuò)誤頁(yè) 為 重寫(xiě)返回(rewrite the response)。
<customErrors mode="On" redirectMode="ResponseRewrite"> <error statusCode="404" redirect="~/404.html"/> </customErrors>
然而這并沒(méi)有太大的作用(這老外真啰嗦).盡管原Url地址沒(méi)有被重定向, ASP.NET 仍然返回的是 200,此外將我們自定義錯(cuò)誤頁(yè)顯示為純文本。
似乎我們不得不返回一個(gè)ASP.NET頁(yè)面. 如果你之前以為不用再去 *.aspx頁(yè)面的話,那我恐怕讓你失望了。
因此將錯(cuò)誤頁(yè)及相應(yīng)的web.config改為404.aspx之后,url和content type(text/html)都正常了。
但200的問(wèn)題依然存在. 這個(gè)問(wèn)題微軟官方給出了相應(yīng)的解決方案——設(shè)置頁(yè)面的狀態(tài)碼. 我們?cè)?04.aspx加入如下部分:
<% Response.StatusCode = 404 %>
我們現(xiàn)在得到了正確的狀態(tài)碼、url及自定義錯(cuò)誤頁(yè)面,就這樣完事兒了嗎?
錯(cuò).
如果我們鏈接到一個(gè)靜態(tài)頁(yè)路徑(e.g. foo.html) 或一個(gè)不匹配我們路由配置的URL (e.g. /foo/bar/foo/bar),我們會(huì)看到到一個(gè)標(biāo)準(zhǔn)的IIS 404錯(cuò)誤頁(yè)面.
上述情況繞過(guò)了ASP.NET由IIS處理了請(qǐng)求. 當(dāng)然如果你在controller ation 中 return一個(gè)HttpNotFound()也會(huì)得到同樣的結(jié)果——這是因?yàn)镸VC只是簡(jiǎn)單的設(shè)置status code并沒(méi)有拋出錯(cuò)誤,而是將它交給了IIS.
這種情況我們需要設(shè)置iis的錯(cuò)誤頁(yè)面(僅IIS 7+有效).在 web.config <system.webServer></system.webServer>配置節(jié)中:
<httpErrors errorMode="Custom"> <remove statusCode="404"/> <error statusCode="404" path="/404.html" responseMode="ExecuteURL"/> </httpErrors>
同樣設(shè)置 errorMode="Custom" 以便本地測(cè)試. 正常情況會(huì)設(shè)置為 errorMode="DetailedLocalOnly".
注意我使用了html頁(yè)面,而不是aspx。通常你應(yīng)該用簡(jiǎn)單的靜態(tài)文件作為錯(cuò)誤頁(yè)面,這樣即使ASP.NET出現(xiàn)錯(cuò)誤時(shí)錯(cuò)誤頁(yè)面依然能夠正常顯示。
現(xiàn)在如果我們導(dǎo)航到一個(gè)不存在的靜態(tài)文件路徑就會(huì)得到一個(gè)自定義錯(cuò)誤頁(yè)面而不是IIS默認(rèn)的404 page,剩下的還是和之前一樣的200問(wèn)題。
幸運(yùn)的是 IIS 實(shí)際上提供了內(nèi)置的解決方案來(lái)解決這一點(diǎn),如果你設(shè)置 responseMode ="File"IIS 將返回您的自定義錯(cuò)誤頁(yè)面,而不改變?cè)嫉捻憫?yīng)標(biāo)頭︰
<error statusCode="404" path="404.html" responseMode="File"/>
搞定。
自定義500錯(cuò)誤頁(yè)
大部分無(wú)外乎照搬上面的解決方法,添加一個(gè)自定義的500錯(cuò)誤頁(yè)面。這里有幾點(diǎn)值得注意的地方。
標(biāo)準(zhǔn)的 ASP.NET MVC模板內(nèi)置的 HandleErrorAttribute 作為一個(gè)全局過(guò)濾器。捕獲在ASP.NET MVC管道引發(fā)的任何錯(cuò)誤,并返回一個(gè)自定義"錯(cuò)誤"視圖提供你有在web.config中啟用自定義錯(cuò)誤。它會(huì)尋找 ~/views/{controllerName}/error.cshtml 或 ~ / views/shared/error.cshtml。
如果你使用了過(guò)濾器(filter),你需要更新現(xiàn)有的自定義錯(cuò)誤視圖,并不存在的則需要?jiǎng)?chuàng)建(最好放在views/shared文件夾下)
我沒(méi)有看見(jiàn)這個(gè)filter有可以設(shè)置的屬性值,在 MVC 管道引發(fā)的任何異常都會(huì)退回到標(biāo)準(zhǔn)的 ASP.NET 錯(cuò)誤配置頁(yè)面,既然你要設(shè)置那些**那這里就用不到這個(gè)filter。
添加如下自定義錯(cuò)誤頁(yè)配置:
<customErrors mode="On" redirectMode="ResponseRewrite"> <error statusCode="404" redirect="~/404.aspx"/> <error statusCode="500" redirect="~/500.aspx"/> </customErrors>
類似于前面創(chuàng)建的404.aspx:
<% Response.StatusCode = 500 %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>500 Server Error</title> </head> <body> <h1>500 Server Error</h1> </body> </html>
不幸的是這樣做并不會(huì)捕獲到你應(yīng)用程序中的每一個(gè)異常。一個(gè)相當(dāng)常見(jiàn)的錯(cuò)誤——由 ASP.NET 產(chǎn)生的請(qǐng)求的驗(yàn)證,如一個(gè)危險(xiǎn)的url路徑/foo/bar<script></script> ,這個(gè)實(shí)際上會(huì)產(chǎn)生一個(gè)404響應(yīng);因此你可以添加一個(gè)默認(rèn)錯(cuò)誤配置:
<customErrors mode="Off" redirectMode="ResponseRewrite" defaultRedirect="~/500.aspx"> <error statusCode="404" redirect="~/404.aspx"/> <error statusCode="500" redirect="~/500.aspx"/> </customErrors>
最后為了捕獲非ASP.NET異常我們?cè)O(shè)置IIS自定義服務(wù)器內(nèi)部錯(cuò)誤500錯(cuò)誤頁(yè)面:
<error statusCode="500" path="500.html" responseMode="File"/>
總結(jié)
在你的應(yīng)用程序根目錄創(chuàng)建如下錯(cuò)誤頁(yè)面:
404.html - for IIS
404.aspx - for ASP.NET
500.html - for IIS
500.aspx - for ASP.NET
確認(rèn)您設(shè)置在 ASPX 頁(yè)面內(nèi)的適當(dāng)響應(yīng)狀態(tài)碼.
拋棄 MVC HandleErrorAttribute 全局篩選器;配置 ASP.NET 的自定義錯(cuò)誤:
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/500.aspx"> <error statusCode="404" redirect="~/404.aspx"/> <error statusCode="500" redirect="~/500.aspx"/> </customErrors>
配置IIS自定義錯(cuò)誤頁(yè):
<httpErrors errorMode="DetailedLocalOnly"> <remove statusCode="404"/> <error statusCode="404" path="404.html" responseMode="File"/> <remove statusCode="500"/> <error statusCode="500" path="500.html" responseMode="File"/> </httpErrors>
原文鏈接:http://benfoster.io/blog/aspnet-mvc-custom-error-pages
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
.NET 6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)數(shù)據(jù)塑形
在查詢的場(chǎng)景中,還有一類需求不是很常見(jiàn),就是在前端請(qǐng)求中指定返回的字段。所以這篇文章主要介紹了.NET 6如何實(shí)現(xiàn)數(shù)據(jù)塑形,需要的可以參考一下2022-01-01
asp.net Repeater分頁(yè)實(shí)例(PageDataSource的使用)
Asp.net提供了三個(gè)功能強(qiáng)大的列表控件:DataGrid、DataList和Repeater控件,但其中只有DataGrid控件提供分頁(yè)功能。相對(duì)DataGrid,DataList和Repeater控件具有更高的樣式自定義性,所以很多時(shí)候我們喜歡使用DataList或Repeater控件來(lái)顯示數(shù)據(jù)2013-04-04
Springboot服務(wù)Docker化自動(dòng)部署的實(shí)現(xiàn)方法
這篇文章主要介紹了Springboot服務(wù)Docker化自動(dòng)部署的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
ASP.NET 固定標(biāo)題列與欄位的具體實(shí)現(xiàn)
客戶提這個(gè)要求很久了,最近才時(shí)間弄,但是看到百度中要沒(méi)有很多詳細(xì)的代碼。廢話不多說(shuō)直接貼代碼。2013-06-06
增加asp.net應(yīng)用程序性能的20種方法(簡(jiǎn)單有效)
增加asp.net應(yīng)用程序性能的20種方法小結(jié),需要的朋友可以參考下,對(duì)于服務(wù)器也需要一些設(shè)置。2010-01-01
asp.net 圖片的讀寫(xiě)入庫(kù)實(shí)現(xiàn)代碼
asp.net對(duì)圖片的讀寫(xiě),實(shí)現(xiàn)將圖片保存到數(shù)據(jù)庫(kù)中,然后再讀取顯示的實(shí)現(xiàn)代碼。2009-11-11
ASP.NET下使用xml反序列化、緩存依賴實(shí)現(xiàn)個(gè)性化配置文件的實(shí)時(shí)生效
本文主要介紹了ASP.NET下使用xml反序列化、緩存依賴實(shí)現(xiàn)個(gè)性化配置文件的實(shí)時(shí)生效的方法。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01
Asp.net的應(yīng)用程序?qū)ο蠛晚?yè)面生存周期
Asp.net的應(yīng)用程序?qū)ο蠛晚?yè)面生存周期,需要的朋友可以參考一下2013-02-02
asp.net實(shí)現(xiàn)服務(wù)器文件下載到本地的方法
這篇文章主要介紹了asp.net實(shí)現(xiàn)服務(wù)器文件下載到本地的方法,需要的朋友可以參考下2017-02-02

