ABP框架 - 我的第一個Web API
上一篇我們已經對ABP是什麽,能做什麽、有了一個印象。那麽接下來我們將動手使用ABP框架快速開發一個API,你將會發現使用ABP框架有多麽便利,會實實在在感受到它的魅力。
環境要求
- Visual Studio 2017
- SQL Server
- .Net Core SDK
創建應用程序
我們使用ABP模板來創建應用程序,訪問http://www.aspnetboilerplate.com/Templates,你將會看到如下頁面
- 參照上圖所示的選項選擇
- 輸入項目名稱,我這裏是"AbpTraining"
- 輸入驗證碼
點擊“創建項目”, 接著我們就會從ABP模板網站上獲得一個項目源碼的壓縮包AbpTraining.zip. 解壓縮AbpTraining.zip就會獲得初始項目的源代碼。
運行應用程序
- 進入解壓目錄,點擊aspnet-core/AbpTraining.sln,打開解決方案
- 在本地Sql Server數據庫實例中創建數據庫AbpTrainingDb
找到AbpTraining.Web.Host/appsettings.json, 根據自己本地環境修改數據庫連接(ConnectionStrings)
"ConnectionStrings": { "Default": "Server=localhost; Database=AbpTrainingDb; Trusted_Connection=True;" }
- 使用數據庫遷移腳本創建初始數據庫
- 在Visual Studio中選擇工具-> Nuget包管理器-> 包管理器控制臺
- 設置AbpTraining.Web.Host為啟動項目
- 在包管理器控制臺中設置AbpTraining.EntityFrameworkCore為默認項目
- 包管理器控制臺中執行命令 update-database -verbos, 等待命令成功執行完成,就完成了數據庫的同步
運行AbpTraining.Web.Host, 將會出現swagger的api頁面,程序運行成功
我的第一個API
1. API功能
功能: 根據商品名查詢商品信息
2. 創建商品實體
AbpTraining.Core\Products\Product.cs
using Abp.Domain.Entities.Auditing; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace AbpTraining.Products { //可以顯示的指定表名,不指定默認是實體名+s [Table("Product")] public class Product : FullAuditedEntity<long> { [Required] [StringLength(128)] public string Name { get; set; } public decimal Price { get; set; } } }
- [Table("Product")] 顯示指定實體對應的表名,如果不指定,默認用類名+s
- FullAuditedEntity
- [Required]指定字段是必填的, 不指定則字段可為空
- [StringLength(128)]指定字段最大長度為128
3. 創建商品領域DomainService
AbpTraining.Core\Products\ProductDomainService.cs
using Abp.Domain.Repositories;
using Abp.Domain.Services;
using System.Threading.Tasks;
using System.Linq;
using Abp.UI;
using Microsoft.EntityFrameworkCore;
namespace AbpTraining.Products
{
public class ProductDomainService : DomainService
{
private readonly IRepository<Product, long> _productRepository;
public ProductDomainService(IRepository<Product, long> productRepository)
{
_productRepository = productRepository;
}
public async Task<Product> GetProductByName(string name)
{
var query = from p in _productRepository.GetAll()
where p.Name == name
select p;
var product = await query.FirstOrDefaultAsync();
if (product == null)
{
throw new UserFriendlyException($"商品({name})不存在");
}
if (product.Price < 0)
{
throw new UserFriendlyException($"商品({name})的價格小於0,請檢查");
}
return product;
}
}
}
- 領域服務要繼承DomainService
- _productRepository數據倉儲直接依賴註入
- 使用async await一異步編程模型
- 使用Linq To Sql查詢數據
- 如果要返回業務錯誤消息給客戶端,要使用UserFriendlyException
4. 創建商品ApplicationService
4.1 定義Dto
AbpTraining.Application\Products\Dto\ProductDto
using Abp.AutoMapper;
namespace AbpTraining.Products.Dto
{
[AutoMapFrom(typeof(Product))]
public class ProductDto
{
public string Name { get; set; }
public decimal Price { get; set; }
}
}
- AutoMapFrom特性指明從哪一個類可以自動映射到當前類,這樣就不用手動的去做實體時間的轉換
AbpTraining.Application\Products\Dto\GetProductByNameInput
using System.ComponentModel.DataAnnotations;
namespace AbpTraining.Products.Dto
{
public class GetProductByNameInput
{
[Required]
public string Name { get; set; }
}
}
- [Required] - input對象中有此特性,ABP會自動對request的這個字段做必填驗證
Mysoft.RDC.Application\Products\Dto\GetProductByNameOutput
namespace AbpTraining.Products.Dto
{
public class GetProductByNameOutput : ProductDto
{
}
}
4.2 定義ApplicationService接口
AbpTraining.Application\Products\IProductAppService.cs
using Abp.Application.Services;
using AbpTraining.Products.Dto;
using System.Threading.Tasks;
namespace AbpTraining.Products
{
public interface IProductAppService : IApplicationService
{
Task<GetProductByNameOutput> GetProductByName(GetProductByNameInput input);
}
}
- 應用服務接口要繼承IApplicationService
4.3 商品ApplicationService實現
AbpTraining.Application\Products\ProductAppService.cs
using System.Threading.Tasks;
namespace AbpTraining.Products.Dto
{
public class ProductAppService : AbpTrainingAppServiceBase, IProductAppService
{
private readonly ProductDomainService _productDomainService;
public ProductAppService(ProductDomainService productDomainService)
{
_productDomainService = productDomainService;
}
public async Task<GetProductByNameOutput> GetProductByName(GetProductByNameInput input)
{
//1.將input dto轉換為domain obj
//2.調用doamin service
var item = await _productDomainService.GetProductByName(input.Name);
//call other doamin serivce
//3.將domain obj轉換為output dto
var output = ObjectMapper.Map<GetProductByNameOutput>(item);
return output;
}
}
}
- 應用服務實現要繼承AbpTrainingAppServiceBase
5. 數據庫
5.1 數據庫實體映射
在AbpTraining.EntityFrameworkCore\EntityFrameworkCore\AbpTrainingDbContext.cs 中添加如下代碼片段
public DbSet<Product> Products { get; set; }
5.2 生成migration文件
在包管理器控制臺中,執行如下命令,生成遷移腳本文件
Add-Migration AddProduct -Verbos
- 執行完成後,會在在AbpTraining.EntityFrameworkCore\Migrations下看到新生成的腳本文件,我這次生成的文件名是20180405043514_AddProduct.cs (會有一個時間戳前綴,每次會不一樣)
5.3 更新數據庫
在包管理器控制臺中,執行如下命令,將新的實體同步數據庫
Update-Database -Verbos
- 執行完成後,你會在數據庫看到一個新表Product
6. 運行服務、測試
設置AbpTraining.Web.Host為啟動項目,直接在Visual Studio中運行, 在Swagger的API列表中找到/api/services/app/Product/GetProductByName 即可以開始測試。
到此,我們的第一個API就成功的完成了.
ABP框架 - 我的第一個Web API