Browse Source

Support secondary Ids and allow to normalize action in url.

pull/96/head
Halil İbrahim Kalkan 9 years ago
parent
commit
9a7507ce31
  1. 27
      src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs
  2. 32
      src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs
  3. 41
      src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AppServiceControllerOptions.cs
  4. 18
      src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DefaultUrlActionNameNormalizer.cs
  5. 7
      src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/IUrlActionNameNormalizer.cs
  6. 27
      src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/UrlActionNameNormalizerContext.cs
  7. 1
      test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/AppModule.cs
  8. 17
      test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/PhoneBookUrlActionNameNormalizer.cs
  9. 11
      test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PersonAppService_Tests.cs

27
src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs

@ -261,7 +261,7 @@ namespace Volo.Abp.AspNetCore.Mvc
return new AttributeRouteModel(new RouteAttribute(url));
}
private static string CalculateUrl(string moduleName, string controllerName, ActionModel action, string httpMethod)
protected virtual string CalculateUrl(string moduleName, string controllerName, ActionModel action, string httpMethod)
{
var url = $"api/{moduleName}/{controllerName}";
@ -272,15 +272,34 @@ namespace Volo.Abp.AspNetCore.Mvc
}
//Add action name if needed
var actionName = HttpMethodConventionHelper.RemoveHttpMethodPrefix(action.ActionName, httpMethod);
if (!actionName.IsNullOrEmpty())
var actionNameInUrl = NormalizeUrlActionName(moduleName, controllerName, action, httpMethod);
if (!actionNameInUrl.IsNullOrEmpty())
{
url += $"/{actionName}";
url += $"/{actionNameInUrl}";
//Add secondary Id
var secondaryIds = action.Parameters.Where(p => p.ParameterName.EndsWith("Id", StringComparison.Ordinal)).ToList();
if (secondaryIds.Count == 1)
{
url += $"/{{{secondaryIds[0].ParameterName}}}";
}
}
return url;
}
protected virtual string NormalizeUrlActionName(string moduleName, string controllerName, ActionModel action, string httpMethod)
{
var context = new UrlActionNameNormalizerContext(moduleName, controllerName, action, httpMethod, action.ActionName);
foreach (var normalizer in _options.AppServiceControllers.UrlActionNameNormalizers)
{
normalizer.Normalize(context);
}
return context.ActionNameInUrl;
}
protected virtual void RemoveEmptySelectors(IList<SelectorModel> selectors)
{
selectors

32
src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs

@ -1,9 +1,4 @@
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Volo.Abp.AspNetCore.Mvc
namespace Volo.Abp.AspNetCore.Mvc
{
public class AbpAspNetCoreMvcOptions
{
@ -14,29 +9,4 @@ namespace Volo.Abp.AspNetCore.Mvc
AppServiceControllers = new AppServiceControllerOptions();
}
}
public class AppServiceControllerOptions
{
public ControllerAssemblySettingList ControllerAssemblySettings { get; }
public List<Type> FormBodyBindingIgnoredTypes { get; }
public AppServiceControllerOptions()
{
ControllerAssemblySettings = new ControllerAssemblySettingList();
FormBodyBindingIgnoredTypes = new List<Type>
{
typeof(IFormFile)
};
}
public AbpControllerAssemblySettingBuilder CreateFor(
Assembly assembly,
string moduleName = AbpControllerAssemblySetting.DefaultServiceModuleName,
bool useConventionalHttpVerbs = true)
{
var setting = new AbpControllerAssemblySetting(moduleName, assembly, useConventionalHttpVerbs);
ControllerAssemblySettings.Add(setting);
return new AbpControllerAssemblySettingBuilder(setting);
}
}
}

41
src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AppServiceControllerOptions.cs

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.AspNetCore.Http;
namespace Volo.Abp.AspNetCore.Mvc
{
public class AppServiceControllerOptions
{
public ControllerAssemblySettingList ControllerAssemblySettings { get; }
public List<Type> FormBodyBindingIgnoredTypes { get; }
public List<IUrlActionNameNormalizer> UrlActionNameNormalizers { get; }
public AppServiceControllerOptions()
{
ControllerAssemblySettings = new ControllerAssemblySettingList();
FormBodyBindingIgnoredTypes = new List<Type>
{
typeof(IFormFile)
};
UrlActionNameNormalizers = new List<IUrlActionNameNormalizer>
{
new DefaultUrlActionNameNormalizer()
};
}
public AbpControllerAssemblySettingBuilder CreateFor(
Assembly assembly,
string moduleName = AbpControllerAssemblySetting.DefaultServiceModuleName,
bool useConventionalHttpVerbs = true)
{
var setting = new AbpControllerAssemblySetting(moduleName, assembly, useConventionalHttpVerbs);
ControllerAssemblySettings.Add(setting);
return new AbpControllerAssemblySettingBuilder(setting);
}
}
}

