- So my blog software was pretty much fleshed out. I could write posts, have tags, have a calendar of posts, an archive links. Multiple blogs, mutliple blog writters per blog, File uploads, WYSIWYG text editing. All in all I was pretty pleased.
Now though I was starting to get into personalizing my blog with some controls that only I may care about. Since I'd like to share this software with others and let them use it I thought it would be better if I made these features optional plugins.
No problem I've done plugin architectures in Win Forms, and in ASP.Net, how bad could it be in ASP.Net MVC? Unfortunately it was conceptually easy, but ended up being prettty technically challenging.
I started off thinking that I'd do it like any other sort of plugin architecture. I'd define an interface for my plugins, and then anythign that implemented that interface I could dynamically load and integrate, but the more I thought about it, the more I realized that I might have problems tying into my controllers with something like that. See the interface design, as I thought about it at the time, is pretty much geared towards immediate processing. It doesn't fit into the controller/view model of loading and displaying data as separate functions.
So as I realized that, I decided I really wanted my plugins to do MVC themselves, and did a little research and found this blog post that talked about exactly what I was thinking. The gist of the post is that you just have to
- Create a class library project.
- Add a reference to System.Web.MVC
- Create folders in the project for Controller, Model, Views
- Add your controller and derive it from the MVC Controller base class (just as it usually works in an ASP.Net MVC project)
- Add your views the same way that you would add them in an ASP.Net MVC project (make sure they are under a folder named after your controller.
- Now this is the only real change. Make sure you select the view, and add it as an embedded resource.
Once you have that done, you have to make a minor change to your core ASP.Net application. You need to add a Virtual Path Provider that will go out and load up your target view from the resource stream in your assembly. After all that, it just works, and it works pretty well, but I had a couple of problems with it.
The first problem that I encountered was because I didn't want to use full blown MVC pages for my plugins, but MVC User Controls instead. I wanted the plugins to fit into my overall page design, not be independant. So for step 5 I just made my views .ascx files that derived from ViewUserControl instead, and still embedded them. Overall that worked like a champ, but there was a drawback.
Because they were ViewUserControls they didn't get their Controller methods fired automatically. Instead the Controller for the page they were on fired, and when the view was rendered, then my ViewUserControl plugin was instantiated and rendered. So the plugins Controller never fired, it didn't have any data. Well thats a bit of a problem.
Okay, I had two options
- Somehow get the page controller to load up my data and pass that to my plugin control.
- Just use ajax to do a post to my plugin controller.
I went with option two, and with just a couple of lines of code, it worked like a champ. Great!
So I go to deploy this to my GoDaddy account, and immediately hit a problem. I got a SecurityPermissoins exception when I tried to add my Virtual Path Provider. Go Daddy didn't allow this behavior on my hosting account. Well there goes that solution, so what else could I do?