Reputation: 2126
I used an example on extensible asp.net mvc 3 to build my plug-able application, but I encountered a problem. In a plug-in I declared and implmemented an interface.
But, in plug-in controller when I want to use this class, the application throws an error and it seems that EntityConfig was not initialized. How can this be fixed?
[Export(typeof(IController)), ExportMetadata("controllerName", "Concept")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ConceptController : Controller
{
[Import(typeof(IEntityConfig))]
private IEntityConfig EntityConfig;
public ActionResult Index()
{
var obs = EntityConfig.EntityName;
return View("~/Bin/Views/Concept/Index.cshtml",obs );
}
}
public interface IEntityConfig
{
string EntityName { get;}
}
[Export(typeof(IEntityConfig))]
public class TestEntity : IEntityConfig
{
public string EntityName
{
get{return "Test";}
}
}
Edited : In other side, when I is use this example, there is no problem in resolving EntityConfig, but in the view, when I want to load model as follows :
@using Concepts
@model Concepts.Models.TestModel
the application throws an error and tells me 'The type or namespace name 'Concepts' could not be found', although when I check container after it was initiated, I can see Concepts in in loaded assemblies.
Would you please help me ? Thanks.
Edited : I uploaded the samples :
Edited (2011/22/09): I tested the above code on other sample that @Matthew Abbott provided in his blog, and it worked, although this sample has been built against mvc 2.0.
Upvotes: 2
Views: 604
Reputation: 61589
Looking over your code, can you be sure that the part is actually being imported? Your constructor code for your composition container is such like:
var discoverableControllerFactory = new DiscoverableControllerFactory(
new CompositionContainer(
new DirectoryCatalog(extensionsPath))
);
You're only including your extensions path as a catalog. Can you guaruntee that you're also including your base application path, e.g.:
var discoverableControllerFactory = new DiscoverableControllerFactory(
new CompositionContainer(
new AggregateCatalog(
new DirectoryCatalog("bin"),
new DirectoryCatalog(extensionsPath)))
);
If the parts actually exist in your Unity container, you could add an export provider that grabs those parts from that container and allows them to be composed by MEF.
As for your second problem, you will need to subclass the System.Web.WebPages.Razor.RazorBuildProvider
to ensure it includes assemblies in your extensions directory:
namespace ExtensibleMvcApplication
{
public class CustomRazorBuildProvider : RazorBuildProvider
{
public static IEnumerable<Assembly> _assemblies;
static CustomRazorBuildProvider()
{
string extensionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Extensions");
_assemblies = Directory.GetFiles(extensionsPath, "*.dll")
.Select(Assembly.Load);
}
public override void GenerateCode(System.Web.Compilation.AssemblyBuilder assemblyBuilder)
{
foreach (var assembly in _assemblies)
assemblyBuilder.AddAssemblyReference(assembly);
base.GenerateCode(assemblyBuilder);
}
}
}
Which you'd need to register in your config:
<buildProviders>
<remove extension=".cshtml" />
<add extension=".cshtml" type="ExtensibleMvcApplication.CustomRazorBuildProvider, ExtensibleMvcApplication"/>
</buildProviders>
Upvotes: 1