diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs index c3e6ce1740..4dac8cf831 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs @@ -209,17 +209,16 @@ namespace Volo.Abp.AspNetCore.Mvc private void AddAbpServiceSelector(string moduleName, string controllerName, ActionModel action, [CanBeNull] AbpControllerAssemblySetting configuration) { + var verb = configuration?.UseConventionalHttpVerbs == true + ? HttpVerbHelper.GetConventionalVerbForMethodName(action.ActionName) + : HttpVerbHelper.DefaultHttpVerb; + var abpServiceSelectorModel = new SelectorModel { - AttributeRouteModel = CreateAbpServiceAttributeRouteModel(moduleName, controllerName, action) + AttributeRouteModel = CreateAbpServiceAttributeRouteModel(moduleName, controllerName, action, verb), + ActionConstraints = { new HttpMethodActionConstraint(new[] { verb }) } }; - var verb = configuration?.UseConventionalHttpVerbs == true - ? HttpVerbHelper.GetConventionalVerbForMethodName(action.ActionName) - : HttpVerbHelper.DefaultHttpVerb; - - abpServiceSelectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { verb })); - action.Selectors.Add(abpServiceSelectorModel); } @@ -227,13 +226,11 @@ namespace Volo.Abp.AspNetCore.Mvc { foreach (var selector in action.Selectors) { + //TODO: Revise this? + var method = selector.ActionConstraints.OfType().FirstOrDefault()?.HttpMethods?.FirstOrDefault(); if (selector.AttributeRouteModel == null) { - selector.AttributeRouteModel = CreateAbpServiceAttributeRouteModel( - moduleName, - controllerName, - action - ); + selector.AttributeRouteModel = CreateAbpServiceAttributeRouteModel(moduleName, controllerName, action, method); } } } @@ -250,13 +247,17 @@ namespace Volo.Abp.AspNetCore.Mvc return _configuration.Value.ControllerAssemblySettings.GetSettingOrNull(controllerType); } - private static AttributeRouteModel CreateAbpServiceAttributeRouteModel(string moduleName, string controllerName, ActionModel action) + private static AttributeRouteModel CreateAbpServiceAttributeRouteModel(string moduleName, string controllerName, ActionModel action, string verb) { - return new AttributeRouteModel( - new RouteAttribute( - $"api/services/{moduleName}/{controllerName}/{action.ActionName}" - ) - ); + //TODO: Implement via interfaces! + + var url = $"api/services/{moduleName}/{controllerName}"; + if (!verb.IsIn("POST")) + { + url += $"/{action.ActionName}"; + } + + return new AttributeRouteModel(new RouteAttribute(url)); } private static void RemoveEmptySelectors(IList selectors) diff --git a/src/Volo.Abp/Volo/Abp/Application/Dtos/ListResultDto.cs b/src/Volo.Abp/Volo/Abp/Application/Dtos/ListResultDto.cs index 5b218b0dde..acdc42c873 100644 --- a/src/Volo.Abp/Volo/Abp/Application/Dtos/ListResultDto.cs +++ b/src/Volo.Abp/Volo/Abp/Application/Dtos/ListResultDto.cs @@ -2,11 +2,9 @@ using System.Collections.Generic; namespace Volo.Abp.Application.Dtos { - public class ListResultDto + public class ListResultDto : IListResult { - /// - /// List of items. - /// + /// public IReadOnlyList Items { get { return _items ?? (_items = new List()); } diff --git a/src/Volo.Abp/Volo/Abp/Application/Dtos/PagedResultDto.cs b/src/Volo.Abp/Volo/Abp/Application/Dtos/PagedResultDto.cs index e9972ef0b4..a4c8e6ce82 100644 --- a/src/Volo.Abp/Volo/Abp/Application/Dtos/PagedResultDto.cs +++ b/src/Volo.Abp/Volo/Abp/Application/Dtos/PagedResultDto.cs @@ -10,9 +10,7 @@ namespace Volo.Abp.Application.Dtos [Serializable] public class PagedResultDto : ListResultDto, IPagedResult { - /// - /// Total count of Items. - /// + /// public int TotalCount { get; set; } /// diff --git a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PersonAppService_Tests.cs b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PersonAppService_Tests.cs index 4d5bcacd66..e11f4910c7 100644 --- a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PersonAppService_Tests.cs +++ b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PersonAppService_Tests.cs @@ -69,7 +69,7 @@ namespace Volo.Abp.AspNetCore.Mvc //Ideally should be [POST] /api/app/person var response = await Client.PostAsync( - "/api/services/app/person/Create", + "/api/services/app/person", new StringContent(postData, Encoding.UTF8, "application/json") ); diff --git a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/GetPersonPhonesFilter.cs b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/GetPersonPhonesFilter.cs new file mode 100644 index 0000000000..8df4220888 --- /dev/null +++ b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/GetPersonPhonesFilter.cs @@ -0,0 +1,9 @@ +using Volo.Abp.TestApp.Domain; + +namespace Volo.Abp.TestApp.Application +{ + public class GetPersonPhonesFilter + { + public PhoneType? Type { get; set; } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/IPersonAppService.cs b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/IPersonAppService.cs index 203aeaba8f..f5bee1701a 100644 --- a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/IPersonAppService.cs +++ b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/IPersonAppService.cs @@ -1,8 +1,12 @@ -using Volo.Abp.Application.Services; +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; namespace Volo.Abp.TestApp.Application { public interface IPersonAppService : IAsyncCrudAppService { + Task> GetPhones(Guid id, GetPersonPhonesFilter filter); } } \ No newline at end of file diff --git a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PersonAppService.cs b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PersonAppService.cs index d738173ade..20ad74f31a 100644 --- a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PersonAppService.cs +++ b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PersonAppService.cs @@ -1,4 +1,8 @@ -using Volo.Abp.TestApp.Domain; +using System; +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.TestApp.Domain; using Volo.Abp.Domain.Repositories; using Volo.Abp.Application.Services; @@ -9,6 +13,16 @@ namespace Volo.Abp.TestApp.Application public PersonAppService(IQueryableRepository repository) : base(repository) { + + } + + public async Task> GetPhones(Guid id, GetPersonPhonesFilter input) + { + var person = await GetEntityByIdAsync(id); + + return new ListResultDto( + ObjectMapper.Map, Collection>(person.Phones) + ); } } } diff --git a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PhoneDto.cs b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PhoneDto.cs new file mode 100644 index 0000000000..273a6a53fc --- /dev/null +++ b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PhoneDto.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Application.Dtos; +using Volo.Abp.TestApp.Domain; + +namespace Volo.Abp.TestApp.Application +{ + public class PhoneDto : EntityDto + { + public string Number { get; set; } + + public PhoneType Type { get; set; } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs index 74ebf2c821..f3651c0783 100644 --- a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs +++ b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs @@ -1,13 +1,16 @@ using System; +using System.Collections.ObjectModel; using Volo.Abp.Domain.Entities; namespace Volo.Abp.TestApp.Domain { public class Person : AggregateRoot { - public string Name { get; set; } + public virtual string Name { get; set; } - public int Age { get; set; } + public virtual int Age { get; set; } + + public virtual Collection Phones { get; set; } private Person() { @@ -19,6 +22,8 @@ namespace Volo.Abp.TestApp.Domain Id = id; Name = name; Age = age; + + Phones = new Collection(); } } } \ No newline at end of file diff --git a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs new file mode 100644 index 0000000000..b541da9240 --- /dev/null +++ b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs @@ -0,0 +1,22 @@ +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.TestApp.Domain +{ + public class Phone : Entity + { + public virtual string Number { get; set; } + + public virtual PhoneType Type { get; set; } + + private Phone() + { + + } + + public Phone(string number, PhoneType type = PhoneType.Mobile) + { + Number = number; + Type = type; + } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PhoneType.cs b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PhoneType.cs new file mode 100644 index 0000000000..4ec0c6bed4 --- /dev/null +++ b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PhoneType.cs @@ -0,0 +1,9 @@ +namespace Volo.Abp.TestApp.Domain +{ + public enum PhoneType + { + Mobile, + Home, + Office + } +} \ No newline at end of file diff --git a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs index 6660f5c873..2eca793dc1 100644 --- a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs +++ b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs @@ -24,16 +24,17 @@ namespace Volo.Abp.TestApp { services.Configure(options => { - options.Configurators.Add((IAbpAutoMapperConfigurationContext ctx) => + options.Configurators.Add(ctx => { ctx.MapperConfiguration.CreateMap().ReverseMap(); + ctx.MapperConfiguration.CreateMap().ReverseMap(); }); }); } private static void SeedTestData(ApplicationInitializationContext context) { - using (IServiceScope scope = context.ServiceProvider.CreateScope()) + using (var scope = context.ServiceProvider.CreateScope()) { scope.ServiceProvider .GetRequiredService()