Reputation: 427
I'm trying to use a base controller with the [InheritedRoute]
attribute. The base class and controllers are created like this:
[InheritedRoute("app/{controller}/{action=index}/{id?}")]
public abstract class MyBaseController : Controller
{
public ActionResult Index()
{
return View();
}
}
public class DefaultController : MyBaseController { }
public class KyleController : MyBaseController { }
[RoutePrefix("app/support")]
[Route("{action=Index}/{id?}")]
public class SupportController : Controller
{
public ActionResult Index()
{
return View();
}
}
The InheritedRouteAttribute
class and stuff:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class InheritedRouteAttribute : Attribute, IDirectRouteFactory
{
public string Name { get; set; }
public int Order { get; set; }
public string Template { get; }
public InheritedRouteAttribute(string template)
{
this.Template = template;
}
public RouteEntry CreateRoute(DirectRouteFactoryContext context)
{
var controllerDescriptor = context.Actions.First().ControllerDescriptor;
var controllerName = controllerDescriptor.ControllerName;
string template;
if (string.Equals(controllerName, "Default", StringComparison.OrdinalIgnoreCase))
{
template = this.Template.Replace("{controller}/", string.Empty);
}
else
{
template = this.Template.Replace("{controller}", controllerName);
}
IDirectRouteBuilder builder = context.CreateBuilder(template);
builder.Name = this.Name ?? controllerName + "_Route";
builder.Order = this.Order;
return builder.Build();
}
}
public class InheritedDirectRouteProvider : DefaultDirectRouteProvider
{
protected override IReadOnlyList<IDirectRouteFactory> GetControllerRouteFactories(ControllerDescriptor controllerDescriptor)
{
return controllerDescriptor.GetCustomAttributes(typeof(IDirectRouteFactory), true).Cast<IDirectRouteFactory>().ToArray();
}
}
In my RouteConfig.cs, I'm not using conventional routes:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes(new InheritedDirectRouteProvider());
}
In essence, I want to make it so that if the user is in a DefaultController
, the word "Default" is stripped out of the URL; otherwise, use the standard convention, prepended with "app". If I strip out Default (by taking out {controller}/), then I get the Multiple controller types error whenever I go to another URL. However, if I leave it, everything is fine, except the URL isn't as I wish.
I'm looking at RouteDebugger and seeing what is registered as my routes, and I see (as I expect):
What am I missing? Why does it think I have a duplicate route, specifically on SupportController
and DefaultController
?
Upvotes: 0
Views: 378
Reputation: 31322
Let's look at these two route templates:
If you visit app/support
both of them will match:
The both routes match also if you visit app/support/something
:
So any url under 'app/support' with 2 or 3 segments will match both routes.
Now when you understand what happens, you probably could figure out the fix by yourself. The easiest fix probably is to make those routes match different number of segments. The possible option is to remove default action for both routes and get rid of optional id parameter:
Choose solution that satisfies the requirements you have. But make sure that 'support' segment from one route does not match the action part from another route as in your current routing.
Upvotes: 1