Controller inheritance and choosing which controller has prevalence

Viewed 118

I have a baseproject and different inheriting projects. The base project has controllers I may want to occasionally inherit and override (partially).

Base project:

public virtual ActionResult Index(string filter = "", int page = 1)

Sub project:

public override ActionResult Index(string filter = "", int page = 1)

Now I changed the routeConfig, so the routing is mapped to the logic from the correct namespace.

context.MapRoute(
                "Routename",
                "AreaName/{controller}/{action}/{id}",
                new { controller = "ControllerName", action = "Index", id = UrlParameter.Optional },
                new string[] { "ProjectName.Areas.AreaName.SpecificControllers"}
            );

However, I want new added routes to be taken from the specific project should they exist there. The ones which are not existant should be taken from the base project's controller. (The specific controller basically starts out empty and will only contains methods for when overriding is desirable). To try and implement this functionality, I added the other project to the routing here:

 context.MapRoute(
                "Routename",
                "AreaName/{controller}/{action}/{id}",
                new { controller = "ControllerName", action = "Index", id = UrlParameter.Optional },
                new string[] { "ProjectName.Areas.AreaName.SpecificControllers", "ProjectName.Areas.AreaName.GenericControllers"}
            );

However, this obviously leads to the following error:

Multiple types were found that match the controller named 'MethodName'. This can happen if the route that services this request ('CRM/{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.

The request for 'MethodName' has found the following matching controllers:
ProjectName.Areas.AreaName.SpecificControllers.ControllerName
ProjectName.Areas.AreaName.GenericControllers.ControllerName

Is there a way to implement this so that my routing will always look at the specific controller first and only at the generic controller if it cannot find the method in the specific controller?

1 Answers

Generally routing choose the base controller method as far as i know.

There is no direct support to resolve the issue you mentioned in this question.

There are couple of workarounds to resolve this.

Option 1 (My Favourite): Admin on base and Route on inherited controller.

To Use [Area] on the base controller and [Route] on the inherited controllers.

I personally like this approach because it keeps the code inside controller clean.

[Area("Admin")]
AdminBaseController: Controller { }

[Route("Users"))
UserAdminController : AdminBaseController { }
  • Url would be /Admin/Users/Action

Option 2: Use Specific Route Prefix in derived controller actions [Route("Admin")] AdminBaseController: Controller { }

public static string UserAdminControllerPrefix = "/Users";
UserAdminController : AdminBaseController { 

[Route(UserAdminControllerPrefix + "/ActionName")]
public void ActionName() {  }

}
  • Formed URL would be /Admin/Users/ActionName

you can choose whichever option which fits your style. Hope this helps. Both the approaches mentioned in this answer : ASP.NET Core MVC Attribute Routing Inheritance

Related