Browse Source

#5325: Create auto controller routes in kebap-case

pull/5925/head
Halil İbrahim Kalkan 6 years ago
parent
commit
346979baed
  1. 12
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpConventionalControllerOptions.cs
  2. 96
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs
  3. 12
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs
  4. 160
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs
  5. 16
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/IConventionalRouteBuilder.cs

12
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpConventionalControllerOptions.cs

@ -12,7 +12,13 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
public ConventionalControllerSettingList ConventionalControllerSettings { get; }
public List<Type> FormBodyBindingIgnoredTypes { get; }
/// <summary>
/// Set true to use the old style URL path style.
/// Default: false.
/// </summary>
public bool UseV3UrlStyle { get; set; }
public AbpConventionalControllerOptions()
{
ConventionalControllerSettings = new ConventionalControllerSettingList();
@ -24,7 +30,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
}
public AbpConventionalControllerOptions Create(
Assembly assembly,
Assembly assembly,
[CanBeNull] Action<ConventionalControllerSetting> optionsAction = null)
{
var setting = new ConventionalControllerSetting(
@ -39,4 +45,4 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
return this;
}
}
}
}

96
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs

@ -23,12 +23,15 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
{
public ILogger<AbpServiceConvention> Logger { get; set; }
private readonly AbpAspNetCoreMvcOptions _options;
protected AbpAspNetCoreMvcOptions Options { get; }
protected IConventionalRouteBuilder ConventionalRouteBuilder { get; }
public AbpServiceConvention(
IOptions<AbpAspNetCoreMvcOptions> options)
IOptions<AbpAspNetCoreMvcOptions> options,
IConventionalRouteBuilder conventionalRouteBuilder)
{
_options = options.Value;
ConventionalRouteBuilder = conventionalRouteBuilder;
Options = options.Value;
Logger = NullLogger<AbpServiceConvention>.Instance;
}
@ -131,7 +134,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
return false;
}
if (_options.ConventionalControllers
if (Options.ConventionalControllers
.FormBodyBindingIgnoredTypes
.Any(t => t.IsAssignableFrom(parameter.ParameterInfo.ParameterType)))
{
@ -306,95 +309,14 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
[CanBeNull]
protected virtual ConventionalControllerSetting GetControllerSettingOrNull(Type controllerType)
{
return _options.ConventionalControllers.ConventionalControllerSettings.GetSettingOrNull(controllerType);
return Options.ConventionalControllers.ConventionalControllerSettings.GetSettingOrNull(controllerType);
}
protected virtual AttributeRouteModel CreateAbpServiceAttributeRouteModel(string rootPath, string controllerName, ActionModel action, string httpMethod, [CanBeNull] ConventionalControllerSetting configuration)
{
return new AttributeRouteModel(
new RouteAttribute(
CalculateRouteTemplate(rootPath, controllerName, action, httpMethod, configuration)
)
);
}
protected virtual string CalculateRouteTemplate(string rootPath, string controllerName, ActionModel action, string httpMethod, [CanBeNull] ConventionalControllerSetting configuration)
{
var controllerNameInUrl = NormalizeUrlControllerName(rootPath, controllerName, action, httpMethod, configuration);
var url = $"api/{rootPath}/{controllerNameInUrl.ToCamelCase()}";
//Add {id} path if needed
var idParameterModel = action.Parameters.FirstOrDefault(p => p.ParameterName == "id");
if (idParameterModel != null)
{
if (TypeHelper.IsPrimitiveExtended(idParameterModel.ParameterType, includeEnums: true))
{
url += "/{id}";
}
else
{
var properties = idParameterModel
.ParameterType
.GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var property in properties)
{
url += "/{" + property.Name + "}";
}
}
}
//Add action name if needed
var actionNameInUrl = NormalizeUrlActionName(rootPath, controllerName, action, httpMethod, configuration);
if (!actionNameInUrl.IsNullOrEmpty())
{
url += $"/{actionNameInUrl.ToCamelCase()}";
//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 rootPath, string controllerName, ActionModel action, string httpMethod, [CanBeNull] ConventionalControllerSetting configuration)
{
var actionNameInUrl = HttpMethodHelper
.RemoveHttpMethodPrefix(action.ActionName, httpMethod)
.RemovePostFix("Async");
if (configuration?.UrlActionNameNormalizer == null)
{
return actionNameInUrl;
}
return configuration.UrlActionNameNormalizer(
new UrlActionNameNormalizerContext(
rootPath,
controllerName,
action,
actionNameInUrl,
httpMethod
)
);
}
protected virtual string NormalizeUrlControllerName(string rootPath, string controllerName, ActionModel action, string httpMethod, [CanBeNull] ConventionalControllerSetting configuration)
{
if (configuration?.UrlControllerNameNormalizer == null)
{
return controllerName;
}
return configuration.UrlControllerNameNormalizer(
new UrlControllerNameNormalizerContext(
rootPath,
controllerName
ConventionalRouteBuilder.Build(rootPath, controllerName, action, httpMethod, configuration)
)
);
}

12
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs

@ -18,6 +18,12 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
[NotNull]
public HashSet<Type> ControllerTypes { get; } //TODO: Internal?
/// <summary>
/// Set true to use the old style URL path style.
/// Default: null (uses the value of the <see cref="AbpConventionalControllerOptions.UseV3UrlStyle"/>).
/// </summary>
public bool? UseV3UrlStyle { get; set; }
[NotNull]
public string RootPath
{
@ -57,9 +63,9 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
public List<ApiVersion> ApiVersions { get; }
public Action<ApiVersioningOptions> ApiVersionConfigurer { get; set; }
public ConventionalControllerSetting(
[NotNull] Assembly assembly,
[NotNull] Assembly assembly,
[NotNull] string rootPath,
[NotNull] string remoteServiceName)
{
@ -104,4 +110,4 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
return false;
}
}
}
}

160
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs

@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Reflection;
namespace Volo.Abp.AspNetCore.Mvc.Conventions
{
public class ConventionalRouteBuilder : IConventionalRouteBuilder, ITransientDependency
{
protected AbpConventionalControllerOptions Options { get; }
public ConventionalRouteBuilder(IOptions<AbpConventionalControllerOptions> options)
{
Options = options.Value;
}
public virtual string Build(
string rootPath,
string controllerName,
ActionModel action,
string httpMethod,
[CanBeNull] ConventionalControllerSetting configuration)
{
var controllerNameInUrl = NormalizeUrlControllerName(rootPath, controllerName, action, httpMethod, configuration);
var url = $"api/{rootPath}/{NormalizeControllerNameCase(controllerNameInUrl, configuration)}";
//Add {id} path if needed
var idParameterModel = action.Parameters.FirstOrDefault(p => p.ParameterName == "id");
if (idParameterModel != null)
{
if (TypeHelper.IsPrimitiveExtended(idParameterModel.ParameterType, includeEnums: true))
{
url += "/{id}";
}
else
{
var properties = idParameterModel
.ParameterType
.GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var property in properties)
{
url += "/{" + NormalizeIdPropertyNameCase(property, configuration) + "}";
}
}
}
//Add action name if needed
var actionNameInUrl = NormalizeUrlActionName(rootPath, controllerName, action, httpMethod, configuration);
if (!actionNameInUrl.IsNullOrEmpty())
{
url += $"/{NormalizeActionNameCase(actionNameInUrl, configuration)}";
//Add secondary Id
var secondaryIds = action.Parameters
.Where(p => p.ParameterName.EndsWith("Id", StringComparison.Ordinal)).ToList();
if (secondaryIds.Count == 1)
{
url += $"/{{{NormalizeSecondaryIdNameCase(secondaryIds[0], configuration)}}}";
}
}
return url;
}
protected virtual string NormalizeUrlActionName(string rootPath, string controllerName, ActionModel action,
string httpMethod, [CanBeNull] ConventionalControllerSetting configuration)
{
var actionNameInUrl = HttpMethodHelper
.RemoveHttpMethodPrefix(action.ActionName, httpMethod)
.RemovePostFix("Async");
if (configuration?.UrlActionNameNormalizer == null)
{
return actionNameInUrl;
}
return configuration.UrlActionNameNormalizer(
new UrlActionNameNormalizerContext(
rootPath,
controllerName,
action,
actionNameInUrl,
httpMethod
)
);
}
protected virtual string NormalizeUrlControllerName(string rootPath, string controllerName, ActionModel action,
string httpMethod, [CanBeNull] ConventionalControllerSetting configuration)
{
if (configuration?.UrlControllerNameNormalizer == null)
{
return controllerName;
}
return configuration.UrlControllerNameNormalizer(
new UrlControllerNameNormalizerContext(
rootPath,
controllerName
)
);
}
protected virtual string NormalizeControllerNameCase(string controllerName, [CanBeNull] ConventionalControllerSetting configuration)
{
if (configuration?.UseV3UrlStyle ?? Options.UseV3UrlStyle)
{
return controllerName.ToCamelCase();
}
else
{
return controllerName.ToKebabCase();
}
}
protected virtual string NormalizeActionNameCase(string actionName, [CanBeNull] ConventionalControllerSetting configuration)
{
if (configuration?.UseV3UrlStyle ?? Options.UseV3UrlStyle)
{
return actionName.ToCamelCase();
}
else
{
return actionName.ToKebabCase();
}
}
protected virtual string NormalizeIdPropertyNameCase(PropertyInfo property, [CanBeNull] ConventionalControllerSetting configuration)
{
if (configuration?.UseV3UrlStyle ?? Options.UseV3UrlStyle)
{
return property.Name;
}
else
{
return property.Name.ToKebabCase();
}
}
protected virtual string NormalizeSecondaryIdNameCase(ParameterModel secondaryId, [CanBeNull] ConventionalControllerSetting configuration)
{
if (configuration?.UseV3UrlStyle ?? Options.UseV3UrlStyle)
{
return secondaryId.ParameterName;
}
else
{
return secondaryId.ParameterName.ToKebabCase();
}
}
}
}

16
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/IConventionalRouteBuilder.cs

@ -0,0 +1,16 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace Volo.Abp.AspNetCore.Mvc.Conventions
{
public interface IConventionalRouteBuilder
{
string Build(
string rootPath,
string controllerName,
ActionModel action,
string httpMethod,
[CanBeNull] ConventionalControllerSetting configuration
);
}
}
Loading…
Cancel
Save