1. 程式人生 > >ABP官方文件(三十八)【AJAX API】

ABP官方文件(三十八)【AJAX API】

6.6 ABP表現層 - AJAX API

6.6.2.1 AJAX操作問題

現代的應用經常會使用AJAX,尤其是單頁應用,幾乎是和伺服器通訊的唯一手段,執行AJAX通常會有以下步驟:

  • 基本上:為了執行一個AJAX呼叫,首先你要在客戶端提供一個可供請求的URL,選取提交資料和一個方法(GET,POST,PUT,DELETE)。

  • 等待呼叫完成後,處理返回結果。當執行AJAX呼叫伺服器端的時候,可能會有錯誤(一般是網路錯誤)。當然也有可能是伺服器端產生了一些錯誤,對於這些錯誤會,伺服器會返回一個失敗的響應並且附上錯誤訊息給客戶端。

  • 客戶端程式碼應該處理這些錯誤,並且可以選擇通知使用者(可以顯示一個錯誤對話方塊)。如果沒有錯誤且伺服器端返回了資料,客戶端必須處理它。還有你應該限制頁面的某個區域(或者整個頁面),並顯示一個忙碌的指示直到AJAX操作完成。

  • 伺服器端在得到請求後執行伺服器端程式碼,捕獲異常並返回一個有效的響應給客戶端。在錯誤情況下,可以選擇傳送錯誤訊息給客戶端。如果是驗證錯誤,伺服器端可以新增驗證錯誤的驗證資訊。在成功情況下,可以傳送返回值給客戶端。

6.6.2.2 ABP的方式

由於使用 abp.ajax 函式對AJAX呼叫進行了封裝, 所以ABP能自動化這些步驟。下面是一個AJAX呼叫示例:

var newPerson = {
    name: 'Dougles Adams',
    age: 42
};

abp.ajax({
    url: '/People/SavePerson',
    data: JSON
.stringify(newPerson) }).done(function(data) { abp.notify.success('created new person with id = ' + data.personId); });

abp.ajax得到 options 作為物件。你可以傳遞任何有效的jQuery的 $.ajax 函式中的引數。有一些預設引數:dataType 是 json,type是 POST,還有 contentType是 application/json(在傳送資料到伺服器端之前,我們需要呼叫 JSON.stringify 將指令碼物件轉換為JSON字串)。通過對apb.ajax傳遞options可以覆蓋預設值。

abp.ajax返回promise。因此,你可以寫這些處理函式:done,fail,then等等。在這個例子中,我們對 PeopleController’s SavePerson action 傳送了一個簡單的AJAX請求。在 done 處理函式中,我們對新建立的person取得了它的主鍵id並且顯示了建立成功的通知。讓我們看看 MVC Controller

public class PeopleController : AbpController
{
    [HttpPost]
    public JsonResult SavePerson(SavePersonModel person)
    {
        //TODO: 儲存新建立的person到資料庫並且返回person的id
        return Json(new {PersonId = 42});
    }
}

正如你猜測的 SavePersonModel 包含了Name和Age屬性。SavePerson 被標記為 HttpPost 特性,因為abp.ajax預設方法是POST。通過返回了匿名物件簡化了方法實現。

這個看上去很簡單直白,但是ABP在背後做了很多重要的處理。讓我們深入瞭解一下:

6.6.2.3 AJAX 返回訊息

即使我們直接的返回了一個帶有PersonId = 2 的物件,ABP也會使用 MvcAjaxResponse 物件來包裝它。事實上AJAX響應返回的內容應該像下面一樣:

{
  "success": true,
  "result": {
    "personId": 42
  },
  "error": null,
  "targetUrl": null,
  "unAuthorizedRequest": false,
  "__abp": true
}

在這裡所有的屬性都是駝峰命名的(因為這在JavaScript中是慣例),即使在服務端程式碼中是PascalCased的。下面解釋一下所有的欄位:

  • success:boolean型別的值(true或者false),用來表示操作的成功狀態。如果是ture,abp.ajax會解析該promise並且呼叫 done 函式。如果是false(在方法被呼叫的時候,如果有個異常被丟擲),它會呼叫 fail 函式並且使用 abp.message.error 函式顯示 error 訊息。

  • result:控制器的action的實際返回值。如果success是ture並且伺服器傳送了返回值那麼它才是有效的。

  • error:如果success是false,這個欄位是一個包含 message和details 欄位的物件。

  • targetUrl:如果需要的話,這提供了一種可能性:伺服器端傳送一個URL到客戶端,使客戶端可以重定向到其它的URL。

  • unAuthorizedRequest:這提供了一種可能性:伺服器端傳送通知給客戶端該操作未被授權,或者是未認證使用者。如果該值是true,那麼abp.ajax會 reloads 當前的頁面。

  • __abp:通過ABP包裝響應返回的特殊簽名。你自己不需要用到它,但是abp.ajax會處理它。

