構建Web API服務

tkbSimplest發表於2015-11-09

返回總目錄《一步一步使用ABP框架搭建正式專案系列教程》


構建動態Web API控制器

ABP可以自動地為應用層生成Web API 層。比如說我們之前建立的應用層:

namespace Noah.ChargeStation.Application.CitiesApp
{
    public interface ICityAppService:IApplicationService
    {
        GetCitiesOutput GetCities(GetCityInput input);
        Task<GetCitiesOutput> GetCitiesAsync(GetCityInput input);
        void UpdateCity(CityInput input);
        Task UpdateCityAsync(CityInput input);
        void CreateCity(CreateCityInput input);
        Task CreateCityAsync(CreateCityInput input);
    }
}

我們想要把這些服務作為Web API 控制器暴露給客戶端。ABP通過一句程式碼就可以自動、動態地為該應用層建立Web API 控制器,在Web API層的Api資料夾下找到xxxWebApiModule類的Initialize方法,新增程式碼:

DynamicApiControllerBuilder.For<ICityAppService>("ChargeStationAPI/City").Build();

你要做的就這麼多!這樣,在“/api/services/chargeStationAPI/City”的地方就建立了一個API控制器,所有的方法客戶端都可以使用。

ICityAppService是我們想要使用Api 控制器包裝的應用服務。對於應用服務這不是強制的而是傳統推薦的方式。“ChargeStationAPI/CIty”是一個有著任意名稱空間的控制器名字。你應該至少定義一級的名稱空間,也可以定義更深層次的名稱空間,

比如“myCompany/myApplication/myNamespace1/myNamespace2/myServiceName”。“/api/services/”是所有的Web API控制器的字首 。因而API控制器的地址將會是這個樣子的“/api/services/ChargeStationAPI/City”,GetCities方

法的地址就是“/api/services/ChargeStationAPI/City/getCities”。因為在Javascript中的命名慣例是camelCase,所以方法名就自動轉成了camelCase命名的格式。

ForAll 方法

在一個應用中,我們可能有許多應用服務,一個一個地構建api控制器也許是一個乏味而難忘的工作。DynamicAPIControllerBuilder提供了一種方法,可以在一次呼叫中,對所有的應用服務建立web api 控制器。例如:

DynamicApiControllerBuilder
    .ForAll<IApplicationService>(typeof(ChargeStationApplicationModule).Assembly, "ChargeStationAPI")
    .Build();

ForAll方法是一個接收介面的泛型方法。第一個引數是程式集物件,該程式集包含從給定介面派生的類。最後一個引數是服務名稱空間的字尾。比如我們在給定程式集中有ICityAppService和IProvinceAppService。對於該配置,服務就是

“/api/services/ChargeStationAPI/CityApp”和“/api/services/ChargeStationAPI/ProvinceApp”。計算服務名的過程是這樣的:移除服務介面的Service和AppService字尾以及I字首。而且,服務名格式被轉成了camelCase格式。如果不喜歡

這個轉換,那麼你可以通過“WithServiceName”方法決定你命名。除此之外,還有一個Where方法來過濾服務。如果你要為所有的應用服務構建, 其次在此基礎上再排除一些,那麼這很有用。

重寫ForAll方法

可以在ForAll方法之後重寫配置。例如:

DynamicApiControllerBuilder
    .ForAll<IApplicationService>(typeof(ChargeStationApplicationModule).Assembly, "ChargeStationAPI")
    .Build();//告訴生成器為所有實現了IApplicationService介面的服務方法建立api控制器
DynamicApiControllerBuilder
    .For<ICityAppService>("ChargeStationAPI/City")
    .ForMethod("CreateCity").DontCreateAction()
    .Build();//告訴生成器不要生成"ChargeStationAPI/City"的"CreateCity"方法

Http 動詞

所有的方法預設都是以POST方式建立的。因此,為了使用建立的Web Api方法,客戶端應該傳送post請求。我們通過不同的方式改變這個行為。

WithVerb方法

可以為一個方法使用WithVerb,像下面這樣:

DynamicApiControllerBuilder.For<ICityAppService>("ChargeStationAPI/City")
    .ForMethod("getCities").WithVerb(HttpVerb.Get)
    .Build();

下面直接演示一下:

image

