接觸ABP框架有一段時間了,也遇到了一些問題,看了官網文檔,可是或許是看的不夠細緻的緣由,實際開發中仍是遇到了一些問題,耗費了時間去處理,回頭一看,原來文檔中早已說起。前端
開發環境:ABP+MPA模式+Asp.Net Corejava
猶如ABP官網文檔所介紹的,ABP已經幫咱們把異常這塊處理的很完善了,咱們要作的就是利用好ABP處理異常的功能。瀏覽器
ABP提供了直接將應用層對外服務的功能,經過ABP運行時所建立的動態API層,咱們能夠使用js方法去直接調用應用層服務,固然直接訪問控制器下的方法並無被捨棄。app
在ABP內自動封裝好了一批處理異常的類,配合着這些異常類的使用,ABP在前端也封裝了一些方法,方便咱們處理異常信息,同時咱們也能夠改造前端在展現異常的方式,ABP封裝的是使用Message API展現異常信息並使用的是sweetAlert插件,ABP前端js中提供了方式能夠使得咱們阻止默認的展現,進而使用自定義的展現插件和展現方式。框架
在封裝的類中,UserFriendlyException是對用戶友好的,對於一些操做可能產生的問題,能夠經過拋出UserFriendlyException直接展現給用戶看,而對於其它異常,前端會將詳細信息的隱藏,由於用戶並不會關心具體報錯緣由,只知道是報錯了。在代碼中,有些操做可能須要咱們進行判斷,而後反饋給用戶,以便提示用戶更改相關數據。async
[AbpAuthorize(AppPermissions.Pages_Standard_ItemCode_Create)] private async Task CreateItemCodeAsync(CreateOrUpdateItemCodeInput input) { var itemCode = ObjectMapper.Map<ItemCode>(input.ItemCode); itemCode.Id = itemCode.CreateUniqueItemCode(); var existedItemCode = await _itemCodeRepository.FirstOrDefaultAsync(t => t.Id.Equals(itemCode.Id)); if (existedItemCode != null) { throw new UserFriendlyException(L("該檢測項目已經存在.")); } await _itemCodeRepository.InsertAsync(itemCode); }
如上,在作一個操做前,可能須要判斷是否有相同的記錄,若是有,須要提示給用戶,經過直接拋出UserFriendlyException,在控制器內或在應用層拋出異常都行,能夠將信息直接呈現給用戶,可是須要注意的是有一些條件限制,須要知足相關的條件才能獲取到該錯誤信息,不然頗有可能拿到以下結果或是英文錯誤:"An error has occurred! Error detail not sent by server."spa
在ABP文檔中,專門有一篇文章是處理異常的,https://aspnetboilerplate.com/Pages/Documents/Handling-Exceptions。插件
一、非Ajax請求,則直接展現錯誤頁,此處模擬拋出兩種異常類型,而後在界面中看異常信息。code
public IActionResult Index() { //throw new System.Exception("error message"); throw new UserFriendlyException("error message"); }
若是是拋出的異常不是UserFriendlyException類型,則錯誤頁中展現的信息可能會被隱藏,展現的是描述性的,只須要知道內部出錯就行。server
當拋出的是UserFriendlyException類型時,能夠看到一些直觀的錯誤信息。
固然,能夠在WebCoreModule模塊的預加載方法中啓動展現詳細信息。
Configuration.Modules.AbpWebCommon().SendAllExceptionsToClients = true;
好比開啓後,能夠看到以下具體錯誤信息,雖然這些信息對於用戶來說是沒有什麼價值的。
二、Ajax請求中,跟着官方給定的文檔走一遍是沒有錯的,就怕一些小細節沒有把握到,而後產生大問題,Ajax形式的調用並結合WrapResult特性使用後,在出現異常時,會將數據封裝成以下簡約形式。
{ "targetUrl": null, "result": null, "success": false, "error": { "message": "An internal error occurred during your request!", "details": "..." }, "unAuthorizedRequest": false }
這裏須要注意一個關鍵的一點,是調用控制器下某個方法的返回類型,必需要object、JsonResult和ObjectResult類型,不然將會頁面錯誤框中看不到具體的錯誤信息。
從開發習慣來說,控制器中的方法返回值類型,我喜歡寫以下的格式(錯誤用法),直接使用IActionResult很方便,可是也會有麻煩,
[HttpPost] public async Task<IActionResult> CreateXXX([FromBody]ItemCodeViewModel itemCodeViewModel) {
//do something...return Json(xxx)); }
當在中拋出異常或是方法內調用應用層服務內拋出異常時,界面上的方法老是沒法獲取到異常信息,經過查看瀏覽器內響應的內容老是隻會有錯誤頁響應回來,而頁面內只能看到"An error has occurred! Error detail not sent by server."
具體緣由就是這個方法的返回值不符合ABP文檔給定的要求,而這些細節,在初看文檔或是二次看文檔中都沒有發現它,細節很重要!!!。
三、直接經過動態Api層請求應用層服務,這種情形下,當應用層拋出異常時,會將異常信息經WrapResult封裝,在前端獲取的錯誤信息即是直接封裝完畢的錯誤信息,而後再經處理展現到頁面中。
2019-04-27,望技術有成後能回來看見本身的腳步