ABP框架 - 动态Web Api层

时间:2022-09-14 10:57:35

文档目录

本节内容:

创建动态Web Api 控制器

这个文档是关于Asp.net Web Api的,如果你对Asp.net Core感兴趣,可查看Asp.net Core文档。

ABP可为你的应用层自动创建Asp.net Web Api层,假设我们有一个如下所示的应用服务

public interface ITaskAppService : IApplicationService
{
GetTasksOutput GetTasks(GetTasksInput input);
void UpdateTask(UpdateTaskInput input);
void CreateTask(CreateTaskInput input);
}

我们想把这个服务作为一个Web Api控制器暴露给客户端,ABP可通过一行配置为这个应用服务,自动动态创建一个Web Api控制器:

Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder.For<ITaskAppService>("tasksystem/task").Build(); 

这就完事了。一个api控制器被创建在地址“/api/services/tasksystem/task”下,所有的方法客户端都可以使用。这个配置应当在你的模块Initialize方法里完成。

ITaskAppService是想要用一个api控制器来包装的应用服务接口,它对于应用服务不是必需,但这是一种约定和建议的做法。“tasksystem/task”是这个api控制器的名称和一个任意的命名空间,你应当定义至少一级的命名空间,但你可以定义更深的命名空间,如“myCompany/myApplication/myNamespace1/myNamespace2/myServiceName”。“/api/services”是所有动态Web Api控制器的前缀,所以这个Api控制器的地址形如“/api/services/tasksystem/task”,GetTasks方法的地址将是“/api/services/tasksystem/task/getTasks”,方法名被转换成驼峰形式,因为在Javascript世界里就是这样约定俗成。

ForAll 方法

在一个应用里可能有很多应用服务,一个一个地创建api控制器会是一件乏味并易遗漏的工作,DynamicApiControllerBuilder提供了一个为所有应用服务创建web api控制器一次调用的方法,例如:

Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder
.ForAll<IApplicationService>(Assembly.GetAssembly(typeof(SimpleTaskSystemApplicationModule)), "tasksystem")
.Build();

ForAll方法是一个接受一个接口的泛型,第一个参数是程序集,它包含继承自前面所指定接口的类,第二个服务的命名空间前缀,假设我们有一个包含ITaskAppService和IPersonAppService的程序集,应用上述配置,服务将是:“/api/services/tasksystem/task”和“/api/services/tasksystem/person”。为计算服务名:Service和AppService后缀和I前缀(接口)会被移除,服务名也被转换成驼峰形式。如果你不喜欢这种约定,有一个“WithServicename”方法可以确定命名。还有一个Where方法可过滤服务,这在你想为除了少数几个外的所有应用服务创建api控制器的时候,非常有用。

重写 ForAll

我们可在ForAll方法之后,重写配置,例如:

Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder
.ForAll<IApplicationService>(Assembly.GetAssembly(typeof(SimpleTaskSystemApplicationModule)), "tasksystem")
.Build(); Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder
.For<ITaskAppService>("tasksystem/task")
.ForMethod("CreateTask").DontCreateAction().Build();

这段代码里,我们为一个程序集里的所有应用服务创建Web Api控制器,然后为一个单独的应用服务(ITaskAppService)重写配置,忽略CreateTask方法。

ForMethod

当使用ForAll方法时,我们可用ForMethods方法进行更好的调用 ,例如:

Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder
.ForAll<IApplicationService>(Assembly.GetExecutingAssembly(), "app")
.ForMethods(builder =>
{
if (builder.Method.IsDefined(typeof(MyIgnoreApiAttribute)))
{
builder.DontCreate = true;
}
})
.Build();

在这个示例里,用一个自定义特性(MyIgnoreApiAttribute)来检查所有方法,不为标记了这个特性的方法创建动态web api控制器。

Http 动词

默认地,所有方法被创建成POST,所以一个客户端应用发送post请求来使用已创建的web api的actions。我们可以把这种行为修改成不同的方式。

WithVerbMethod

我们可以为一个方法使用WithVerb,如:

Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder
.For<ITaskAppService>("tasksystem/task")
.ForMethod("GetTasks").WithVerb(HttpVerb.Get)
.Build();

HTTP 特性

在服务接口里,我们可以给方法添加HttpGet、HttpPost等特性:

public interface ITaskAppService : IApplicationService
{
[HttpGet]
GetTasksOutput GetTasks(GetTasksInput input); [HttpPut]
void UpdateTask(UpdateTaskInput input); [HttpPost]
void CreateTask(CreateTaskInput input);
}

为使用这些特性,应该在项目里添加Microsoft.Asp.net.WebApi.Core的nuget包,并引用它。

命名约定

你可以使用WithconvertionalVerbs方法,代替为每个方法声明HTTP动词,如下所示:

Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder
.ForAll<IApplicationService>(Assembly.GetAssembly(typeof(SimpleTaskSystemApplicationModule)), "tasksystem")
.WithConventionalVerbs()
.Build();

