在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。
我不想使用属性路由。
由于
答案 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;
}
}