返回总目录

本篇目录

构建动态Web API控制器

ABP可以自动地为应用层生成Web API 层。比如说我们有一个应用层如下所示:

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

我们想把这个服务作为Web API控制器暴露给客户端。ABP只需要一行配置就可以为该应用服务创建一个Web API控制器:

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

OK了!在地址为'/api/services/tasksystem/task'的地方就创建了一个API控制器,现在客户端可以使用该应用服务的所有方法。这个配置应该在模块的Initlize方法中完成。

我们使用一个API控制器封装的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中惯例遵循 camelCase规则,所以方法名都转成了camelCase格式。

ForAll 方法

在应用服务层可能会有很多的应用服务,如果要为这些应用服务都构建API控制器的话,一个一个地构建简直是费时费力的事情。没关系,ABP中的DynamicApiControllerBuilder提供了一个为所有应用服务构建Web API控制器的方法,这样我们只需要调用一次就行了。例如:

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

ForAll方法是接收接口类型的泛型方法。第一个参数是一个程序集,该程序集中含有派生自给定接口的类。最后一个参数是服务前缀的命名空间。比如说我们在给定的程序集中有ITaskAppService和IPersonAppService,对于这个配置的话,服务地址将会是 '/api/services/tasksystem/task' 和 '/api/services/tasksystem/person'。计算服务名称的方法是:移除Service或者AppService后缀,以及I前缀(对于接口来说)。此外,服务名称会转成camel Case(驼峰命名)的格式。如果你不喜欢这种转换,那么使用'WithServiceName'来决定服务发名称。此外,还有一个过滤服务的Where方法。除了个别应用服务之外,这个方法在你为其他所有的应用服务构建API控制器时很有用。

重写ForAll 方法

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

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

在上面的代码中,我们为一个程序集中所有的应用服务构建了动态的Web API控制器。然后又为一个应用服务(ITaskAppService)重写了配置,目的是忽略该应用服务中的CreateTask方法。

Http动词

默认情况下,创建的方法都只能POST请求。我们也可以使用不同的方法来改变这种行为。

WithVerb方法

我们可以为一个方法使用WithVerb,像下面那样:

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.AspNet.WebApi.CoreNuget包的引用。

命名规范

不用为每个方法都声明HTTP动词,你可以使用如下所示的WithConventionalVerbs方法:

DynamicApiControllerBuilder
.ForAll<IApplicationService>(Assembly.GetAssembly(typeof(SimpleTaskSystemApplicationModule)), "tasksystem")
.WithConventionalVerbs()
.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:

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

Javascript代理是动态创建的。使用之前应该将下面动态的脚本包括在页面上。

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

服务方法返回了promise(查看jQuery.Deferred)。可以在返回的promise后面继续注册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!');
});

jQuery.ajax的所有参数在这里都是有效的。

单一服务脚本

'/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: 0
}).success(function(result) {
vm.tasks = result.tasks;
});
}
]);
})();

我们可以使用服务的名字(包含命名空间)注射一个服务。然后,可以作为正常的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>

Durandal支持

ABP可以在一个Durandal应用的模块中注入服务代理。看下面的viewmodel:

define(['service!tasksystem/task'],
function (taskService) {
//taskService can be used here
});

ABP配置Durandal(实际上是Require.js)来理解这个'service!'前缀,然后注入合适的javascript服务代理。

返回结果封装

ABP通过 AjaxResponse封装了动态Web API的action的返回值。查看《Ajax文档》获取更多关于封装的信息。你可以为每个应用服务或者每个方法开启或者禁用封装。看下面这个应用服务的例子:

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

这里我们为DoIt方法禁用了封装。这个特性应该为接口声明而不是实现类。

如果你想更好地控制客户端的返回值,那么不封装返回的结果可能是很有用的。特别地,当使用不能和ABP标准的AjaxResponse协作的第三方客户端库时,可能需要禁用封装。这种情况下,你要自己处理异常。

注意:动态javascript代理可以理解返回的结果是否封装和运行正常。

