Support forum for ASP.NET Zero (https://aspnetzero.com/).
User avatar
By jumpball
#18090 Hi

Is it possible (in Angular & ASP.NET Core project) to change AppService url for next API version
For example
/api/v2/Person/GetAllPersons
or
/api/services/v2/Person/GetAllPersons

instead of
/api/services/app/Person/GetAllPersons
By ismcagdas
#18159 Hi,

If you want to use both versions
Code: Select all/api/services/app/Person/GetAllPersons

and
Code: Select all/api/v2/Person/GetAllPersons

AspNet Zero does not offer a solution for this.

The library we used https://github.com/domaindrivendev/Swashbuckle supports api versioning, you can easily change the url as you like if you only want to use single api url.

For supporting multiple api urls at the same time, you have to handle it on your own :).

Thanks.
User avatar
By jumpball
#18167 Thanks,

Where is this part of path defined
/api/services/app

In ABP?
If I want to use single version but /api/v2
How can I redefine it?
User avatar
By jumpball
#18207 Hi,

Unfortunately I stopped at the last step
Could you help me
I'll describe what I did

1. As described hear https://aspnetzero.com/Documents/Develo ... ep-Angular
it was created entity Region, RegionListDto, IRegionAppService, RegionAppService, table Region in DB ang this table was filled by test regions
Method GET /api/services/app/Region/GetRegions work good

2. Then it was created project MyApp.Api.V1
RegionListDto, IRegionAppService, RegionAppService was moved to this project
Namespase of RegionAppService changed from MyApp.Regions to MyApp.Regions.V1

3. Added class MyAppApiV1Module : AbpModule in project MyApp.Api.V1

4. In project HbOnline.Web.Host:
4.1 To PreInitialize of HbOnlineWebHostModule added line
Configuration.Modules.AbpAspNetCore().CreateControllersForAppServices(typeof(MyAppApiV1Module).Assembly, moduleName: "v1", useConventionalHttpVerbs: true);