这种情况下,以方法名的前缀确定HTTP动词:

  • Get:如果方法名以“Get”打头。
  • Put:如果方法名以“Put”或“Update”打头。
  • Delete: 如果方法名以“Delete”或“Remove”打头。
  • Post:如果方法名以“Post”或“Create”或“Insert”打头。
  • Patch:如果方法名以“Patch”打头。
  • 否则:以Post作为默认的HTTP动词。

但我们也可以用前面据说的方法重写它。

Api 浏览器

默认情况下,所有的动态Web api 控制器都会显示在Api浏览器里(例如:Swagger),不过你可以通过flunet DynamicApicontrollerBuilder Api或RemoteService特性来改变这种行为。

RemoteService 特性

你可为任何的接口或方法使用RemoeteService来定义启用/禁用(IsEnabled)动态Api或Api浏览器设置(IsMetadataEnabled)。

动态Javascript代理

你可以通过Javascript的ajax使用动态创建的web api控制器,ABP也通过为api控制器创建动态Javascript代理来简化调用。所以,你可以用像javascript调用函数那样的方式来调用一个动态web api控制器的Action:

abp.services.tasksystem.task.getTasks({
state:
}).done(function (result) {
//use result.tasks here...
});

Javascript的代理是动态创建的,在使用之前,你应当在你的页面里添加动态脚本:

<script src="/api/AbpServiceProxies/GetAll" type="text/javascript"></script>

服务方法返回promise(查看jQuery.Deferred),你可以注册done, fail, then等回调函数,服务方法内部使用abp.ajax,它们在需要的时候处理错误并显示。

AJJX 参数

你可能想传递自定义参数给代理方法,你可以把它们作为第二个参数,如下所示:

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

jQuery.ajax的所有参数在此都是可用的。

除了标准的jQuery.ajax参数外,你可以给AJAX选项添加abpHandleError:false,以便禁用出错时自动显示出错信息。

单独服务脚本

“/api/AbpServiceProxies/GetAll”在一个文件里生成所有服务代理。你也可以生成单独的服务代理,使用“/api/AbpServiceProxies/Get?name=serviceName”,然后在页面里包含这个脚本 ,如下所示:

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

Angular 集成

ABP可以把动态api控制器暴露成一个angularjs服务,假设有个如下所示的例子:

(function() {
angular.module('app').controller('TaskListController', [
'$scope', 'abp.services.tasksystem.task',
function($scope, taskService) {
var vm = this;
vm.tasks = [];
taskService.getTasks({
state:
}).success(function(result) {
vm.tasks = result.tasks;
});
}
]);
})();

我们可以使用它的名称(包含命名空间)注入一个service,然后就可以如调用常规的Javascript函数那样调用它的函数,注意:我们注册success处理程序(代替done),因为这就像在angular的$http服务里,ABP使用Angularjs的$http服务,如果你想传递$http的configuration,你可以传递一个configuration对象,作为服务方法的最后一个参数。

为了使用自动生成的服务,你应该在你的页面里包含必要的脚本:

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

启用/禁用

如果你上面陈述的那样,使用ForAll方法,你可以为一个服务或方法,使用RemoteService特性来禁用它,要在服务接口上使用这个特性,而不是服务类上。

包装结果

ABP通过AjaxResponse对象包装动态Web Api的Action返回值,更多信息查看ajax文档。你可以为每个方法或每个应用服务启用/禁用包装,请看如下应用服务示例:

public interface ITestAppService : IApplicationService
{
[DontWrapResult]
DoItOutput DoIt(DoItInput input);
}

我们为DoIt方法禁用了包装,这个属性要声明在接口里,而不是实现的类里。

如果你想更好地控制返回给客户端的值,不包装是非常有用的,尤其,在使用不支持ABP标准的AjaxResponse的第三方客户端库时,这种情况下,你也需要自己处理异常,因为异常处理也会被禁用(DontWrapResult特性拥有WrapOnError属性,它能启用异常的处理和包装)。

注意:动态javascript代理可以理解没有包装的结果,并用适应的方式处理结果。

关于参数绑定

ABP在运行时创建Api控制器,所以,Asp.net Web Api的模型与参数绑定用来绑定模型和参数,更多信息你可以阅读它们的文档

FormUri 和 FormBody 特性

FormUri和FormBody特性可用在服务接口里,优先控制绑定。

DTO vs 简单类型

我们强烈建议为应用服务和web api控制器的方法使用Dto,但你可以使用简单类型(如string,int,bool...或nullable类型,如int?,bool?...)作为服务参数,可用多个简单类型参数,但只能用一个复杂类型参数(由于Asp.net Web Api的限制)。

kid1412附:英文原文:http://www.aspnetboilerplate.com/Pages/Documents/Dynamic-Web-API