关于参数绑定

ABP在运行时创建了API控制器。因此,ASP.NET Web API的模型和参数绑定可以用于绑定模型和参数。

FromUri和FromBody特性

为了在绑定时进行高级控制,可以在服务接口上使用FromUri和FromBody特性。

DTOs vs原始类型

我们强烈建议为应用服务和Web API控制器的方法使用DTO作为参数类型,但是你也可以使用原始类型(如string,int,bool或者可空的类型如int?,bool?)作为参数类型。虽然可以在应用服务中使用不止一个参数,但是最好用一个复杂的类型将多个参数整合起来,否则客户端就不会生成动态代理服务。在日志记录中就会看到如下图所示的错误:

动态Web API层的更多相关文章

  1. ABP框架 - 动态Web Api层

    文档目录 本节内容: 创建动态Web Api控制器 ForAll 方法 重写 ForAll ForMethods Http 动词 WithVerb 方法 HTTP 特性 命名约定 Api 浏览器 Re ...

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

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

  3. ABP官方文档翻译 5.2 动态We API层

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

  4. 【asp.net core】实现动态 Web API

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

  5. [ABP框架]动态web Api的拦截用法。

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

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

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

  7. 动态We API(ABP官方文档翻译)

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

  8. [译]ABP框架使用AngularJs,ASP.NET MVC,Web API和EntityFramework构建N层架构的SPA应用程序

    本文转自:http://www.skcode.cn/archives/281 本文演示ABP框架如何使用AngularJs,ASP.NET MVC,Web API 和EntityFramework构建 ...

  9. ABP示例程序-使用AngularJs,ASP.NET MVC,Web API和EntityFramework创建N层的单页面Web应用

    本片文章翻译自ABP在CodeProject上的一个简单示例程序,网站上的程序是用ABP之前的版本创建的,模板创建界面及工程文档有所改变,本文基于最新的模板创建.通过这个简单的示例可以对ABP有个更深 ...

随机推荐

  1. configuration error-could not load file or assembly crystaldecisions.reportappserver.clientdoc

    IIS启动网站后报错: configuration error Could not load file or assembly 'crystaldecisions.reportappserver.cl ...

  2. 7 Container With Most Water_Leetcode

    Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). ...

  3. 微信小程序资料

    作者:初雪链接:https://www.zhihu.com/question/50907897/answer/128494332来源:知乎著作权归作者所有,转载请联系作者获得授权. 1:下载开发者工具 ...

  4. LOL(英雄联盟)提示不支持虚拟机登录,解决方法

    搜索虚拟系统下的存放文件索 .VMX 会出现带有.VMX 的文件(比如Windows 7.vmx)用记事本打开在最后面回车再加入一行:monitor_control.restrict_backdoor ...

  5. Good Bye 2016

    A - New Year and Hurry (water) #include <bits/stdc++.h> using namespace std; int main() { ]; ; ...

  6. Unable to convert MySQL date/time value to System.DateTime 错误

    C#读取MySql时,如果存在字段类型为date/datetime时的可能会出现以下问题“Unable to convert MySQL date/time value to System.DateT ...

  7. dedecms为文档页增加动态点击

    加上 <script src="{dede:field name='phpurl'/}/count.php?view=yes&aid={dede:field name='id' ...

  8. IE11 上的3个bug

    1.IE 11在popstate上无法正常使用,所以,需要使用老方法hashchange.有一个叫History.js的library,是可以解决这个问题.但如果url在"#"后跟 ...

  9. jQuery中prop() , attr() ,css() 的区别

    1.  HTML属性是指页面标记中放在引号中的值,而DOM属性则是指通过JavaScript能够存取的值. (1)在jQuery中,prop()是操作DOM属性,attr()是操作HTML属性. HT ...

  10. linux下QT程序输出乱码解决方法

    参考文章:http://blog.csdn.net/jiang1013nan/article/details/6667871 http://my.oschina.net/zjlaobusi/blog/ ...