Dale Fraser
Dale Fraser

Reputation: 4748

Can I use controller name in controller destination

I want a route that will take requests from

/api/v1/job

to

Controller that lives in

/api/v1/jobController

where the controller name is jobv1Controller

    configuration.Routes.MapHttpRoute(
        "v1",
        "Api/v1/{controller}/{id}",
        new { controller = "{controller}v1", id = RouteParameter.Optional });

Upvotes: 0

Views: 62

Answers (1)

Raja Nadar
Raja Nadar

Reputation: 9489

short version:

the in-built DefaultControllerFactory may not be able to create the controller you need, since it treats the value as a plain name string, and doesn't do any token replacement.

the solution would be to extend DefaultControllerFactory and override the CreateController method. Change the controllerName value and then use the base functionality to get you that controller.

Register your custome factory in Global.asax

ControllerBuilder.Current.SetControllerFactory(
                                         typeof(YourCustomControllerFactory)); 

long version:

As you know the flow is as follows:

Request >> Routing System >> MVC's Default Controller Factory >> Create Controller >> Invoke it.

I don't think it is possible to give dynamic values in the default route data dictionary and expect the default controller factory to find that controller.

This is because the built-in controller factory works off the direct value of the controller key, given in the route data dictionary.

The MVC Handler does no magic there of trying to parse the controller value provided as some formatted string, and associating Url Fragment values (controller/action etc.) in this format. it sees it as a straight up value.

By default, the DefaultControllerFactory is invoked to get the controller type, and it uses the string value as-is to activate a controller type.

So one way to solve your problem is to define a custom factory implementing IControllerFactory

Once you do that, your factory's

CreateController method will be called, with the RequestContext and ControllerName string as the 2 parameters.

The RequestContext has the RequestContext.RouteData.Values dictionary, which has all the routing data, tokens, constraints, namespaces etc.

Once you have the incoming controller name, you can massage it to whatever format you need (controllername + "v1") and then instantiate that controller (using DI containers or Service Locator or Activator.CreateInstance etc. whatever you wish) and return it. Try to use some sort of look-up cache for this.

Once you have implemented your custom factory, you can register your custom controller factory with MVC as follows in Global.asax:

ControllerBuilder.Current.SetControllerFactory(
        typeof(YourCustomControllerFactory)); 

Upvotes: 1

Related Questions