123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- using Infrastructure.Helper;
- using Microsoft.AspNetCore.Mvc.ActionConstraints;
- using Microsoft.AspNetCore.Mvc.ApplicationModels;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace ZR.Common.DynamicApiSimple;
- class ApiConvention : IApplicationModelConvention
- {
- public void Apply(ApplicationModel application)
- {
- foreach (var controller in application.Controllers)
- {
- var type = controller.ControllerType;
- if (typeof(IDynamicApi).IsAssignableFrom(type) || type.IsDefined(typeof(DynamicApiAttribute), true))
- {
- ClearAction(controller);
- ConfigureApiExplorer(controller);
- ConfigureSelector(controller);
- }
- }
- }
- private void ClearAction(ControllerModel controller)
- {
- Type genericBaseType = AssemblyUtils.GetGenericTypeByName("BaseService`1");
- var needRemoveAction = controller.Actions
- .Where(action => !action.ActionMethod.DeclaringType.IsDerivedFromGenericBaseRepository(genericBaseType))
- .ToList();
- foreach (var actionModel in needRemoveAction)
- {
- controller.Actions.Remove(actionModel);
- }
- }
- private static void ConfigureApiExplorer(ControllerModel controller)
- {
- if (!controller.ApiExplorer.IsVisible.HasValue)
- controller.ApiExplorer.IsVisible = true;
- foreach (var action in controller.Actions)
- {
- if (!action.ApiExplorer.IsVisible.HasValue)
- {
- action.ApiExplorer.IsVisible = true;
- }
- }
- }
- private void ConfigureSelector(ControllerModel controller)
- {
- RemoveEmptySelectors(controller.Selectors);
- if (controller.Selectors.Any(selector => selector.AttributeRouteModel != null))
- return;
- foreach (var action in controller.Actions)
- {
- ConfigureSelector(action);
- }
- }
- private static void RemoveEmptySelectors(IList<SelectorModel> selectors)
- {
- for (var i = selectors.Count - 1; i >= 0; i--)
- {
- var selector = selectors[i];
- if (selector.AttributeRouteModel == null &&
- (selector.ActionConstraints == null || selector.ActionConstraints.Count <= 0) &&
- (selector.EndpointMetadata == null || selector.EndpointMetadata.Count <= 0))
- {
- selectors.Remove(selector);
- }
- }
- }
- private void ConfigureSelector(ActionModel action)
- {
- RemoveEmptySelectors(action.Selectors);
- if (action.Selectors.Count <= 0)
- AddServiceSelector(action);
- else
- NormalizeSelectorRoutes(action);
- }
- private void AddServiceSelector(ActionModel action)
- {
- var template = new Microsoft.AspNetCore.Mvc.RouteAttribute(GetRouteTemplate(action));
- var selector = new SelectorModel
- {
- AttributeRouteModel = new AttributeRouteModel(template)
- };
- selector.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { GetHttpMethod(action) }));
- action.Selectors.Add(selector);
- }
- private void NormalizeSelectorRoutes(ActionModel action)
- {
- foreach (var selector in action.Selectors)
- {
- var template = new Microsoft.AspNetCore.Mvc.RouteAttribute(GetRouteTemplate(action,selector));
- selector.AttributeRouteModel = new AttributeRouteModel(template);
- if (selector.ActionConstraints.OfType<HttpMethodActionConstraint>().FirstOrDefault()?.HttpMethods?.FirstOrDefault() == null)
- selector.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { GetHttpMethod(action) }));
- }
- }
- private string GetRouteTemplate(ActionModel action,SelectorModel selectorModel=null)
- {
- var routeTemplate = new StringBuilder();
- var names = action.Controller.ControllerType.Namespace.Split('.');
- if (names.Length > 2)
- {
- routeTemplate.Append(names[^2]);
- }
- // Controller
- var controllerName = action.Controller.ControllerName;
- if (controllerName.EndsWith("Service"))
- controllerName = controllerName[0..^7];
- if (selectorModel is { AttributeRouteModel: not null })
- {
- if (!string.IsNullOrWhiteSpace(selectorModel.AttributeRouteModel?.Template))
- {
- if (selectorModel.AttributeRouteModel.Template.StartsWith("/"))
- {
- routeTemplate.Append(selectorModel.AttributeRouteModel.Template);
- }
- else
- {
- routeTemplate.Append($"{BaseRoute}/{controllerName}/{selectorModel.AttributeRouteModel.Template}");
- }
- }
- }
- else
- {
- routeTemplate.Append($"{BaseRoute}/{controllerName}");
- // Action
- var actionName = action.ActionName;
- if (actionName.EndsWith("Async") || actionName.EndsWith("async"))
- actionName = actionName[..^"Async".Length];
- if (!string.IsNullOrEmpty(actionName))
- {
- routeTemplate.Append($"/{RemoveHttpMethodPrefix(actionName)}");
- }
- }
-
- return routeTemplate.ToString();
- }
- private static string GetHttpMethod(ActionModel action)
- {
- var actionName = action.ActionName.ToLower();
- string Method = string.Empty;
- if (!string.IsNullOrEmpty(actionName))
- {
- Method = GetName(actionName);
- }
- return Method;
- }
- private static string GetName(string actionName)
- {
- string result = "GET";
- foreach (string key in Methods.Keys)
- {
- if (actionName.Contains(key))
- {
- result = Methods[key];
- break;
- }
- }
- return result;
- }
- internal static Dictionary<string, string> Methods { get; private set; }
- internal static string BaseRoute { get; private set; } = "api";
- static ApiConvention()
- {
- Methods = new Dictionary<string, string>()
- {
- ["get"] = "GET",
- ["find"] = "GET",
- ["fetch"] = "GET",
- ["query"] = "GET",
- ["post"] = "POST",
- ["add"] = "POST",
- ["create"] = "POST",
- ["insert"] = "POST",
- ["submit"] = "POST",
- ["put"] = "POST",
- ["update"] = "POST",
- ["delete"] = "DELETE",
- ["remove"] = "DELETE",
- ["clear"] = "DELETE",
- ["patch"] = "PATCH"
- };
- }
- private static string RemoveHttpMethodPrefix(string actionName)
- {
- foreach (var method in Methods.Keys)
- {
- if (actionName.StartsWith(method, StringComparison.OrdinalIgnoreCase))
- {
- // 移除前缀并返回结果
- return actionName.Substring(method.Length);
- }
- }
- return actionName; // 如果没有找到前缀,返回原始名称
- }
- }
|