views:

70

answers:

1

Hi, i have a very tough problem for me to solve, and i thought and searched alot and came down t one conclusion which i will mention down. the problem is i have a client that wants to create a websites based on a Common functionality, so let us call it Modules, so what i thought is to use MVC Contrib Portable Areas, which are great ideas to plug Modules, but i have a big problem, let us say i created a Blog module which will be implemented in a new site he want, now some users have unique requirements like one of them needs to add Gallery of pictures to each article, or List of references in each article. this would be easy in normal situation where you have one site to work on, so all what you have to do is

  • add a new gallery table with Foreign key to the Blog table.
  • regenerate Linq2SQl code and update the Model.
  • add new form elements to the Create,Edit,Delete Views .
  • add the logic in the controller.

but in my situation it is complicated and time cumbersome because of 2 reasons

  • if the new functionality is cool and client decide to implement it in all sites, then i have to repeat the work for each site.
  • if the functionality is unique it will create inconsistency for me in future

that is why as first step to solve the problem i used Portable Areas to create Addons for each Module, now this will definitely ease my work by dragging 1 DLL for each new Module or Addon, but i have a little problem here, which

  • because the new Module or Addin is a Dll, how can i create such a functionality in My Admin panel to install the new Addon or find any new added Module/Addon dragged new DLLS to the Main Application
  • What is best practice to create an installation procedure inside the Portable Area, like Update the DB, New Routes,etc..

Now to the biggest Problem which is specific to Module Addon :) let us take back the Article Gallery Addon, if i follow the logic i have mentioned above by creating it as a Portable area, it would be easier to create a functionality in the Module Code to loop through all Installed Addons and list them in the CRUD Views, but because i isolated the Addon and don't want to manually update the Main Module Code for the Reasons Above there will be no way for doing CRUD operations for the new Addons in Sync with the main module because there is no Foreign Key Relation, again because as i said above it may be Optional, so i thought of the following solution which i hope there would be a better one

First in Installation Process i will create a Table for the Gallery Addon, but instead of creating a foreign Key relation i will create a manual Foreign Key which will get populated by Generating a Unique ID in the Main Module Controller when i create record by using the following code then store it in ViewData and just pass it to the Addon Controller when i create the new Record,

private  string GenerateId()
 {
  long i = 1;
  foreach (byte b in Guid.NewGuid().ToByteArray())
  {
   i *= ((int)b + 1);
  }
  return string.Format("{0:x}", i - DateTime.Now.Ticks);
 }
ViewData["FK"] = GenerateId();

but here are my Concerns

  • Is this way feasible or just plain Stupid.
  • is this technique will generate a truly unique key.

i am extremely sorry if my question is lame, but this is the best place to ask and i think many people would want to have such a functionality and hope someone will answer me thanks in advanced.

+1  A: 

I think it's a great question. awhile ago I started working on a CMS project using MVC1, where I wanted to support plugins. I had it working so that the admin could drop a new plugin assembly into the bin folder, and next app start, it would scan all assemblies for IPlugin (or whatever) and load them. I embedded the partial views into the plugin assembly so it was all self contained. each plugin was given a unique identifier when it was placed on a page, and the plugin's controller knew how to use that ID to query it's own table (repository) for it's data. the main application didn't know anything about the plugin's schema.

the only difference here is that it sounds like you would have multiple websites running on the same database, and you need to differentiate which instances of the plugin you need for each website. I assume somewhere you've got a key that indicates which website it is, that could be used via foreign key to select only the plugins for that website for the page the user is on.

I'm not sure if this is an answer, I'm sort of just thinking out loud. hopefully it'll help the discussion a little.

EDIT: To automatically load plugins, I used NInject's ability to scan assemblies for IModules. My IPlugin inherits from Ninject.Modules.INinjectModule, and all plugins implement the IPlugin interface. Then on app startup, I have the following line:

kernel.Load( "*.Plugin.dll" );

where kernel is a Ninject.IKernel and that line will scan any assembly matching that file pattern, so I could drop in an assembly like Weather.Plugin.dll.

dave thieben
thanks man for thinking out load, actually what i want to do is same like you, the sites are not running on one central DB,what i meant is that the main DB schema will be repeated on each site, my problem is that i want those Plugins that has no strong Foreign key relation to get the ID of the newly inserted Main Blog Article for example so i can connect them together when i query, and i seem not to be able to find awayanother thing, can you tell me how you search for those new assemblies, i mean any small code would help :)
updated my answer w/ the scanning code. I'm not sure what you mean by "connect them together when i query". could you tell me what you're trying to do?
dave thieben
keeol man,what i meant when querying them, is if you read my question above, i have mentioned that i will have a base Blog Module, and maybe a new Addon (Plugin) that will let you add Images to the article, now my problem as i have mentioned is how when i insert a new Article, i will be able to get it's id and make it a foreign key in the gallery Plugin so when i want to show the article, i can join query the Article Table + the Gallery Plugin table, basically my struggle is in when i hit save i want a mechanism that will get the New article ID and pass it to for example to render action
aha. ok, you will need some sort of table to correlate your articles to their plugins, using the article ID and the unique ID you're generating. you might also need to store the Type (fully qualified typename) of the plugin the ID is for. then when you have a request to load an article, you can find out what plugins ought to be on that page, and pull them from the db. when you add a plugin to the article, you'll need to pass the article ID to the adding action so that it can be stored in this mapping table.
dave thieben
I'm thinking it might also be necessary to in addition to the IPlugin interface, have something like a IPluginRepository interface that is defined in your plugin assembly so that an article can instantiate it and query it for the plugins given the article's ID. because each plugin could have it's own schema and/or persistence mechanism.
dave thieben
thanks alot for the ideas man, but i am still having hard time how to implement it, i mean here is an example, an Article Create page is there and inside the form i use renderaction to load the plugin, now how when i press the save button,MVC will first insert the Article then pass the ID to any plugin then in each plugin you start it's saving to DB logic with the passed ID, i am saying this because when submit the form none of this will happen in a queable manner
make sure the pertinent parameters for the plugin selected are part of the form in form inputs, like hidden in put fields. for example, when the user adds the gallery plugin, you'd probably need to set the plugin classname in a hidden, and say the folder for the images the user selects. then when the form is submitted, those values are available in your Article Create action. in your action, first save the Article so you get the ID for the article, then delegate saving to the plugin and pass the ID of the article.
dave thieben
beautiful man, i have done all the steps you have mentioned, but the stupid question that i have been asking since long time :) , in MVC how i can delegate saving the plugin ?
it would either be on the IPlugin interface or IPluginRepository if you have one. the Article Create action would save the article and then load the plugins selected based on the classname in your hidden input field, and then call plugin.Save(articleId) or whatever.
dave thieben
Brilliant man, only when i submit the form and if the article Model is valid the Plugin Model validation using RenderAction is not being reached, only if the Article Model is not Valid it does, i have found that out through Debugging
that one I don't know about. you might need to post that as a separate question. good luck.
dave thieben
thank u for the great help
please accept as answered if it helped you.
dave thieben