ASP.NET MVC & MEF - Pluggable architecture - asp.net-mvc

I started creating a PoC following SO this post but I wasn't able to get a very basic sample to work.
What I did:
I created an ASP.NET MVC project using empty template and MVC references.
I added Bootstrapper, CustomControllerFactory and CustomViewEngine classes and also the corresponding lines in Application_Start.
I created an ASP.NET MVC project using MVC template.
I added the Export and PartCreationPolicy decorators on HomeController.
I published the module project to a folder inside /Modules directory -in WebHost root path.
What didn't work:
The method CompositionContainer.GetExportedValue throws an exception saying that it couldn't load one or more required types and that there is more information on LoaderExceptions property. That property is an array with 77 instances of what appears to be the same exception:
Could not load file or assembly Antlr3.Runtime, Version=3.4.1.9004, Culture=neutral, PublicKeyToken=eb42632606e9261f or one of its dependencies.
In FusionLog property I can see that the problem is related to the assembly version (see here).
I found a workaround for "solving" this by copying the dependentAssembly declarations from the module's web.config to the WebHost configuration file. However I'd like to avoid this as the WebHost should not be modified based on the module's needs.
Even after the workaround, it didn't work. While rendering the view, it threw this exception:
CS0234: The type or namespace name 'Optimization' does not exist in the namespace 'System.Web' (are you missing an assembly reference?)

For your help is share a full test project using MEF. visit this github link.
You need something like--
public class AzRDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly CompositionContainer _container;
public AzRDependencyResolver(CompositionContainer container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
return this;
}
/// <summary>
/// Called to request a service implementation.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementation or null.</returns>
public object GetService(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var name = AttributedModelServices.GetContractName(serviceType);
var export = _container.GetExportedValueOrDefault<object>(name);
return export;
}
/// <summary>
/// Called to request service implementations.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementations.</returns>
public IEnumerable<object> GetServices(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var exports = _container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
return exports;
}
public void Dispose()
{
}
}

Related

Custom IServicePovider is not always used

