2025-06-16 17:24:23 +08:00

158 lines
5.8 KiB
C#

using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Syc.Abp.Application.Contracts.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.Conventions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Reflection;
namespace Syc.Abp.Application.Contracts.Route
{
/// <summary>
/// 自定义路由规则
/// </summary>
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
public class SycConventionalRouteBuilder : IConventionalRouteBuilder
{
protected AbpControllerOptions controllerOptions { get; }
protected AbpConventionalControllerOptions Options { get; }
public SycConventionalRouteBuilder(IOptions<AbpControllerOptions> controllerOptions,IOptions<AbpConventionalControllerOptions> options)
{
Options = options.Value;
this.controllerOptions = controllerOptions.Value;
}
public virtual string Build(
string rootPath,
string controllerName,
ActionModel action,
string httpMethod,
[CanBeNull] ConventionalControllerSetting configuration)
{
if (controllerOptions.UrlRootPathMap.ContainsKey(action.Controller.ControllerType.AsType()))
rootPath = controllerOptions.UrlRootPathMap[action.Controller.ControllerType.AsType()];
var controllerNameInUrl = NormalizeUrlControllerName(rootPath, controllerName, action, httpMethod, configuration);
var url = $"api{rootPath}/{NormalizeControllerNameCase(controllerNameInUrl, configuration)}";
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) + "}";
}
}
}
var actionNameInUrl = NormalizeUrlActionName(rootPath, controllerName, action, httpMethod, configuration);
if (!actionNameInUrl.IsNullOrEmpty())
{
url += $"/{NormalizeActionNameCase(actionNameInUrl, configuration)}";
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)
{
return property.Name;
}
protected virtual string NormalizeSecondaryIdNameCase(ParameterModel secondaryId, [CanBeNull] ConventionalControllerSetting configuration)
{
return secondaryId.ParameterName;
}
}
}