我們直接在Url位址列傳送一次get請求,發現有一個Json格式的資料,錯誤資訊很明確,“輸入是null”。雖然報錯了,至少可以肯定的是已經生成了web api控制器,只是該控制器需要一個輸入引數而已。

HTTP特性

我們可以把HttpGet,HttpPost…特性加到服務介面的方法上:

public interface ICityAppService:IApplicationService
{
    [HttpGet]
    GetCitiesOutput GetCities(GetCityInput input);
    [HttpGet]
    Task<GetCitiesOutput> GetCitiesAsync(GetCityInput input);
    [HttpPost]
    void UpdateCity(CityInput input);
    [HttpPost]
    Task UpdateCityAsync(CityInput input);
    [HttpPost]
    void CreateCity(CreateCityInput input);
    [HttpPost]
    Task CreateCityAsync(CreateCityInput input);
}

要使用這些HTTP特性,就必須嚮應用層專案中新增Microsoft.AspNet.WebApi.Core Nuget包的引用。新增了HTTP特性之後,就不需要使用上面的WithVerb方法了。

命名慣例

不需要為每一個方法宣告HTTP動詞,可以使用WithConventionalVerbs方法:

DynamicApiControllerBuilder
    .ForAll<IApplicationService>(typeof(ChargeStationApplicationModule).Assembly, "ChargeStationAPI")
    .WithConventionalVerbs()//根據方法名使用慣例HTTP動詞,預設對於所有的action使用Post
    .Build();

這種情況,HTTP動詞是通過方法名的字首決定的:

  • Get:方法名以Get開頭。
  • Put:方法名以Put或Update開頭。
  • Delete:方法名以Delete或Remove開頭。
  • Post:方法名以Post或Create開頭。
  • 否則,Post是HTTP動詞的預設值。

我們可以通過對特定的方法使用WithVerb方法或者HTTP特性來覆蓋上述慣例。

動態Javascript代理

在Javascript中,可以經由Ajax使用動態建立的web api控制器。ABP通過為動態的web api控制器建立動態的Javascript代理簡化了這個。因此,可以在Javascript中像呼叫一個function一樣來呼叫一個動態的web api 控制器action:

 

Javascript代理是動態建立的。使用之前應該將下面動態的指令碼包括在頁面上。

<script src="~/api/AbpServiceProxies/GetAll"></script>

可以註冊done,fail,then等回撥函式。服務方法內部使用了abp.ajax。如果需要的話,它們處理錯誤並顯示錯誤資訊。

Ajax引數

可以傳遞一個自定義的ajax引數給代理方法。可以將它們作為第二個引數傳遞:

 

abp.services.tasksystem.task.createTask({
    assignedPersonId: 3,
    description: 'a new task description...'
},{ //override jQuery's ajax parameters
    async: false,
    timeout: 30000
}).done(function () {
    abp.notify.success('successfully created a task!');
});

  

單獨服務指令碼

'/api/AbpServiceProxies/GetAll'在一個檔案中生成所有的服務代理。使用'/api/AbpServiceProxies/Get?name=serviceName'也可以生成一個單獨的服務代理,只需要在頁面中包括下面的程式碼:

<script src="/api/AbpServiceProxies/Get?name=tasksystem/task" type="text/javascript"></script>

Angular支援

ABP可以作為angular服務暴露動態的api控制器。

(function() {
    angular.module('ChargeStationAPI').controller('CityListController', [
        '$scope', 'abp.services.chargeStationAPI.City',
        function($scope, cityService) {
            var vm = this;
            vm.cities = [];
            taskService.getCities({
                ProvinceCode: 1
            }).success(function(result) {
                vm.cities = result.cities;
            });
        }
    ]);
})();

我們可以使用服務的名字(包含名稱空間)注射一個服務。然後,可以作為正常的Javascript函式呼叫它的function。注意,我們註冊到了success控制程式碼上(而不是done),因為它就像在angular的$http服務中。ABP使用AngularJs的$http服務。如果

你想要傳遞$http配置,可以作為服務方法的最後一個引數傳遞一個配置物件。

要使用自動生成的服務,應該在頁面中包含需要的指令碼:

<script src="~/Abp/Framework/scripts/libs/angularjs/abp.ng.js"></script>
<script src="~/api/AbpServiceProxies/GetAll?type=angular"></script>

相關文章