這種格式的物件會被 abp.ajax 函式識別且處理。abp.ajax會得到控制器的實際返回值(一個帶有personid屬性的物件),如果沒有錯誤的話,那麼你會在done函式中處理返回值。

6.6.2.4 處理錯誤

正如上面所述,ABP在伺服器端處理異常,並且返回一個帶有錯誤訊息的物件。如下所示:

{
  "targetUrl": null,
  "result": null,
  "success": false,
  "error": {
    "message": "An internal error occured during your request!",
    "details": "..."
  },
  "unAuthorizedRequest": false,
  "__abp": true
}

正如你看到的,success是false 並且 result是null。abp.ajax處理這個物件,並且使用abp.message.error函式來顯示錯誤訊息給使用者。如果你的伺服器端程式碼丟擲了 UserFriendlyException 型別的異常。它會直接的顯示異常資訊給使用者。否則,它會隱藏實際的錯誤(將錯誤寫入日誌),並且顯示一個標準的“伺服器內部錯誤…”資訊給使用者。所有的這些都是ABP自動處理的。

你可能想為某個特別的AJAX呼叫禁止顯示訊息,那麼新增 * abpHandleError: false*abp.ajax的options

HTTP狀態碼

在異常發生的時候,ABP會返回給定的HTTP狀態碼:

  • 401:未經身份驗證的請求(沒有登入,但是伺服器端需要身份驗證);

  • 403:未授權的請求;

  • 500:所有其它型別的異常。

6.6.2.5 WrapResult和DontWrapResult特性

使用 WrapResult和DontWrapResult 特性,可以對控制器的某個action或者所有的action來控制包裝。

ASP.NET MVC 控制器

如果返回的型別是 JsonResult(或者Task\

public class PeopleController : AbpController
{
    [HttpPost]
    [WrapResult(WrapOnSuccess = false, WrapOnError = false)]
    public JsonResult SavePerson(SavePersonModel person)
    {
        //TODO: 儲存新建立的person到資料庫並且返回person的id
        return Json(new {PersonId = 42});
    }
}

作為一個快速開發方式,我們只能使用 [DontWrapResult] 特性在這個相同的示例上。

你可以在啟動配置裡面改變這個預設的行為(使用 Configuration.Modules.AbpMvc()…)。

ASP.NET Web API 控制器

如果action被成功執行,ABP 不會預設包裝 Web API Action的返回結果。如果需要的話,你可以新增WrapResult特性到action或者控制器上。但是它會 包裝異常

你可以在啟動配置裡面改變這個預設的行為(使用 Configuration.Modules.AbpWebApi()…)。

動態Web API層

預設 ABP會 包裝 動態Web API層的所有方法。你可以在你應用服務的介面上使用 WrapResult和DontWrapResult 特性來改變這個行為。

你可以在啟動配置裡面改變這個預設的行為(使用 Configuration.Modules.AbpWebApi()…)。

ASP.NET Core 控制器

ABP會自動包裝JsonResult,ObjectRes以及那些沒有實現IActionResult物件。詳情請查閱ASP.NET Core文件

你可以在啟動配置裡面改變這個預設的行為(使用 using Configuration.Modules.AbpAspNetCore()…)。

6.6.2.6 動態Web API層

雖然ABP提供了一種呼叫Ajax的簡單機制,但是在真實世界的應用中,為每個Ajax呼叫編寫javascript函式是很經典的。例如:

//建立一個抽象了Ajax呼叫的function
var savePerson = function(person) {
    return abp.ajax({
        url: '/People/SavePerson',
        data: JSON.stringify(person)
    });
};

//建立一個新的 person
var newPerson = {
    name: 'Dougles Adams',
    age: 42
};

//儲存該person
savePerson(newPerson).done(function(data) {
    abp.notify.success('created new person with id = ' + data.personId);
});

這是一個最佳實踐,但是對每個AJAX呼叫函式都這樣做,那是耗時且乏味的。對於應用服務和控制器,ABP能夠自動的生成這些函式。