4.2 In Startup.cs code inside services.AddSwaggerGen added line
options.SwaggerDoc("v1", new Info { Title = MyApp API v1", Version = "v1" });

and options.DocInclusionPredicate((docName, description) => true
changed to
options.DocInclusionPredicate((docName, description) => {
return description.GroupName == docName;
});

Added
services.AddMvc(c =>
c.Conventions.Add(new ApiExplorerGroupPerVersionConvention())
);

and inside
app.UseSwaggerUI(options =>
line inserted
options.SwaggerEndpoint("/swagger/v1/swagger.json", "MyApp API v1");

4.3 Added class
public class ApiExplorerGroupPerVersionConvention : IControllerModelConvention
{
var controllerNamespace = controller.ControllerType.Namespace; // e.g. "Controllers.V1"
var apiVersion = controllerNamespace.Split('.').Last().ToLower();
controller.ApiExplorer.GroupName = apiVersion == "v1" ? "v1" :"app";
}

5. After successefully start of server project we can see 2 version of API on swagger page
Under MyApp API v1 only 1 controller and 1 GET method
Region
GET /api/services/v1/Region/GetRegions

But after press Try it out! I've got Response code 500
Response Body
{
"result": null,
"targetUrl": null,
"success": false,
"error": {
"code": 0,
"message": "An internal error occurred while executing the request!",
"details": null,
"validationErrors": null
},
"unAuthorizedRequest": false,
"__abp": true
}

Probably problem with routing:
Request really sended to localhost:22742/api/services/v1/Region/GetRegions
But it can not find action of controller

Other requests work exelent

What have I missed?
By ismcagdas
#18223 Hi,

Have you checked the error logs ?
There must be a Logs.txt file under your web project, it should contain detailed error message.
It might help to understand problem.

Thanks.
User avatar
By jumpball
#18235 DEBUG 2017-05-16 11:24:13,690 [10 ] NetCore.StaticFiles.StaticFileMiddleware - The request path /api/services/v1/Region/GetRegions does not match a supported file type
DEBUG 2017-05-16 11:24:13,690 [10 ] osoft.AspNetCore.Routing.Tree.TreeRouter - Request successfully matched the route with name '(null)' and template 'api/services/v1/Region/GetRegions'.
DEBUG 2017-05-16 11:24:13,702 [10 ] ore.Mvc.Internal.ControllerActionInvoker - Executing action HbOnline.HbDirectory.Regions.V1.RegionAppService.GetRegions (HbOnline.Api.V1)
ERROR 2017-05-16 11:24:13,706 [10 ] Mvc.ExceptionHandling.AbpExceptionFilter - No component for supporting the service HbOnline.HbDirectory.Regions.V1.RegionAppService was found
Castle.MicroKernel.ComponentNotFoundException: No component for supporting the service HbOnline.HbDirectory.Regions.V1.RegionAppService was found
в Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
в Castle.MicroKernel.DefaultKernel.Resolve(Type service, IDictionary arguments)
в Castle.Windsor.WindsorContainer.Resolve(Type service)
в Castle.Windsor.MsDependencyInjection.ScopedWindsorServiceProvider.ResolveInstanceOrNull(Type serviceType, Boolean isOptional)
в Castle.Windsor.MsDependencyInjection.ScopedWindsorServiceProvider.GetServiceInternal(Type serviceType, Boolean isOptional)
в Castle.Windsor.MsDependencyInjection.ScopedWindsorServiceProvider.GetRequiredService(Type serviceType)
в Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
в Microsoft.AspNetCore.Mvc.Controllers.ServiceBasedControllerActivator.Create(ControllerContext actionContext)
в Microsoft.AspNetCore.Mvc.Controllers.DefaultControllerFactory.CreateController(ControllerContext context)
в Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
в Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()
DEBUG 2017-05-16 11:24:14,378 [10 ] ore.Mvc.Internal.ControllerActionInvoker - Request was short circuited at exception filter 'Abp.AspNetCore.Mvc.ExceptionHandling.AbpExceptionFilter'.
DEBUG 2017-05-16 11:24:14,410 [10 ] etCore.Mvc.Internal.ObjectResultExecutor - Selected output formatter 'Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter' and content type 'application/json' to write the response.
INFO 2017-05-16 11:24:14,410 [10 ] etCore.Mvc.Internal.ObjectResultExecutor - Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
INFO 2017-05-16 11:24:14,430 [10 ] ore.Mvc.Internal.ControllerActionInvoker - Executed action HbOnline.HbDirectory.Regions.V1.RegionAppService.GetRegions (HbOnline.Api.V1) in 727.8813ms
DEBUG 2017-05-16 11:24:14,430 [10 ] Microsoft.AspNetCore.Server.Kestrel - Connection id "0HL4S6JCVM439" completed keep alive response.
INFO 2017-05-16 11:24:14,430 [10 ] soft.AspNetCore.Hosting.Internal.WebHost - Request finished in 741.8192ms 500 application/json; charset=utf-8
User avatar
By jumpball
#18314 Hi,

I've added interface IApiV1Service HbOnline.Api.V1 project
RegionAppService in this project now start with
public class RegionAppService : HbOnlineAppServiceBase, IRegionAppService, IApiV1Service
{ ...

Then one more line was added to PreInitialize in WebHostModeule
IocManager.IocContainer.Register(Classes.FromAssemblyNamed(typeof(HbOnlineApiV1Module).Assembly.FullName).BasedOn<IApiV1Service>().LifestylePerThread().WithServiceSelf());

And now I's Ok
I have 2 versions of API and controllers in this version can has the same names

INFO 2017-05-17 17:11:50,682 [9 ] soft.AspNetCore.Hosting.Internal.WebHost - Request starting HTTP/1.1 GET http://localhost:22742/api/services/app ... GetRegions
...
INFO 2017-05-17 17:11:52,053 [3 ] ore.Mvc.Internal.ControllerActionInvoker - Executed action HbOnline.Regions.RegionAppService.GetRegions (HbOnline.Application) in 1364.5514ms
...
INFO 2017-05-17 17:12:22,727 [3 ] soft.AspNetCore.Hosting.Internal.WebHost - Request starting HTTP/1.1 GET http://localhost:22742/api/services/v1/ ... GetRegions
...
INFO 2017-05-17 17:12:23,158 [10 ] ore.Mvc.Internal.ControllerActionInvoker - Executed action HbOnline.Api.V1.RegionAppService.GetRegions (HbOnline.Api.V1) in 425.9908ms

Thanks for your advices and for good ABP & AspNetZero documentation