In the startup.cs, I want to define an extended ServiceProvider: It basically wraps the default IServiceProvider implementation.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
[...]
var servicesProvider = services.BuildExtendedServiceProvider();
return servicesProvider;
}
Here is the core extended service provider implementation
/// <summary>
/// Extends the native asp.net service provider
/// </summary>
public class ExtendedServicesProvider : IServiceProvider
{
private readonly IServiceProvider _serviceProvider;
/// <summary>
/// Creates a new instance of <see cref="ExtendedServicesProvider"/> provider based on the native mvc <see cref="IServiceProvider"/>
/// </summary>
/// <param name="serviceProvider"></param>
public ExtendedServicesProvider(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
/// <inheritDoc />
public object GetService(Type serviceType)
{
var resolvedService = _serviceProvider.GetService(serviceType);
[...]
return resolvedService;
}
}
At startup, I can see that GetService is called for each service with "singleton" life time (great!!)
However, it is not called anymore after that, and the default ServiceProvider is called instead...
By the way, if I request the resolution of IServiceProvider, this is the native one that I get.
I would like my serviceProvider to replace completely the native one and to be called EVERY TIME.
Did I miss something??
Ok, I just checked the source code (I should have checked before posting the question sorry).
https://github.com/aspnet/DependencyInjection/blob/master/src/Microsoft.Extensions.DependencyInjection/ServiceProvider.cs
The build method adds by itself the IServiceProvider type with the native instance.
As there seem to have no way to modify it properly (without reflection on "_table" field I mean :-). It seems to me that the approach is clearly not good.
I think I'll try other dependency injection engines such as Autofac, but I really wanted to keep the native engine that seemed to me really light weight.

Moving ApplicationUser and other models out of MVC project

How can I split the properties, functionality and classes out of the default ASP.Net Mvc / Identity 2.0? I am battling with a few things:
by default, it wants to use OWIN's context to wire up some kind of dependency injection, and control the Managers
it puts the ApplicationDbContext at the application level, where my architecture requires it be available at "lower" levels.
It requires that I declare any properties in the same class as the functionality that acts on those properties (which doesn't fit in with my architecture)
The ApplcationUser model has dependencies on Asp.Net, which I would like to break if I am to move the POCO to a non-MVC layer of the solution
Application architecture:
I have a solution that has several tiers :
Api - defines interfaces for services
Domain - stores POCO models representing a business domain
Business - stores logic for interacting with domain objects, and consumes services
Service - implementation of services, including Entity Framework, and the structure maps for the domain objects
Application - in this case, an MVC application.
My business layer only knows about service interfaces, not implementation, and I am using dependency injection to wire everything up.
I have some interfaces defining read/write/unit of work operations for a data service, and an implementation of these that inherit from DbContext (in my Service layer). Instead of having a series of DbSet<MyPoco> MyPocos {get;set;}, I am wiring it up by passing a series of type configurations that define relationships, then accessing my types through Set<Type>(). All that works great.
This stack has been in place for an existing application, and works well. I know it will transition to an MVC application, and am only having issues with the "out of the box" ASP.Net Identity-2.
My solution to this was to: Abstract all the things
I got around this by abstracting most of the functionality of identity into its own project which allowed for easier unit testing and reuse of the abstraction in other projects.
I got the idea after reading this article
Persistence-Ignorant ASP.NET Identity with Patterns
I then fine tuned the idea to suit my needs. I basically just swapped out everything I needed from asp.net.identity for my custom interfaces which more or less mirrored the functionality provided by the framework but with the advantage of easier abstractions and not implementations.
IIdentityUser
/// <summary>
/// Minimal interface for a user with an id of type <seealso cref="System.String"/>
/// </summary>
public interface IIdentityUser : IIdentityUser<string> { }
/// <summary>
/// Minimal interface for a user
/// </summary>
public interface IIdentityUser<TKey>
where TKey : System.IEquatable<TKey> {
TKey Id { get; set; }
string UserName { get; set; }
string Email { get; set; }
//...other code removed for brevity
}
IIdentityManager
/// <summary>
/// Exposes user related api which will automatically save changes to the UserStore
/// </summary>
public interface IIdentityManager : IIdentityManager<IIdentityUser> { }
/// <summary>
/// Exposes user related api which will automatically save changes to the UserStore
/// </summary>
public interface IIdentityManager<TUser> : IIdentityManager<TUser, string>
where TUser : class, IIdentityUser<string> { }
/// <summary>
/// Exposes user related api which will automatically save changes to the UserStore
/// </summary>
public interface IIdentityManager<TUser, TKey> : IDisposable
where TUser : class, IIdentityUser<TKey>
where TKey : System.IEquatable<TKey> {
//...other code removed for brevity
}
IIdentityResult
/// <summary>
/// Represents the minimal result of an identity operation
/// </summary>
public interface IIdentityResult : System.Collections.Generic.IEnumerable<string> {
bool Succeeded { get; }
}
In my default implementation of the identity manager, which also lives in its own project, I simply wrapped the ApplicationManager and then mapped results and functionality between my types and the asp.net.identity types.
public class DefaultUserManager : IIdentityManager {
private ApplicationUserManager innerManager;
public DefaultUserManager() {
this.innerManager = ApplicationUserManager.Instance;
}
//..other code removed for brevity
public async Task<IIdentityResult> ConfirmEmailAsync(string userId, string token) {
var result = await innerManager.ConfirmEmailAsync(userId, token);
return result.AsIIdentityResult();
}
//...other code removed for brevity
}
The application layer is only aware of the abstractions and the implementation is configured at startup. I don't have any using Microsoft.AspNet.Identity at the higher level as they are all using the local abstractions.
the tiers can look like this :
Api - defines interfaces for services (including Identity abstraction interfaces)
Domain - stores POCO models representing a business domain
Business - stores logic for interacting with domain objects, and consumes services
Service - implementation of services, including Entity Framework, and the structure maps for the domain objects
Identity - implementation of Microsoft.AspNet.Identity specific services, including Microsoft.AspNet.Identity.EntityFramework; and OWIN configuration
Application - in this case, an MVC application.
In MVC Application layer the AccountController thus only needed
using MyNamespace.Identity.Abstractions
public partial class AccountController : Controller {
private readonly IIdentityManager userManager;
public AccountController(IIdentityManager userManager) {
this.userManager = userManager;
}
//...other code removed for brevity
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Signin(LoginViewModel model, string returnUrl) {
if (ModelState.IsValid) {
// authenticate user
var user = await userManager.FindAsync(model.UserName, model.Password);
if (user != null) {
//...code removed for brevity
} else {
// login failed
setFailedLoginIncrementalDelay();
ModelState.AddModelError("", "Invalid user name or password provided.");
}
}
//TODO: Audit failed login
// If we got this far, something failed, redisplay form
return View(model);
}
}
This assumes you are using some DI framework. It is only in the configuring of the IoC that any mention is made of the layer that implements identity completely abstracting it away from those that have need of using identity.
//NOTE: This is custom code.
protected override void ConfigureDependencies(IContainerBuilder builder) {
if (!builder.HasHandler(typeof(IIdentityManager))) {
builder.PerRequest<IIdentityManager, DefaultUserManager>();
}
}

Accessing Methods/Properties from a class in a separate project without adding reference to the project containing the class (Same solution)

I'm not sure if the title correctly describes my problem. If someone could better describe my problem by reading the following description, please help me by editing the title to something more meaningful.
I'm trying to learn asp.net MVC with Entity Framework and Ninject.
I was having a look at NuGet Gallery application on GitHub and tried to implement a few parts in my project.
I followed the answer provided in this question [How do architect an ASP.Net MVC app with EF?] and designed my project with the following layered structure.
MyDemoApp
MyDemoApp.Domain (Contains POCO Classes)
MyDomain.Service (Contains references to Domain,EF. It contains only Interfaces)
MyDemoApp.Data (Contains references to EF, Domain, Service. It contains classes dealing with Entity Context and Repository)
MyDemoApp.Web (Contains references to ApplicationModel,Data,Domain,Service,Ninject)
MyDemoApp.ApplicationModel (Contains references to Data, Domain, Serivce. It implements the classes from Service project)
MyDemoApp.Web has no business logic and is acting like Humble Object, as mentioned in this answer
I have a Interface IConfiguration in MyDemoApp.Service project which is being implemented by Configuration class located in MyDemoApp.Web where I'm trying to read the connection string. I need to pass this connection string to the object of EntityContext being created in EntityContextFactory located in MydemoApp.Data
If I add a project reference of MyDemoApp.web to MyDemoApp.Data then Visual Studio Prompts me saying that it would cause a circular reference
In the following code return new EntitiesContext(""); How should I pass a parameter over here that would get the connection string that my bindings.cs gets ?
namespace MyDemoApp.Data
{
public class EntitiesContextFactory : IDbContextFactory<EntitiesContext>
{
public EntitiesContext Create()
{
//TO-DO : Get the Connnectionstring
return new EntitiesContext(""); //Need to pass connection string by calling property from Configuration class in MyDemoApp.Web project
}
}
public class EntitiesContext:DbContext,IEntitiesContext
{
public EntitiesContext(string connectionString) : base(connectionString)
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Provide mapping like foreign key
}
}
}
}
Configuration.cs:
namespace MydemoApp.Web
{
public class Configuration : IConfiguration
{
public string ConnectionString
{
get
{
return ConfigurationManager.ConnectionStrings['dev'].ConnectionString;
}
}
}
}
Bindings.cs:
namespace MydemoApp.Web.Bindings
{
public class MyModule : NinjectModule
{
public override void Load()
{
Bind<IConfiguration>().To<Configuration>();
var configuration = new Configuration(); //Gives me Connectionstring
Bind<IEntitiesContext>().ToMethod(context => new EntitiesContext(configuration.ConnectionString)); // This part would help me pass the connection string to the constructor
}
}
}
I don't quite get what problem you are facing. I assume that you need to access a class in Web assembly from Data assembly, but Data assembly already referencing Web assembly.
Can you just inject the configuration interface to your factory constructor, and use that to get the connection string?
public class EntitiesContextFactory : IDbContextFactory<EntitiesContext>
{
public EntitiesContextFactory(IConfiguration configuration){
this.configuration = configuration;
}
IConfiguration configuration;
public EntitiesContext Create()
{
return new EntitiesContext(configuration.ConnectionString);
}
}
I may misunderstand your question though.
Personally, I think you should leverage the ConfigurationManager in your EntitiesContextFactory.
This would look like:
return new EntitiesContext(System.Configuration.ConfigurationManager.ConnectionStrings["{connectionstringname}"].ConnectionString)
This class is agnostic of whether it is an app.config or web.config that is providing the configuration.
All it stipulates is that application that is hosting the dlls for running, must be configured with an (app/web).config that contains that connection string. your app can test for this at startup since it knows it has a dependency on a database connection for it to work.

