Skip to content

Instantly share code, notes, and snippets.

@seangwright
Created July 13, 2017 01:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save seangwright/8a4d52cd7a60320a53db60c2e2e5456f to your computer and use it in GitHub Desktop.
Save seangwright/8a4d52cd7a60320a53db60c2e2e5456f to your computer and use it in GitHub Desktop.
AspNet Core MVC attribute routing lower/kebab case controller placeholder replacement
/**
Takes something like this
[Route("api/customer/{customerId:int}/[controller]")]
public class SpecialOrderController : Controller
{
// ...
[HttpGet("~/api/[controller]")]
[Produces(typeof(IEnumerable<SpecialOrderResponse>))]
public IActionResult Get() => Ok(db.Query(new GetAllSpecialOrders()));
}
and with Swashbuckle / Ahoy, generates swagger documentation like
GET /api/customer/{customerId}/special-order
GET /api/special-order
*/
public class KebabRoutingConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
foreach (var selector in controller.Selectors)
{
selector.AttributeRouteModel = replaceControllerTemplate(selector, controller.ControllerName);
}
foreach (var selector in controller.Actions.SelectMany(a => a.Selectors))
{
selector.AttributeRouteModel = replaceControllerTemplate(selector, controller.ControllerName);
}
AttributeRouteModel replaceControllerTemplate(SelectorModel selector, string name)
{
return selector.AttributeRouteModel != null
? new AttributeRouteModel
{
Template = selector.AttributeRouteModel.Template
.Replace("[controller]", PascalToKebabCase(name))
}
: null;
}
string PascalToKebabCase(string value)
{
if (string.IsNullOrEmpty(value))
{
return value;
}
return Regex.Replace(
value,
"(?<!^)([A-Z][a-z]|(?<=[a-z])[A-Z])",
"-$1",
RegexOptions.Compiled)
.Trim()
.ToLower();
}
}
}
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
options.Conventions.Add(new KebabRoutingConvention())
);
}
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment