2

I am doing some plugin kind of work using asp.net mvc. I have two plugins(mvc projects) Say users and home. In both the plugins, I have Home Controllers. Yes the names are home controller in both the plugins(projects). When I build the project the Dlls are copied to the host project (third one).

this is home plugin

namespace Plugin.Home.Controllers
{
public class HomeController : Controller
{
    public string Index()
    {
        return "Home from home";
    }

    public string JustATest()
    {
        return "Just a test from home";
    }

}
}

Here is another controller in different project(User Plugin)

this is home controller

namespace Plugin.Users.Controllers
{
public class HomeController : Controller
{
    public string Index()
    {
        return "Home from Users";
    }

    public string JustATest()
    {
        return "Just a test from Users";
    }

    public string JustAnotherTest()
    {
        return "Just another test from Users";
    }

}
}

In global.asax I have register routes using namespaces.

routes.MapRoute(
        "Default", // Route name
        "Home/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional },     
 new[] { "Plugin.Home.Controllers" }

routes.MapRoute(
           "Users", // Route name
           "users/{action}/{id}", // URL with parameters
           new { controller = "Home", action = "Index", id = UrlParameter.Optional },     new[] { "Plugin.Users.Controllers" }
       );

I can access all the routes in the browser without any problem.

Now the problems

  1. I try to use @{Html.RenderAction("JustATest","Home");} It only renders from the home controller in home module. How can i render it from Users module.

  2. It throws an exception saying method not found in home controller, when I say @{Html.RenderAction("JustAnotherTest","Home");}

At what stage I can check if a given controller has the given method or not (Some ControllerFactory). Or how can i make sure it picks up the right controller.

Help will be appreciated.

Regards

Parminder

Parminder
  • 3,088
  • 6
  • 37
  • 61

2 Answers2

2

If you really need to save controller names both HomeController, i see simple solution to use hack like this:

routes.MapRoute(
        null,
        "{home}/{action}/{id}", 
        new { controller = "Home", action = "Index", home="Home", id = UrlParameter.Optional });
routes.MapRoute(
        null,
        "{home}/{action}/{id}", 
        new { controller = "Home", action = "Index", home="Users", id = UrlParameter.Optional }
       );

And you can access to this actions both by url and with RenderAction:

@{Html.RenderAction("JustATest","Home", new {home="Home"});}
@{Html.RenderAction("JustATest","Home", new home="Users");}

But I think that problem is artificial (because it is more hard that you imagine), and you use means only for using means, but not for solving real problem. For real plugin architecture you need to create at least: 1. Custom Route Constraint for checking, that controller type is from assembly, where controller was defined. 2. Installer, that will install all routes independently of main application 3. Create unit tests for each plugin application Routes to ensure that all routes, that was installed from plugins, that do not know anything about each other, works properly (and don't break each other).

I recommend to take your controllers at main web application and give them different names.

David Levin
  • 6,573
  • 5
  • 48
  • 80
0

See the format used here:

render action with lambda

@Html.RenderACtion<Plugin.Home.Controllers.HomeController>(...)

Edit

I see your issue now. It's that they are dynamically loaded at runtime and hence the names aren't known when you compile. Check out using DefaultControllerFactory as mentioned in various postings here:

How to achieve a dynamic controller and action method in ASP.NET MVC?

Community
  • 1
  • 1
Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71
  • Thanks Adam, but host application has no idea about controllers and methods in the plugins. – Parminder Aug 26 '11 at 03:54
  • The host method has to unless you are using dependency injection, in that case you still need to specify in a config 'some' assembly name/class name to create an instance of. If you want to call RenderAction from your host application, the controller methods must be visible in your plugin. They are marked above as public so I don't quite follow? Where are you calling RenderAction from? – Adam Tuliper Aug 26 '11 at 05:05
  • The controller methods are definately public. I can access them using http://somesite/users/JustATest or http://somesite/home/JustATest, because the runtime look into other dll files available in bin folder and create instance if there is any type inherited from IController which is true for home plugin and users plugin. but when the renderaction executed, it seems get confused. – Parminder Aug 26 '11 at 05:29
  • Thanks Adam. Seems I would need to take that path. But this moment Levin's answer was the solution. – Parminder Aug 29 '11 at 03:51