Using Ninject from an external project to resolve dependencies

I'm currently working on a project whereby I will be developing views that will be pre-compiled and will be part of an external MVC 3.0 web solution I do not have any control over.
Part of my requirements is that I will need to access an underlying database in order to get some data. I would like to use Ninject (I've been informed that's what the external solution uses) to inject the database instance into my controllers as necessary.
I understand that you add the bindings in such a place as the Global.asax however I do not have access to this as that is part of the external solution out of my control.
Is there anyway I can create this dependency injection in my project that contains the pre-compiled views etc and ensure it is resolved when the external project loads our controller?
If this is too vague let me know and I'll try and offer more information.
EDIT:
Initially upon taken on Darin's suggestion I got the exception below:
System.InvalidOperationException crossed a native/managed boundary
Message=Sequence contains no elements
Source=System.Core
StackTrace:
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectMvcHttpApplicationPlugin.cs:line 53
at Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:line 52
at Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:line 32
at Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:line 52
at MyApp.App_Start.NinjectWebCommon.Start() in C:\App\NinjectWebCommon.cs:line 28
InnerException:
However upon thinking about it, the bootstrapper should already be initialised in our external MVC application (assuming they are using this method I guess). So I don't need to do all the initialisation all I need to do is register my dependencies with the current Kernal.
Something like:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
RegisterServices(bootstrapper.Kernel);
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IDataContext>().To<ApiDataContext>();
}
}
When doing this I now get the items injected. However I'm not 100% this is the correct solution but it seems to work?
I understand that you add the bindings in such a place as the Global.asax
Not necessarily. Have you recently installed the Ninject.MVC3 NuGet in a new MVC application? If you haven't I invite you to do so now. Simply create a new ASP.NET MVC 3 project using the Internet Application template in Visual Studio and install this NuGet. Ready?
After doing that you will notice that the NuGet package created in App_Start folder to your project. It didn't touch at any Global.asax. Now let's inspect the contents of the NinjectWebCommon.cs file added to this folder:
[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]
namespace MvcApplication1.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
}
}
}
Notice the WebActivator's PreApplicationStartMethod and ApplicationShutdownMethodAttribute assembly attributes that allow you to plug code that executes when an ASP.NET application respectively starts and shuts down.
Alright, now simply put this code in your library and configure your kernel in the RegisterServices method.

