ASP.NET Core MVC中的虚线路由?

时间:2017-02-13 07:12:30

标签: asp.net-mvc asp.net-core

在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。

我不想使用属性路由。

由于

1 个答案:

答案 0 :(得分:2)

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

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

UseMvc中的路由不起作用。它们根本不会被ASP.Net本身考虑。我在GitHub上创建了一个问题...但不确定它会如何发展。现在,您可以在方法上指定具有属性的路径。 Convention将重用/复制原始路由并以{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;
    }
}