ABP框架 - 动态Web Api层的更多相关文章

  1. DDD开发框架ABP之动态Web API层

    建立动态Web API 控制器 ASP.NET Boilerplate 能够自动为您的应用层产生Web API层.比如说我们有如下的一个应用服务: public interface ITaskAppS ...

  2. &lbrack;ABP框架&rsqb;动态web Api的拦截用法。

    先进行配置 首先这种需求,一般发生在APP端,我们给APP,不会给所有项目系统的接口给他们用.我们系统有200个接口,但是APP的需求只会用20个.那么这个需求也就应运而生了. 以上为API文件夹中为 ...

  3. 动态Web API层

    返回总目录 本篇目录 构建动态Web API控制器 ForAll 方法 重写ForAll 方法 Http动词 动态Javascript代理 Ajax参数 单一服务脚本 Angular支持 Durand ...

  4. ABP官方文档翻译 5&period;2 动态We API层

    动态Web APID层 创建动态Web API控制器 ForAll方法 重写ForAll ForMethods Http动词 WithVerb方法 HTTP特性 命名约定 API管理器 RemoteS ...

  5. 【asp&period;net core】实现动态 Web API

    序言: 远程工作已经一个月了,最近也算是比较闲,每天早上起床打个卡,快速弄完当天要做的工作之后就快乐摸鱼去了.之前在用 ABP 框架(旧版)的时候就觉得应用服务层写起来真的爽,为什么实现了个 IApp ...

  6. ABP文档 - Web Api 控制器

    文档目录 本节内容: 简介 AbpApiController 基类 本地化 其它 过滤 审计日志 授权 防伪造过滤 工作单元 结果包装和异常处理 结果缓存 验证 模块绑定器 简介 通过Abp.Web. ...

  7. ASP。NET Core Blazor CRUD使用实体框架和Web API

    下载source code - 1.7 MB 介绍 *请查看我的Youtube视频链接来学习ASP.NET Core Blazor CRUD使用实体框架和Web API. 在本文中,我们将了解如何为A ...

  8. 手工搭建ABP框架&lpar;1&rpar; - Web项目

    为了防止不提供原网址的转载,特在这里加上原文链接: http://www.cnblogs.com/skabyy/p/7295533.html ABP是 ASP.NET Boilerplate Proj ...

  9. 动态We API层(动态生成js)

    ABP动态webapi前端怎么调用? 研究abp项目时,页面js文件中一直不明白abp.services... 是从哪里来的 在调试SimpleTaskSystem的AngularJs demo时,一 ...

随机推荐

  1. kafka的一些认识

    原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com   近来无事研究了一下kafka,并且用golang连接kafka做了producer和consumer的简单测试 ...

  2. AngularJS Best Practices&colon; pretty urls

    By default, AngularJS will route URLs with a hashtag. For example: http://example.com/ http://exampl ...

  3. IE9下Coolite&period;Ext出现createContextualFragment错误

    解决Ext在IE9上报错“createContextualFragment”,只需要在使用Coolite.Ext页面加入如下代码即可: if ((typeof Range !== "unde ...

  4. C&plus;&plus;中如何按照map中的value来进行排序

    sort函数无法对map进行排序,网上的方法一般是通过将map转为vector后,再来使用sort进行排序. 如下, 比较函数 bool cmp(const pair<int,int> & ...

  5. C&num;控件之:进度条(ProgressBar)

    一.重绘进度条 public class CustomProgressBar:ProgressBar { public CustomProgressBar() { this.SetStyle(Cont ...

  6. libgdx学习记录21——Box2d物理引擎之碰撞Contact、冲量Impulse、关节Joint

    Box2d中,物体可以接受力(Force).冲量(Impulse)和扭矩(Torque).这些物理元素都能改变物体的运动形式,并且默认都会唤醒物体,当然只是针对动态物体. 力是一个持久的效果,通过Bo ...

  7. PHP的extension&lowbar;dir设置问题

    PHP安装时,extension_dir的路径要设成绝对路径:extension_dir = "D:/Tools/php-7.0.5/ext", 不然如果设成extension_d ...

  8. C&num; - 反射与编译

    编译 首先了解下,如何区分编译生成的 .dll的版本方法1:ILSpy反编译工具 通过 assembly属性,release版本没有或仅有如下一种属性 [assembly: Debuggable(De ...

  9. linux常用的一些访问目录

    救命三键(Ctrl+Alt+Delete)  /var/log     如果是网络服务的问题时,请到 这个目录里头去查阅一下 log file (登录档): /etc/rc.local    修改挂载 ...

  10. &lbrack;Selenium&rsqb;点击下拉框之后,从下拉列表选择元素进行点击很容易失败

    点击下拉框之后,下拉列表会显示出来,但是有时候下拉列表会很快就消失掉,导致后面选择元素的时候会失败. 像这种情况,需要将鼠标移动到下拉列表上,使下拉列表维持显示,然后才选择元素进行点击. 将鼠标移动到 ...