This module requires that the HttpApplication implements IContainerProviderAccessor

Hi
I want to use Autofac in my asp.net mvc appliation and here is the code I have in global.asxc file :
protected void Application_Start()
{
....
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
but when I run the project, I see this error :
This module requires that the HttpApplication (Global Application Class) implements IContainerProviderAccessor
what is wrong ?
I had the same problem as the OP, but my solution was different.
From here:
Remove Old Items
Remove IContainerProviderAccessor interface from Global.asax. This implementation is no longer used by ASP.NET MVC integration.
Remove references to the AutofacControllerFactory. The new MVC integration uses the MVC DependencyResolver class for integration instead.
Remove ASP.NET Autofac HTTP module configurations. Previously there were some Autofac ContainerDisposal and PropertyInjection modules required in your web.config. These should be removed.
A minimal global.asax.cs setup for autofac for asp.net mvc3 could look like this:
(RegisterRoutes is removed from the code). As opposed to previous versions of asp.net mvc (from http://code.google.com/p/autofac/wiki/Mvc3Integration)
the HttpApplication class no longer needs to implement the IContainerProviderAccessor interface as described in the ASP.NET Integration documentation. All code related to implementing the interface should be removed your Global.asax.cs file.
You will also need a reference to Autofac.Integration.Mvc.dll
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;
using Autofac.Integration.Mvc;
namespace ApplicationX
{
public class MvcApplication : HttpApplication
{
private static IContainer _container;
/// <summary>
/// Gets the container.
/// </summary>
public IContainer Container
{
get { return _container; }
}
// RegisterRoutes and RegisterGlobalFilters removed ...
/// <summary>
/// Fired when the first resource is requested from the web server and the web application starts
/// </summary>
protected void Application_Start()
{
// Register: create and configure the container
_container = BootstrapContainer();
DependencyResolver.SetResolver(new AutofacDependencyResolver(_container));
// MVC Stuff
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
/// <summary>
/// Fired when the web application ends
/// </summary>
public void Application_End()
{
// Release: remember to dispose of your container when your application is about to shutdown to let it gracefully release all components and clean up after them
_container.Dispose();
}
/// <summary>
/// Bootstrapper is the place where you create and configure your container
/// </summary>
/// <returns>An Autofac container</returns>
private IContainer BootstrapContainer()
{
var builder = new ContainerBuilder();
// You can make property injection available to your MVC views by adding the ViewRegistrationSource to your ContainerBuilder before building the application container.
builder.RegisterSource(new ViewRegistrationSource());
// An example of a module that registers the dependencies for a ServiceLayer of your application
builder.RegisterModule(new ServiceModule());
builder.RegisterControllers(typeof(MvcApplication).Assembly);
return builder.Build();
}
}
}

Resources