核心 MVC 中的虚线路由 ASP.NET



在 Core 之前,我在 MVC 中使用了这样的东西:

 public class HyphenatedRouteHandler : MvcRouteHandler
    {
        protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            requestContext.RouteData.Values["controller"] = requestContext.RouteData.Values["controller"].ToString().Replace("-", "_");
            requestContext.RouteData.Values["action"] = requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
            return base.GetHttpHandler(requestContext);
        }
    }

如何在 ASP.Net Core 中使用 url 中的破折号? ...像 http://www.example.com/my-friendly-url...并将其转换为动作my_friendly_url。

我不想使用属性路由。

谢谢

在 ConfigureServices 方法的 Startup 中添加此约定:

options.Conventions.Add(new DashedRoutingConvention());

UseMvc 中的路由将不起作用。它们根本不会被 ASP.Net 本身考虑。我在 GitHub 上创建了问题...但不确定它会如何发展。现在,您可以使用方法的属性指定路由。约定将重用/复制原始路由,并以格式{controller}/{action}更新/添加新的虚线路径。

public class DashedRoutingConvention : IControllerModelConvention
{
    public void Apply(ControllerModel controller)
    {
        string parent = this.Convert(controller.ControllerName);
        foreach (ActionModel action in controller.Actions)
        {
            string child = this.Convert(action.ActionName);
            string template = $"{parent}/{child}";
            if (this.Lookup(action.Selectors, template) == true)
                continue;
            List<SelectorModel> selectors = action.Selectors.Where(item => item.AttributeRouteModel?.Template == null).ToList();
            if (selectors.Count > 0)
            {
                foreach (SelectorModel existing in selectors)
                {
                    if (existing.AttributeRouteModel == null)
                        existing.AttributeRouteModel = new AttributeRouteModel();
                    existing.AttributeRouteModel.Template = template;
                }
            }
            else
            {
                selectors = action.Selectors.Where(item => item.AttributeRouteModel?.Template != null).ToList();
                foreach (SelectorModel existing in selectors)
                {
                    SelectorModel selector = new SelectorModel(existing);
                    selector.AttributeRouteModel.Template = template;
                    if (action.Selectors.Any(item => this.Compare(item, selector)) == false)
                        action.Selectors.Add(selector);
                }
            }
        }
    }
    private string Convert(string token)
    {
        if (token == null)
            throw new ArgumentNullException(nameof(token));
        if (token == string.Empty)
            throw new ArgumentException("Failed to convert empty token.");
        return Regex.Replace(token, "(?<!^)([A-Z][a-z]|(?<=[a-z])[A-Z])", "-$1", RegexOptions.Compiled).Trim().ToLower();
    }
    private bool Lookup(IEnumerable<SelectorModel> selectors, string template)
    {
        foreach (SelectorModel selector in selectors)
        {
            string current = selector.AttributeRouteModel?.Template;
            if (string.Compare(current, template, StringComparison.OrdinalIgnoreCase) == 0)
                return true;
        }
        return false;
    }
    private bool Compare(SelectorModel existing, SelectorModel adding)
    {
        if (existing.AttributeRouteModel == null && adding.AttributeRouteModel != null)
            return false;
        if (existing.AttributeRouteModel != null && adding.AttributeRouteModel == null)
            return false;
        if (existing.AttributeRouteModel != null && adding.AttributeRouteModel != null)
        {
            if (existing.AttributeRouteModel.Template != adding.AttributeRouteModel.Template)
                return false;
            if (existing.AttributeRouteModel.Order != adding.AttributeRouteModel.Order)
                return false;
        }
        if (existing.ActionConstraints == null && adding.ActionConstraints != null)
            return false;
        if (existing.ActionConstraints != null && adding.ActionConstraints == null)
            return false;
        if (existing.ActionConstraints != null && adding.ActionConstraints != null)
        {
            if (existing.ActionConstraints.Count != adding.ActionConstraints.Count)
                return false;
        }
        return true;
    }
}

最新更新