構建Web API服務


返回總目錄《一步一步使用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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM