ASP.Net, MVC, MEF and loading approved plugins (ie, plugins with known signer) - asp.net-mvc

I'm working on an ASP.Net MVC/MEF based project.
Is it possible to build the catalog such that the DLLs added to the application are approved using a known signer? We don't want to load any old plugin that conforms - just those that have been approved (approving a plugin means its signed with a known key).
Jeff

You need to perform filtering like this before you initialise the MEF catalog. I.e., if you're using AssemblyCatalog:
var assemblies = // all assemblies
var catalog = new AggregateCatalog(
assemblies
.Where(a => IsAcceptable(a))
.Select(a => new AssemblyCatalog(a))
);
You need to supply the IsAcceptable method to perform assembly filtering as appropriate:
bool IsAcceptable(Assembly a) { ... }

var c = X509Certificate.CreateFromSignedFile(assemblyFile);
if (c.Issuer = "Joe") ...
just an idea, didnt tried :) let us know if it works..

Related

Use ASP.NET MVC Unity for Data Caching

I have a ASP.Net MVC project running on .NET 4.6.1 Framework.
I have recently added Unity.Mvc 5 IoC framework for dependency injection
In order to have flexibility for unit testing and other, I moved my Unity Configuration to a separate class library so that I can call the Unity Register methods from Unit test projects and other as needed.
Here is my high-level solution design.
I would like to use the same class library to implement application cache.
When I installed Unity.Mvc5 from nuget package it added following references (I added some of them manually) :
Microsoft.Practices.EnterpriseLibrary.Caching 5.0.505.0
Enterprise Library Shared Library 5.0.505.0
Microsoft.Practices.ServiceLocation 1.3.0.0
Microsoft.Practices.Unity 4.0.0.0
Microsoft.Practices.Unity.Configuration 4.0.0.0
Microsoft.Practices.Unity.Interception 2.1.505.0
Microsoft.Practices.Unity.Interception.Configuration 2.1.505.0
Microsoft.Practices.Unity.RegistrationByConvention 4.0.0.0
I tried few articles to implement Application Block Cache Management so that I can cache data in my Service Implementer layers, but all those documentations are showing code examples which is expecting Unity 2.xxx version.
Here is my Unity Configuration
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<UserManager<User>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<User>, UserStore<User>>(new HierarchicalLifetimeManager());
container.RegisterType<DbContext, OfficeGxDbContext>(new HierarchicalLifetimeManager());
container.RegisterType<IAppSetting, AppSettingService>();
container.RegisterType<ISubscription, SubscriptionService>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
In my AppSettingService.cs I have get all method
public List<AppSetting> All()
{
using (var context = new MyDbContext())
{
//CachecKeyItem.AppSettingsAll
return context.AppSettings.Where(x => !x.IsDeleted)
.Include(x => x.Module).ToList();
}
}
I want to store this data in cache and reuse it. Similarly do this across all projects I have in my solution and if there is any update or add or delete for any DB records, I want the cached object to refresh it so that cached object is always in sync with DB data
I ended up doing something like this
public interface ICacheService
{
T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class;
}
Service Implementor
public class InMemoryCache : ICacheService
{
public T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class
{
if (MemoryCache.Default.Get(cacheKey) is T item) return item;
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(8));
return item;
}
}
use like this
_cacheService.GetOrSet(CachecKeyItem.AppSettingsAll, () => context.AppSettings
.Where(x => !x.IsDeleted)
.Include(x => x.Module).ToList());
Now my question is, when there is any change to data, like add/edit/delete, how do I refresh the cache in most efficient way? I know deleting the key would be one, is there a better way?
It slightly depends on if your running in a single server system or multi server system. Its generally better to always design for multi-server that way if you ever decide to scale out your already sorted.
So assuming you can get a message to fire off when your cache invalidates to all the servers without issue then the easiest way is to delete your cache key... now that also brings a few areas of optimization that can be looked at.
Is this cached data utilized heavily, in which case may you benefit from a pre-fetch cache where you either send the updated cached entry to all servers or require all servers to ask for it? Is it used very little in which case you don't really want to re-populate until its requested otherwise your needlessly bloating your application.

Autofac Fails to Resolve after App Pool Recycle

I've used Autofac for years and never seen this behavior: after building, the app runs fine. However, after the app pool is recycled (I tested this by touching the web.config), I get a DependencyResolutionException:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Namespace.Controllers.HomeController' can be invoked with the available services and parameters
HomeController has one dependency, which has other dependencies, etc. But I know it can resolve them, because it does before it's recycled. Why on earth would this happen???
I autowire everything like so:
public static IContainer GetAutoFacContainer()
{
var builder = new ContainerBuilder();
var assembliesToRegister = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => a.FullName.StartsWith("Prefix")).ToArray();
builder.RegisterAssemblyTypes(assembliesToRegister)
.AsImplementedInterfaces().AsSelf().PropertiesAutowired().InstancePerLifetimeScope();
return builder.Build();
}
Then I use the container for WebAPI and MVC Controllers.
var autoFacContainer = DependencyRegistrar.GetAutoFacContainer();
DependencyResolver.SetResolver(new AutofacDependencyResolver(autoFacContainer));
GlobalConfiguration.Configuration.DependencyResolver =
new AutofacWebApiDependencyResolver(autoFacContainer);
Thanks to Steven's comment above, I did find the answer on the other question as well as the Autofac site. Why these never turned up in my research I don't know.
http://docs.autofac.org/en/latest/faq/iis-restart.html
The Solution
Change AppDomain.CurrentDomain.GetAssemblies()
To BuildManager.GetReferencedAssemblies().Cast<Assembly>()
Done!

Why should Ninject dlls be in the Web/bin folder? Can't I just put them in the GAC?

My company has got a deployment policy (I skip the details) such that any 3rd party software should be installed in the GAC, whilst our libraries are in Web/bin folder. But this approach doesn't work with Ninject and MVC 3/4. Let's follow an example:
This is my dependencies binding code:
public class RequestorDependenciesRegistration : NinjectModule
{
public override void Load()
{
Bind<IMyDearDependency>().To<MyDearImplementation>();
}
}
And this is my MVC controller:
public MyController(IMyDearDependency something) {
this.something = something; // 'something' is set only if Ninject dlls are in Web/bin... X-(
}
If Ninject dlls are in the GAC, it loads the module correctly, but when instantiating the MVC Controller the dependency is not injected (in some cases is null, in some cases MVC returns an error "No parameterless constructor etc etc"). If I manually copy Ninject*.dll in the Web/bin folder, than everything works fine, even without restarting IIS! Can't really understand why...
Even more surprisingly (for me), if I do something super-dirty like storing a reference to the Ninject Kernel instance in a public static property and use it as a ServiceLocator, it works! (Something dirty like this, in the MVC controller):
public MyController(IMyDearDependency something) { // 'something' is always null if Ninject is only in the GAC...
var controller = Kernel.Get<MyController>()
this.something = controller.something; // ... but this 'controller.something' is set, even if Ninject is only in the GAC!!! 8-O
}
Can anyone suggest me the reason why? And possibly a solution? :-) Many thanks!!
Ninject has a built in extension loading mechanism which is used to load the different extension like the Ninject.Web.Mvc.
But mechanism is looking only for the application folder to load the extensions so if your dll are in the GAC Ninject won't find them.
To solve this you can turn off the automatic extension loading and load the MvcModule module by hand when creating your StandardKernel:
var _kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new MvcModule(),
/* your other modules * /);

How can we support modular and testable patterns with ASP.NET MVC 4 and MEF 2?

We're trying to use MEF 2 with ASP.NET MVC 4 to support an extensible application. There are really 2 parts to this question (hope that's okay SO gods):
How do we use Microsoft.Composition and the MVC container code (MEF/MVC demo source) to replace Ninject as our DI for ICoreService, ICoreRepository, IUnitOfWork, and IDbContext?
It looks like we can't use both Ninject and the MVC container at the same time (I'm sure many are saying "duh"), so we'd like to go with MEF, if possible. I tried removing Ninject and setting [Export] attributes on each of the relevant implementations, spanning two assemblies in addition to the web project, but Save() failed to persist with no errors. I interpreted that as a singleton issue, but could not figure out how to sort it out (incl. [Shared]).
How do we load multiple assemblies dynamically at runtime?
I understand how to use CompositionContainer.AddAssemblies() to load specific DLLs, but for our application to be properly extensible, we require something more akin to how I (vaguely) understand catalogs in "full" MEF, which have been stripped out from the Microsoft.Composition package (I think?); to allow us to load all IPluggable (or whatever) assemblies, which will include their own UI, service, and repository layers and tie in to the Core service/repo too.
EDIT 1
A little more reading solved the first problem which was, indeed, a singleton issue. Attaching [Shared(Boundaries.HttpRequest)] to the CoreDbContext solved the persistence problem. When I tried simply [Shared], it expanded the 'singletonization' to the Application level (cross-request) and threw an exception saying that the edited object was already in the EF cache.
EDIT 2
I used the iterative assembly loading "meat" from Nick Blumhardt's answer below to update my Global.asax.cs code. The standard MEF 2 container from his code did not work in mine, probably because I'm using the MEF 2(?) MVC container. Summary: the code listed below now works as desired.
CoreDbContext.cs (Data.csproj)
[Export(typeof(IDbContext))]
[Shared(Boundaries.HttpRequest)]
public class CoreDbContext : IDbContext { ... }
CoreRepository.cs (Data.csproj)
[Export(typeof(IUnitOfWork))]
[Export(typeof(ICoreRepository))]
public class CoreRepository : ICoreRepository, IUnitOfWork
{
[ImportingConstructor]
public CoreRepository(IInsightDbContext context)
{
_context = context;
}
...
}
CoreService.cs (Services.csproj)
[Export(typeof(ICoreService))]
public class CoreService : ICoreService
{
[ImportingConstructor]
public CoreService(ICoreRepository repository, IUnitOfWork unitOfWork)
{
_repository = repository;
_unitOfWork = unitOfWork;
}
...
}
UserController.cs (Web.csproj)
public class UsersController : Controller
{
[ImportingConstructor]
public UsersController(ICoreService service)
{
_service = service;
}
...
}
Global.asax.cs (Web.csproj)
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
CompositionProvider.AddAssemblies(
typeof(ICoreRepository).Assembly,
typeof(ICoreService).Assembly,
);
// EDIT 2 --
// updated code to answer my 2nd question based on Nick Blumhardt's answer
foreach (var file in System.IO.Directory.GetFiles(Server.MapPath("Plugins"), "*.dll"))
{
try
{
var name = System.Reflection.AssemblyName.GetAssemblyName(file);
var assembly = System.Reflection.Assembly.Load(name);
CompositionProvider.AddAssembly(assembly);
}
catch
{
// You'll need to craft exception handling to
// your specific scenario.
}
}
}
}
If I understand you correctly, you're looking for code that will load all assemblies from a directory and load them into the container; here's a skeleton for doing that:
var config = new ContainerConfiguration();
foreach (var file in Directory.GetFiles(#".\Plugins", "*.dll"))
{
try
{
var name = AssemblyName.GetAssemblyName(file);
var assembly = Assembly.Load(name);
config.WithAssembly(assembly);
}
catch
{
// You'll need to craft exception handling to
// your specific scenario.
}
}
var container = config.CreateContainer();
// ...
Hammett discusses this scenario and shows a more complete version in F# here: http://hammett.castleproject.org/index.php/2011/12/a-decent-directorycatalog-implementation/
Note, this won't detect assemblies added to the directory after the application launches - Microsoft.Composition isn't intended for that kind of use, so if the set of plug-ins changes your best bet is to detect that with a directory watcher and prompt the user to restart the app. HTH!
MEF is not intended to be used as DI framework. Which means that you should separate your "plugins" (whatever they are) composition from your infrastructure dependencies, and implement the former via MEF and the latter via whatever DI framework you prefer.
I think there are a little misunderstandings on what MEF can and can't do.
Originally MEF was conceived as purely an extensibility architecture, but as the framework evolved up to its first release, it can be fully supported as a DI container also. MEF will handle dependency injection for you, and does so through it's ExportProvider architecture. It is also entirely possible to use other DI frameworks with MEF. So in reality there are a number of ways things could be achieved:
Build a NinjectExportProvider that you can plug into MEF, so when MEF is searching for available exports, it will be able to interrogate your Ninject container.
Use an implementation of the Common Services Locator pattern to bridge between MEF and Ninject or vice versa.
Because you are using MEF for the extensibility, you'll probably want to use the former, as this exposes your Ninject components to MEF, which in turn exposes them to your plugins.
The other thing to consider, which is a bit disappointing, is in reality there isn't a lot of room for automagically plugging in of features ala Wordpress on ASP.NET. ASP.NET is a compiled and managed environment, and because of that you either resort to late-binding by loading assemblies manually at runtime, or you restart the application to pick up the new plugins, which sort of defeats the object of being able to plug new extensions in through the application.
My advice, is plan your architecture to pick up any extensibility points as startup and assume that any core changes will require a deployment and application restart.
In terms of the direct questions asked:
The CompositionProvider accepts in instance of ContainerConfiguration which is used internally to create the CompositionContainer used by the provider. So you could use this as the point by which you customise how you want your container to be instantiated. The ContainerConfiguration supports a WithProvider method:
var configuration = new ContainerConfiguration().WithProvider(new NinjectExportDescriptorProvider(kernel));
CompositionProvider.SetConfiguration(configuration);
Where NinjectExportDescriptorProvider might be:
public class NinjectExportDescriptorProvider: ExportDescriptorProvider
{
private readonly IKernel _kernel;
public NinjectExportDescriptorProvider(IKernel kernel)
{
if (kernel == null) throw new ArgumentNullException("kernel");
_kernel = kernel;
}
public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(
CompositionContract contract, DependencyAccessor dependencyAccessor)
{
var type = contract.ContractType;
if (!_kernel.GetBindings(type).Any())
return NoExportDescriptors;
return new[] {
new ExportDescriptorPromise(
contract,
"Ninject Kernel",
true, // Hmmm... need to consider this, setting it to true will create it as a shared part, false as new instance each time,
NoDependencies,
_ => ExportDescriptor.Create((c, o) => _kernel.Get(type), NoMetadata)) };
}
}
}
Note: I have not tested this, this is all theory, and is based on the example AppSettingsExportDescriptorProvider at: http://mef.codeplex.com/wikipage?title=ProgrammingModelExtensions
It's different from using the standard ExportProvider, because using the CompostionProvider is built around lightweight composition. But essentially you're wrapping up access to your Ninject kernel and making it available to your CompositionContainer.
As with adding a specific new provider (see above), you can use the ContainerConfiguration to read the available assemblies, probably something like:
var configuration = new ContainerConfiguration().WithAssemblies(AppDomain.GetAssemblies())
Again, I haven't tested all of this, but I hope it at least points you in the right direction.

Spring .Net Configuration Fluently

I have the need to use Spring .Net in a project and am exploring configuration options. All I can find about config for Spring .Net is config file stuff. Does Spring support configuration in code? I have used Castle and Ninject, and both seem to offer this natively. I have found projects that claim to add support, but I dont want some knock off project that will die in 6 months. I have found references in blogs that seem to indicate Spring supports this but I cant find any documentation!!
Part 2 of this might be would you recommend Spring .Net over Windsor knowing it cant support fluent configuration? I know both are great IoC containers, but I have worked on projects that have massive config files for Spring configuration and I hate it.
No, the current version (1.3) of Spring.NET only supports XML configuration. There has been talk about supporting Code as Configuration in future versions, but this has not yet materialized.
In my opinion, Castle Windsor is far superior to Spring.NET. I can't think of a single feature of Spring.NET that Castle Windsor doesn't have. On the other hand, Castle Windsor has the following features that are not available in Spring.NET:
Code as Configuration
Convention-based configuration
More lifetimes
Custom lifetimes
Object graph decommissioning
Explicit mapping of interfaces/base classes to concrete types
Type-based resolution
Modular configuration (Installers)
Built-in support for Decorators
Typed Factories
There are probably other features I forgot about...
It appears I was a bit too quick on the trigger here, although to my defense, the Spring.NET documentation also states that there's only XML configuration in the current version.
However, it turns out that if for certain contexts, a very primitive API is available that enables you to configure a context without XML. Here's an example:
var context = new GenericApplicationContext();
context.RegisterObjectDefinition("EggYolk",
new RootObjectDefinition(typeof(EggYolk)));
context.RegisterObjectDefinition("OliveOil",
new RootObjectDefinition(typeof(OliveOil)));
context.RegisterObjectDefinition("Mayonnaise",
new RootObjectDefinition(typeof(Mayonnaise),
AutoWiringMode.AutoDetect));
Notice how this API very closely mirrors the XML configuration schema. Thus, you don't get any fluent API from the IObjectDefinitionRegistry interface, but at least there's an API which is decoupled from XML. Building a fluent API on top of this is at least theoretically possible.
You will find a fully working spring fluent API for spring.net on github:
https://github.com/thenapoleon/Fluent-API-for-Spring.Net
This API brings fluent configuration, and will soon support convention based configuration.
In answer to the first part of your question: the springsource team appears to be working on a code configuration project on github: https://github.com/SpringSource/spring-net-codeconfig. It was announced with (but not included in) the 1.3.1 (december 2010) release.
From the MovieFinder example:
[Configuration]
public class MovieFinderConfiguration
{
[Definition]
public virtual MovieLister MyMovieLister()
{
MovieLister movieLister = new MovieLister();
movieLister.MovieFinder = FileBasedMovieFinder();
return movieLister;
}
[Definition]
public virtual IMovieFinder FileBasedMovieFinder()
{
return new ColonDelimitedMovieFinder(new FileInfo("movies.txt"));
}
}
There is another option using the Spring.AutoRegistration. The same concept used with Unity AutoRegistration.
https://www.nuget.org/packages/Spring.AutoRegistration
http://autoregistration.codeplex.com/
var context = new GenericApplicationContext();
context.Configure()
.IncludeAssembly(x => x.FullName.StartsWith("Company.ApplicationXPTO"))
.Include(x => x.ImplementsITypeName(), Then.Register().UsingSingleton()
.InjectByProperty(If.DecoratedWith<InjectAttribute>))
.ApplyAutoRegistration();
It is also possible to use Spring.FluentContext project.
With it, the configuration of MovieFinder would look as follows:
// Configuration
private static IApplicationContext Configure()
{
var context = new FluentApplicationContext();
context.RegisterDefault<MovieLister>()
.BindProperty(l => l.MovieFinder).ToRegisteredDefaultOf<ColonDelimitedMovieFinder>();
context.RegisterDefault<ColonDelimitedMovieFinder>()
.UseConstructor((FileInfo fileInfo) => new ColonDelimitedMovieFinder(fileInfo))
.BindConstructorArg().ToValue(new FileInfo("movies.txt"));
return context;
}
// Usage
static void Main(string[] args)
{
IApplicationContext context = Configure();
var movieLister = context.GetObject<MovieLister>();
foreach (var movie in movieLister.MoviesDirectedBy("Roberto Benigni"))
Console.WriteLine(movie.Title);
Console.ReadLine();
}
It does not require any hardcoded literal ID for objects (but allows that), it is type safe and contains documentation with samples on GitHub wiki.
Using the Fluent-API-for-Spring.Net, the configuration could look something like:
private void ConfigureMovieFinder()
{
FluentApplicationContext.Clear();
FluentApplicationContext.Register<ColonDelimitedMovieFinder>("ColonDelimitedMovieFinder")
.BindConstructorArgument<FileInfo>().To(new FileInfo("movies.txt"));
// By default, fluent spring will create an identifier (Type.FullName) when using Register<T>()
FluentApplicationContext.Register<MovieLister>()
.Bind(x => x.MovieFinder).To<IMovieFinder>("ColonDelimitedMovieFinder");
}

Resources