.NET Assembly Loading with Strong Name - asp.net-mvc

How to load the assemblies (example my service layer assemblies) into my MVC application from a location (directory) other than the Bin folder (I dont want to register in GAC)
Can I have a strong name common across all my assemblies I use in my application. Any Disadvantages of having a common strong name for all assemblies?

You can use Assembly.LoadFromFile() with any path. Could be a bit tricky though if the assembly to load requires other libraries which are stored in your default bin folder. It normally works, but I've also seen problems arising there (especially also in unit tests etc.).
What do you mean by "one strong name"? Using the same keyfile for all assemblies? Yes, that's definitely acceptable.

Related

Decoupling went too far - implementation dlls are not included in the bin folder because they are not referenced

It seems I might have gone a bit too far with decoupling.
I have a solution with asp.net projects and I use Ninject as IoC Container.
Most of the crucial parts that are used in the MVC projects are interfaces coming from a dedicated 'Contracts' library.
The actual implementation of the interfaces are located in other assemblies, that are not really referenced directly in the MVC app.
They are completely separate, MVC app only knows Contracts dll.
Ninject is loading all the referenced code in the composition root (at app startup)
kernel.Load("MyAssPrefix.*"); //load binding modules
kernel.Bind(x =>
{
x.FromAssembliesMatching("MyAssPrefix.*")
.SelectAllClasses()
.BindDefaultInterface();
}); //bind all the rest
Now, the problem is that since some of the assemblies are not referenced directly in the app, then dlls are not copied to the bin folder.
This causes problems at runtime - especially difficult, considering that the type has to be called to be resolved and throw error - which means you can compile, deploy and start getting errors weeks later, when some functionality is being used.
I have a 'CompositionRoot' project which is shared among few apps and which specifies some explicit bindings. Of course this project has all the required bits added as reference, but they are not called explicitly, so they are not included.
(When I simply drop required dlls to bin folder, it starts working ok)
I have a workaround for my problem which is to have a module that could bind assemblies, where I call a random class from that assembly which causes the dll to be added to output and it all to work OK.
public class BindAssembliesModule : NinjectModule
{
#region Overrides of NinjectModule
public override void Load()
{
this.Kernel.Bind(x => x.FromAssembliesMatching(typeof(MyAssPrefix.SomeClass).Assembly.GetName().Name).SelectAllClasses().BindDefaultInterface());
}
#endregion
}
This however seems hacky for a few reasons
it is not obvious
its redundant code that is not needed (except to ensure that references are not 'optiomized)
its fragile - if the class that I picked is moved to a different assembly, this stops working
it requires remembering about this hack when new assemblies are added
So, what is the proper way to handle that, what am I doing wrong?
I've had this problem in the past. The way i've got around it is to add a reference to the projects/dlls concerned. MsDeploy will ignore them as they aren't actually used in code, just reference referenced, so they get left behind as you have seen.
Then what I did was follow something like the methodology in this answer: adding extra files to published MVC API project
Which allows you to pick up extra files from the bin folder and get them into the publish stage.
It's a one time fix for the host project and then you can forget about it, it will work fine afterwards.
You can avoid these hacks by:
Create a post-build event in your start-up project and write here a command copying all your dll dependencies to your output folder
Write your custom build script and do the same here

ASP.Net MVC: How to dynamically load assemblies (controllers) without an AppPool restart/recycle

I'm trying to write a module/plugin system for a website I'm working on. The overall goals are:
That the main website does not have to be recompiled every time a new plugin is added.
To be able to dump DLL's and CSHTML files into a set of folders that would basically add a set of routes, controller(s), and any other assemblies that the module depends on (Entity Framework, etc).
To avoid marking plugin files as "embedded resources" -- especially views.
To be able to add and remove these modules/plugins WITHOUT having to restart/recycle the IIS app pool or unload the app domain.
I got #1-3 working by following the example of Umbraco. Basically, I marked a method with the PreApplicationStartMethod attribute, and in it I shadow copy DLLs around, and use a custom ViewEngine to locate the module's CSHTML files. When my website first starts up, my module's controllers and views are working, and assemblies are loaded: Hooray!
However, when it came time to try part #4, I am getting this error when calling BuildManager.AddReferencedAssembly():
This method can only be called during the application's pre-start
initialization phase. Use PreApplicationStartMethodAttribute to
declare a method that will be invoked in that phase
It's been a very frustrating process so far, and my gut tells me that this error signifies a dead end. Is this the case, or is there a clever workaround?
Editing the web.config file when you add the new modules should cause the site to recompile.
You could automate this in a script, forcing your new .dll's to be copied to the live ASP.NET temp files directory.
Check out portable areas. Essentially a regular MVC area (including views, controllers, etc.) gets compiled into a single dll. These dll's (one for each area) can be dropped into a hosting MVC website and can be called like any other MVC area.
Some references to get started:
Portable Areas three years later – Part 5
MvcContrib Portable Areas
"To be able to add and remove these modules/plugins WITHOUT having to restart/recycle the IIS app pool or unload the app domain."
It turns out that this you cannot unload an assembly from an app domain.
How to unload an assembly from the primary AppDomain?

Entity Framework not working when in separate project from MVC3 web application project

I have an Entity Framework Project and a repository class in a separate project from my MVC3 web application. I have established a reference in my MVC project to the Entity Framework data project so i can instantiate an instance of the repository and call the methods thereof. However I get the error:
The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid.
I've run into this before and I believe the solution is to include the connection string from the entity framework app.config file in the MVC web.config file.
This doesn't rest well with me. It feels like there should be another way that would make projects less tightly coupled together. I'm I dreaming or is there a better practice that would allow me just to make call to the referenced dll and be done with it?
Thanks
The app.config file that is included in the DLL of your Entity Framework project contains a Connection String that is used by the EDMX designer to find the target database when running an 'Update Model from Database' command.
When deploying your application, the only configuration file that is known is the web.config. The app.config file from your EF dll is not used in production.
So in your web.config you include the connection string that is used when you are running your MVC application. When using transformations you can also specify different connection strings for different deployment scenarios (test and production for example).
So it's not like you are introducing some sort of coupling. You are just using the configuration methods that .NET offers you.
There are ways, hard-coding the connection string in your repository and using it when you create the context comes to mind, but you most certainly don't want to use them. The right way to handle it is through the configuration file. You really don't want to have it use the configuration file from the DLL, since that would give you less control over what connection string you're using. This would make it harder, rather than easier, to have different connection strings for integration testing, staging, and production. While it's possible to combine the approach (fixed connection string that can be overridden by a configuration setting), having used both my preference is for a completely configuration driven approach. I like the single convention and the one-time step of updating the Web.Config (and any transforms) with the correct configuration setting seems little cost to pay for the simple convention of using the configuration always.
I don't understand how putting a connection string in the MVC project's config file makes it "tightly coupled". The config files themselves are a source for loose coupling. You can always change connection strings using config transforms, meaning you can switch the connection string just by choosing a different solution configuration.

StructureMap configuration: Options to minimize dependencies on the StructureMap assembly

I understand how to implement a StructureMap registry, my question concerns the fact that every project that contains a StructureMap registry requires a static reference to the StructureMap assembly. Is there a best practice for how to structure the configuration for a large number of projects (30+) without forcing each project to take this dependency?
The alternative, I suppose, would be to create a bootstrapper assembly that could be referenced by the host process. The bootstrapper would perform all wire-up. In this scenario, the bootstrap assembly, instead, would have references to all of the projects. This has the upside of centralizing the reference to StructureMap so that all of the projects are unaware of StructureMap.
Using XML-based configuration is not an option for me.
Are there any other options for configuration that minimize the number of static references the projects in the solution must take? I'm guessing that there isn't, but thought I'd solicit some other opinions.
Technically, you only need a single project to reference the container framework, and that is the top-level application project. It references all the other projects and specifies the configuration of the components.
This puts the entire graph configuration out of the hands of each project, opting instead to define graphs only where they are used. This gives each application the complete freedom to configure components, rather than assuming the components will be used in the same way every time (as is implied by the registries which are inherent to each project).
An aside that may or may not be useful: in quantum physics, when we observe a particle, we collapse it from every possible state into a particular one. Frameworks are similar, in that they don't exist in a single state until they are observed, which here means "put to use in an application." This frames the application as the observer, which is the context in which the framework collapses into a single form.
Now, I generally wouldn't want the application be responsible for both being a running application and also configuring that runtime. For this reason, I tend to have a Composition project which references the others as well as the container framework. The actual application project can then reference the Composition project. This externalizes the registries from each project, including the application project, producing a cohesive assembly whose sole purpose is to define the composition of a particular application.

Dependency Injection and loading dependent assembly in .NET

I'm working with dependency injection (DI from now on) to resolve components and am looking for an elegant solution to loading dependent assemblies in a .NET environment. As an explanation, lets say that we have 3 assemblies, A, B and C, where A depends on B and B depends on C. Now I need to load components from assembly A, but because I am using DI, I don't have a reference to assembly A. And even a reference to assembly A wouldn't be enough because I somehow need to ensure that A, B and C all end up in my output directory.
So, some obvious solutions are to:
- add references to A, B and C from the executing application: Requires knowledge of the dependency structure which, in my case, is extremely complex, making this a somewhat undesired solution.
- add these dlls to the GAC: Just not an option in my case.
So I'm wondering if anyone has an elegant solution to this issue. Not sure if it's relevant but I'm using Castle Windsor for DI.
Thanks
Joni
There is an event called AssemblyResolve on your AppDomain that gives you a chance to load missing assemblies. This lets you load your missing assembly from any stream you provide such as a file in a different folder or a file stored in a database.
What would it buy you to load the assemblies dynamically?
You should just add references to A, B, and C in the executing application, unless you're writing an application designed to be extended by other parties, or you have to change the dependencies extremely frequently.
Otherwise, you're solving a trivial problem (the need to recompile to deploy changes) by introducing a different problem (the possibility of failing at runtime).
Think of the list of references as your application's constructor arguments - your application should clearly declare its dependencies instead of tucking them away in a config file.
If the only issue you have is getting the assemblies in the output directory than it's not a Windsor question - it's a MsBuild question (or NAnt or whatever you're using to build your project). Just have your script do it.
If you're looking at extensibility scenario, that is you have the assemblies in the directory and you want to load them, Windsor 2.5 (current trunk) has some pretty nice support for this as well, both from XML and from fluent API.

Resources