本文屬于 OData 系列文章
ABP 是一個流行的 ASP. NET 開發框架,舊版的的 ABP 已經能夠非常好的支持了 OData ,并提供了對應的 OData 包,
ABP vNext 是一個重新設計的,面向微服務的框架,提供了一些非常有用的特性,包括分頁查詢等但是它并不能原生支持 OData ,我們需要自行實作,
本文的實作方式本質上為
side by side
方式,由于 ABP vNext 官方沒有對應的設計,所以你依然需要自己撰寫控制器,
本文使用 ABP CLI 6.0.3 生成的 ABP vNext 專案、Microsoft.AspNetCore.OData 8.1.2
原理
ABP vNext 有自動生成 Controller 的機制,我們的 ApplicationService,它會幫我們自動生成對應的終結點,并對外提供服務,這個程序是由 ABP 控制的,我們能修改的內容非常有限,
// TodoAppHttpApiHostModule.cs
private void ConfigureConventionalControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(TodoAppApplicationModule).Assembly, options =>
{
//// 移除自動生成的控制器
//options.ControllerTypes.Remove(typeof(TodoAppController));
//options.RootPath = "abp";
//// 添加手動實作的控制器
//options.ControllerTypes.Add(typeof(TodoAppImplController));
});
});
}
它依照慣例生成,我們可以對型別進行增加或者減少,但是不能控制生成的行為,而 OData 的控制器,需要我們從 ODataController
繼承,或者使用 [EnableQuery]
,因此我們需要阻止自動生成控制器,自己實作對應的邏輯,
有了對應的控制器,就需要在應用程式模塊中配置 OData 的路由、EDM 等資訊,并且不要和原有的控制器路由沖突,
實作
首先禁用自動生成控制器功能,
//TodoAppService.cs
[RemoteService(false)]
public class TodoAppService : ApplicationService, ITodoAppService
{
private readonly IRepository<TodoItem, Guid> _todoItemRepository;
public TodoAppService(IRepository<TodoItem, Guid> todoItemRepository)
{
_todoItemRepository = todoItemRepository;
}
public async Task<IQueryable<TodoItemDto>> GetListAsync()
{
var items = await _todoItemRepository.GetQueryableAsync();
return items
.Select(item => new TodoItemDto
{
Id = item.Id,
Text = item.Text
})
}
}
將應用服務打上 [RemoteService(false)]
標記,服務就不會自動生成控制器,接下來在 HttpApi
專案中新建一個與服務同名的控制器,由于 ABP 專案自動生成了控制器抽象類模板,我們繼承并實作它即可,
/* Inherit your controllers from this class.
*/
public abstract class TodoAppController : AbpControllerBase
{
protected TodoAppController()
{
LocalizationResource = typeof(TodoAppResource);
}
}
public class TodoController : TodoAppController
{
private readonly ITodoAppService todoAppService;
public TodoController(ITodoAppService todoAppService)
:base()
{
this.todoAppService = todoAppService;
}
[EnableQuery]
public async Task<IEnumerable<TodoItemDto>> GetAsync()
{
var result = await todoAppService.GetListAsync();
return result.AsQueryable();
}
}
注入對應的服務,實作自己的邏輯,如果需要利用 EF Core 的查詢功能,請使用 IQueryable
傳遞資料到控制器層,然后配置 OData :
//TodoAppHttpApiHostModule.cs
private IEdmModel GetEdmModels()
{
var builder = new ODataConventionModelBuilder();
var device = builder.EntitySet<TodoItemDto>("Todo").EntityType.HasKey(w => w.Id);
return builder.GetEdmModel();
}
記得在 PreConfigureServices
中加上呼叫,
//TodoAppHttpApiHostModule.cs
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictBuilder>(builder =>
{
builder.AddValidation(options =>
{
options.AddAudiences("TodoApp");
options.UseLocalServer();
options.UseAspNetCore();
});
});
// 加上這個呼叫
PreConfigure<IMvcBuilder>(builder =>
{
builder.AddOData(opt =>
{
opt.RouteOptions.EnablePropertyNameCaseInsensitive = true;
opt.RouteOptions.EnableQualifiedOperationCall = false;
opt.Expand().Filter().Count().OrderBy().Filter().SetMaxTop(30);
opt.AddRouteComponents("api/app/", GetEdmModels());
});
});
}
運行后,大功告成:
總結
本文實作了 OData 在 ABP vNext 中的使用,請注意,本方案只是一個 Demo,應用到生產前請自行評估風險,期待 ABP 團隊在未來正式支持 OData
吧,本文的完整代碼在 github,運行前可能需要先執行資料庫初始化,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/552596.html
標籤:ASP.NET
上一篇:VB.NET 截取字串
下一篇:返回列表