18
src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DefaultUrlActionNameNormalizer.cs

@ -0,0 +1,18 @@
using System;
using Volo.Abp.Http;
namespace Volo.Abp.AspNetCore.Mvc
{
public class DefaultUrlActionNameNormalizer : IUrlActionNameNormalizer
{
public void Normalize(UrlActionNameNormalizerContext context)
{
if (context.ActionNameInUrl.IsNullOrEmpty())
{
return;
}
context.ActionNameInUrl = HttpMethodConventionHelper.RemoveHttpMethodPrefix(context.ActionNameInUrl, context.HttpMethod);
}
}
}

7
src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/IUrlActionNameNormalizer.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.AspNetCore.Mvc
{
public interface IUrlActionNameNormalizer
{
void Normalize(UrlActionNameNormalizerContext context);
}
}

27
src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/UrlActionNameNormalizerContext.cs

@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace Volo.Abp.AspNetCore.Mvc
{
public class UrlActionNameNormalizerContext
{
public string ModuleName { get; }
public string ControllerName { get; }
public ActionModel Action { get; }
public string HttpMethod { get; }
public string ActionNameInUrl { get; set; }
public UrlActionNameNormalizerContext(string moduleName, string controllerName, ActionModel action, string httpMethod, string actionNameInUrl)
{
ModuleName = moduleName;
ControllerName = controllerName;
Action = action;
HttpMethod = httpMethod;
ActionNameInUrl = actionNameInUrl;
}
}
}

1
test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/AppModule.cs

@ -25,6 +25,7 @@ namespace Volo.Abp.AspNetCore.App
services.Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.AppServiceControllers.CreateFor(typeof(TestAppModule).Assembly);
options.AppServiceControllers.UrlActionNameNormalizers.Add(new PhoneBookUrlActionNameNormalizer());
});
services.AddAssemblyOf<AppModule>();

17
test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/PhoneBookUrlActionNameNormalizer.cs

@ -0,0 +1,17 @@
using System;
using Volo.Abp.AspNetCore.Mvc;
namespace Volo.Abp.AspNetCore.App
{
public class PhoneBookUrlActionNameNormalizer : IUrlActionNameNormalizer
{
public void Normalize(UrlActionNameNormalizerContext context)
{
if (string.Equals(context.ActionNameInUrl, "phone", StringComparison.OrdinalIgnoreCase))
{
context.ActionNameInUrl = "phones";
return;
}
}
}
}

11
test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PersonAppService_Tests.cs

@ -129,9 +129,8 @@ namespace Volo.Abp.AspNetCore.Mvc
var postData = _jsonSerializer.Serialize(new PhoneDto { Type = PhoneType.Mobile, Number = phoneNumberToAdd });
//Ideally should be [POST] /api/people/{id}/phones
var response = await Client.PostAsync(
$"/api/app/people/{personToAddNewPhone.Id}/phone",
$"/api/app/people/{personToAddNewPhone.Id}/phones",
new StringContent(postData, Encoding.UTF8, "application/json")
);
@ -154,8 +153,7 @@ namespace Volo.Abp.AspNetCore.Mvc
{
var douglas = _personRepository.GetList().First(p => p.Name == "Douglas");
//Ideally should be [GET] /api/people/{id}/phones?type=office
var result = await GetResponseAsObjectAsync<ListResultDto<PhoneDto>>($"/api/app/people/{douglas.Id}/Phones");
var result = await GetResponseAsObjectAsync<ListResultDto<PhoneDto>>($"/api/app/people/{douglas.Id}/phones");
result.Items.Count.ShouldBe(douglas.Phones.Count);
}
@ -165,11 +163,10 @@ namespace Volo.Abp.AspNetCore.Mvc
var douglas = _personRepository.GetList().First(p => p.Name == "Douglas");
var firstPhone = douglas.Phones.First();
//Ideally should be [DELETE] /api/app/people/{id}/phones/{phoneId}
await Client.DeleteAsync($"/api/app/people/{douglas.Id}/Phone?phoneId=" + firstPhone.Id);
await Client.DeleteAsync($"/api/app/people/{douglas.Id}/phones/{firstPhone.Id}");
douglas = _personRepository.GetList().First(p => p.Name == "Douglas");
douglas.Phones.Any(p => p.Id == firstPhone.Id).ShouldBeFalse();
}
}
}
}
Loading…
Cancel
Save