<ABP framework> dynamic Web Api layer, abpapi
Document directory
Content of this section:
- Create a dynamic Web Api Controller
- ForAll Method
- Override ForAll
- Http verb
- WithVerb Method
- HTTP features
- Naming Conventions
- Api Browser
- RemoteService features
- Dynamic Javascript proxy
- AJAX Parameters
- Separate service script
- Angular Integration
- Enable/disable
- Packaging result
- About parameter binding
- FormUri and FormBody features
- DTO vs simple type
Create a dynamic Web Api Controller
This document is about Asp.net Web Api. If you are interested in Asp.net Core, you can view the Asp.net Core document.
You can automatically create an Asp.net Web Api layer for your application layer. Assume that we have an Application Service as follows:
public interface ITaskAppService : IApplicationService{ GetTasksOutput GetTasks(GetTasksInput input); void UpdateTask(UpdateTaskInput input); void CreateTask(CreateTaskInput input);}
We want to expose this service as a Web Api controller to the client. You can configure the service as a Web Api controller in one line to automatically create a Web Api controller:
Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder.For<ITaskAppService>("tasksystem/task").Build();
This is the end of the process. An api controller is created under the address "/api/services/tasksystem/task" and can be used by all method clients. This configuration should be completed in the Initialize method of your module.
ITaskAppService is an application service interface packaged with an api controller. It is not necessary for application services, but it is a convention and a recommended practice. "Tasksystem/task" is the name of this api controller and an arbitrary namespace. You should define at least one level of namespace, but you can define a deeper namespace, for example, "myCompany/myApplication/myNamespace1/myNamespace2/myServiceName ". "/Api/services" is the prefix of all dynamic Web Api controllers, so the address of this Api controller is like "/api/services/tasksystem/task ", the address of the GetTasks method will be "/api/services/tasksystem/task/getTasks", and the method name will be converted into a camper, because in the Javascript world, this is a convention.
ForAll Method
There may be a lot of application services in an application. Creating an api controller one by one is boring and easy to omit, dynamicApiControllerBuilder provides a method for creating a web api controller to call all application services at a time. For example:
Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder .ForAll<IApplicationService>(Assembly.GetAssembly(typeof(SimpleTaskSystemApplicationModule)), "tasksystem") .Build();
The ForAll method is a generic type that accepts an interface. The first parameter is an assembly, which contains the class inherited from the previously specified interface and the namespace prefix of the second service, suppose we have an Assembly that contains ITaskAppService and IPersonAppService, and the service will be: "/api/services/Tasksystem/task"And "/api/services/Tasksystem/person". For computing Service names: Service and AppService suffixes and I prefixes (interfaces) will be removed, and Service names will also be converted to the hump form. If you do not like this Convention, you can use the "WithServicename" Method to Determine the name. There is also a Where method to filter services, which is useful when you want to create api controllers for all the application services except a few.
Override ForAll
We can rewrite the configuration after the ForAll method, for example:
Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder .ForAll<IApplicationService>(Assembly.GetAssembly(typeof(SimpleTaskSystemApplicationModule)), "tasksystem") .Build();Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder .For<ITaskAppService>("tasksystem/task") .ForMethod("CreateTask").DontCreateAction().Build();
In this Code, we create a Web Api controller for all the application services in a set of programs, and then rewrite the configuration for an Independent Application Service (ITaskAppService) to ignore the CreateTask method.
ForMethod
When the ForAll method is used, we can use the ForMethods Method for better calling. For example:
Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder .ForAll<IApplicationService>(Assembly.GetExecutingAssembly(), "app") .ForMethods(builder => { if (builder.Method.IsDefined(typeof(MyIgnoreApiAttribute))) { builder.DontCreate = true; } }) .Build();
In this example, a custom feature (MyIgnoreApiAttribute) is used to check all methods, instead of creating a dynamic web api controller for methods marked with this feature.
Http verb
By default, all methods are created as POST, so a client application sends a post request to use the actions of the created web api. We can change this behavior to a different method.
WithVerbMethod
We can use WithVerb for a method, for example:
Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder .For<ITaskAppService>("tasksystem/task") .ForMethod("GetTasks").WithVerb(HttpVerb.Get) .Build();
HTTP features
In the service interface, we can add features such as HttpGet and HttpPost to the method:
public interface ITaskAppService : IApplicationService{ [HttpGet] GetTasksOutput GetTasks(GetTasksInput input); [HttpPut] void UpdateTask(UpdateTaskInput input); [HttpPost] void CreateTask(CreateTaskInput input);}
To use these features, add the nuget package of Microsoft.Asp.net. WebApi. Core in the project and reference it.
Naming Conventions
You can use the WithconvertionalVerbs method to declare an HTTP verb for each method, as shown below:
Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder .ForAll<IApplicationService>(Assembly.GetAssembly(typeof(SimpleTaskSystemApplicationModule)), "tasksystem") .WithConventionalVerbs() .Build();
In this case, determine the HTTP verb with the method name prefix:
- Get: if the method name starts with "Get.
- Put: if the method name starts with "Put" or "Update.
- Delete: if the method name starts with "Delete" or "Remove.
- Post: if the method name starts with "Post", "Create", or "Insert.
- Patch: if the method name is prefixed with "Patch.
- Otherwise, use Post as the default HTTP verb.
But we can also rewrite it using the aforementioned method.
Api Browser
By default, all dynamic Web api controllers are displayed in Api browsers (for example, Swagger). However, you can use flunet DynamicApicontrollerBuilder Api or RemoteService to change this behavior.
RemoteService features
You can use RemoeteService for any interface or method to define IsEnabled dynamic Api or IsMetadataEnabled ).
Dynamic Javascript proxy
You can use Javascript ajax to use a dynamically created web api controller, and also create a dynamic Javascript proxy for the api controller to simplify calling. Therefore, you can call the Action of a dynamic web api controller in the way that javascript calls a function:
abp.services.tasksystem.task.getTasks({ state: 1}).done(function (result) { //use result.tasks here...});
Javascript proxies are dynamically created. before using them, you should add dynamic scripts to your page:
<script src="/api/AbpServiceProxies/GetAll" type="text/javascript"></script>
The service method returns promise (view jQuery. deferred), you can register done, fail, then, and other callback functions. The service method internally uses the abp. ajax, which can handle errors and display them as needed.
AJJX Parameters
You may want to pass custom parameters to the proxy method. You can use them as the second parameter, as shown below:
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!');});
All parameters of jQuery. ajax are available here.
In addition to the standard jQuery. ajax parameters, you can add abpHandleError: false to the AJAX options to enable automatic display of error information when an error occurs.
Separate service script
"/Api/AbpServiceProxies/GetAll" generates all service proxies in one file. You can also generate a separate service proxy using "/api/AbpServiceProxies/Get? Name =ServiceName ",Then include the script in the page, as shown below:
<script src="/api/AbpServiceProxies/Get?name=tasksystem/task" type="text/javascript"></script>
Angular Integration
You can expose the dynamic api controller as an angularjs service by using the following example:
(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; }); } ]);})();
We can use its name (including the namespace) to inject a service, and then we can call its function as we call a common Javascript function. Note: we register the success Processing Program (instead of done), because it is like in angular's $ http service, if you want to pass $ httpConfiguration, You can passConfigurationObject as the last parameter of the service method.
To use the automatically generated service, you should include the necessary scripts on your page:
<script src="~/Abp/Framework/scripts/libs/angularjs/abp.ng.js"></script><script src="~/api/AbpServiceProxies/GetAll?type=angular"></script>
Enable/disable
If you use the ForAll method as stated above, you can use the RemoteService feature to disable it for a service or method, instead of a service class.
Packaging result
You can use the AjaxResponse object to encapsulate the Action return values of Dynamic Web APIs. For more information, see the ajax document. You can enable/disable packaging for each method or application service. See the following application service example:
public interface ITestAppService : IApplicationService{ [DontWrapResult] DoItOutput DoIt(DoItInput input);}
We disabled packaging for the DoIt method. This attribute should be declared in the interface, rather than the implemented class.
It is very useful if you want to better control the value returned to the client without packaging, especially when using a third-party client library that does not support the abp-standard AjaxResponse, you also need to handle the exception yourself, because the exception handling will also be disabled (the DontWrapResult feature has the WrapOnError attribute, which can enable exception handling and packaging ).
Note: The dynamic javascript proxy can understand the unwrapped results and process the results in an appropriate way.
About parameter binding
The Api controller is created at run time. Therefore, the Asp.net Web Api model is bound with parameters to bind models and parameters. For more information, see their documentation.
FormUri and FormBody features
The FormUri and FormBody features can be used in service interfaces to prioritize binding.
DTO vs simple type
We strongly recommend using Dto for application services and web api controllers, but you can use simple types (such as string, int, bool... Or nullable type, such as int ?, Bool ?...) As a service parameter, multiple simple type parameters are available, but only one complex type parameter can be used (due to Asp.net Web Api restrictions ).