I'm using EF 6.4.4 in .NET 5, and want to associate a MyDbConfiguration with a MyDbContext. However, the only way to do this appears to declare MyDbContext with a DbConfigurationType attribute. For example:
[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext
{
}
But an attribute is static, and I need to create MyDbConfiguration dynamically, via a dependency injection framework. Is there any way to do this?
Related
I am creating a new application using MVC 5 (Razor Views), Entity Framework 6 (Code First), ASP.Net Identity 2.0 and Web API. Trying to create a decent de-coupled architecture, I wanted to enable migrations in my data layer, but I have a misunderstanding of how migrations work. Here's my basic solution architecture:
MyApplication Solution
|-Domain Project
|-Entity1
|-Entity2
|-Entity3
|-Data Layer Project (References Domain Project)
|-DbContext (Inherits from IdentityDbContext)
|-Migrations Folder
|-Service Layer Project (Web API)
|-Business Layer Project
|-MVC Project
|-Views
As shown above, the Data Layer Project I have enabled migrations by executing the Enable-Migrations command in the Package Manager Console. The problem is, it only scripts the models related to Identity (AspNetUserRoles, AspNetUserLogins, etc.). How does a migration know to include an entity? I need it to script the models in my Domain project and not quite sure how to tell EF/Migrations to do so.
UPDATE:
Per a request, my simple (out-of-the-box via scaffolded by new project) DbContext class below:
public class MyDbContext : IdentityDbContext<ApplicationUser>
{
public MyDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static MyDbContext Create()
{
return new MyDbContext();
}
}
The problem is, it only scripts the models related to Identity
(AspNetUserRoles, AspNetUserLogins, etc.). How does a migration know
to include an entity?
The migration "knows" what to script as it scripts on a per context basis. Look at the Configuration.cs class in the Migrations folder and you will notice that it is a generic class with the DbContext type passed in as follows:
internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
So it "knows" because you're explicitly telling it by passing in a MyDbContext generic type parameter.
So if you want to add your own entities classes for migration then you should have a DbSet for each of the entities in your DbContext. i.e.
public class MyDbContext : IdentityDbContext<ApplicationUser> {
public DbSet<Entity1> Entity1s {get;set;}
public MyDbContext()
: base("DefaultConnection", throwIfV1Schema: false){}
public static MyDbContext Create()
{
return new MyDbContext();
} }
If you don't want to reuse MyDbContext for your custom entites then you can create another context, and add your entity DbSets to that. But then you will have to explicitly enable and update the migrations as per How do I enable EF migrations for multiple contexts to separate databases?
i am creating instance of class by using Activator in c# mvc.
but i have to add attribute for example
[required]
dynamically to the instance.
so how can i do it.
I set up "Ninject" in my asp.mvc project. And it works fine each controller get its dependency classes. But I have one class in mvc project that is not controller. It's a simple class that extends "MembershipProvider" (because I have made custom membership) and I need to inject "UserRepository" class in it.
In a NinjectControlelrFactory I bint it:
private void AddBindings()
{
ninjectKernel.Bind<IUserRepository>().To<UserRepository>().WithConstructorArgument(
"connectionString", ConfigurationManager.ConnectionStrings["connStr"].ConnectionString);
}
But how to get it from non controller class?
PS
I can't inject through constructor.
I have some solution but I don't know how 'clean' it is:
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<IUserRepository>()
.To<UserRepository>()
.WithConstructorArgument("connectionString", "ttttttttttttt");
//var tc = kernel.Get<IUserRepository>();
this.userRepository = kernel.Get<IUserRepository>();
}
Use Property Injection. Register your MembershipProvider in the Ninject and use Property injection.
You will need to instantiate MembershipProvider via ninject context.
Check these articles.
Property Injection in ASP.NET MVC with Ninject
Injecting properties in Ninject 2 without 'Inject' attribute
I'm trying to inject a repository to a custom membership provider with ninject in MVC 3.
In MembershipProvider I have tried the following:
[Inject]
public ICustomerRepository _customerRepository{ get; set; }
And
[Inject]
public TUMembershipProvider(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
In my ninject module i tried the following:
Bind<MembershipProvider>().ToConstant(Membership.Provider);
None of the above works.
When i use(in global.asa)
kernel.Inject(Membership.Provider);
together with
[Inject]
public ICustomerRepository _customerRepository{ get; set; }
it works, but i have no life cycle management and this will cause a "ISession is open" error from NHibernate, because the ISession is InRequestScope and the repository is not.
You could use the approach #Remo Gloor outlines in his blog post on provider injection. It involves 3 steps:
Add [Inject]s to any properties on your provider you need injected (although the pattern he shows -- creating a very simple class whose only function is to be a receptable for property injection and forwards any requests to a real class implemented using constructor injection -- is well worth following)
public class MyMembershipProvider : SqlMembershipProvider
{
[Inject]
public SpecialUserProvider SpecialUserProvider { get;set;}
...
Create an initializer wrapper that implements IHttpModule which pulls the provider in, triggering its creation:-
public class ProviderInitializationHttpModule : IHttpModule
{
public ProviderInitializationHttpModule(MembershipProvider membershipProvider)
{
}
...
Register the IHttpModule in your RegisterServices :-
kernel.Bind<IHttpModule>().To<ProviderInitializationHttpModule>();
there is no 4; Ninject does the rest - bootstrapping all registered IHttpModules including the one you added) during the startup sequence.
(Don't forget to read the comments on the blog post re lifetimes etc.)
Finally, if you're looking for something completely braindead direct that solves it neatly, try this #Remo Gloor answer instead
PS a great writeup on the whole mess is Provider is not a Pattern by #Mark Seemann. (and the oboligatory plug for his excellent book:- Dependency injection in .NET which will have you figuring this stuff out comfortably from first principles)
i had this problem
a custom membership, role and profile provider in another project from MVC using repository, when ever i call the provider the injected repository was null.
tried to call kernel.Inject(Membership.Provider); in the NinjectWebCommon method registerServices(IKernel kernel) but got the exception
The result is always null, because asp.net has it's own static property for membership.which is membership.provider. and this instance is not part of instance ninject management.
so use on PostApplicationStartMethod
here is the soloution by cipto add to NinjectWebCommon the attrbute and method :
[assembly: WebActivator.PreApplicationStartMethod(typeof(WebApp.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.PostApplicationStartMethod(typeof(WebApp.App_Start.NinjectWebCommon), "RegisterMembership")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(WebApp.App_Start.NinjectWebCommon), "Stop")]
public static void RegisterMembership()
{
bootstrapper.Kernel.Inject(Membership.Provider);
}
The problem is that the whole Membership infrastructure is a "native" .NET code (System.Web.Security) that does not know about MVC and about the DI container used by MVC.
The static call to Membership.Provider returns the membership provider based on the configuration, however, the specified provider type is instantiated with a simple Activator.CreateInstance call. Hence, the dependency injection has no chance to kick in and set your repository dependency on the result. If you explicitly setup the returned instance with Ninject it can work, because you explicitly gave Ninject the object to set the dependencies. Even in this case it can only work with property injection and not with constructor injection, because the instance is created by the membership configuration previously.
To summarize: you cannot easily inject dependencies into the membership provider because it is not resolved from a dependency injection container.
I think you have 2 possibilities:
You create a repository in the custom membership provider directly or you access it by some other means on demand (where the web context is already present).
You go one level higher and check the components that would use your membership provider and you try change there (to use a membership provider resolved from your DI container instead of the uninitialized Memership.Provider). If this "higher component" is the forms authentication, then this article might be of help (using dependency injection with IFormsAuthentication and IMembershipService): http://weblogs.asp.net/shijuvarghese/archive/2009/03/12/applying-dependency-injection-in-asp-net-mvc-nerddinner-com-application.aspx
Did you try resolving your repository "manually", like in this answer:
Ninject : Resolving an object by type _and_ registration name/identifier
?
I am in the process of creating a custom membership provider for an ASP.Net MVC website. The provider is being created as a separate class as part of a bigger library. There is a need for the back-end data store to be flexible as it could be an Xml File or SQL database. My initial thought was to create an interface for the data store and inject this into provider using dependency injection.
The end result is required is that a developer can inherit the data store interface and provide the required methods to update the data, which will then be used by the custom membership providers.
However through my own lack of skill I can't figure out how to inject the class into the membership provider when adding it to the website? What needs to be done to link the data store to the provider? What would be the simplest way to enable this in the website?
If you are configuring the custom membership providers via the <membership> element in the Web.config file, then I can see the issues you will have with dependency injection.
The providers are constructed and managed by the framework, and there is no opportunity for you to intercept that construction to provide additional dependency injection for the IDataStore interface.
If my assumption is correct, then what you can do is override the Initialize() method in your custom provider, and do the dependency injection there. You can have a custom name/value setting in the provider configuration which points to a type that implements IDataStore, which is passed as part of a dictionary to the Initialize() method.
Then, you activate an instance of the data store type and set it on the appropriate property:
public class MyMembershipProvider : MembershipProvider
{
public IDataStore DataStore
{
get;
set;
}
public override Initialize(string name, NameValueCollection config)
{
var dataStoreType = config["dataStoreProvider"];
if (!String.IsNullOrEmpty(dataStoreType))
{
var type = Type.GetType(dataStoreType);
DataStore = (IDataStore) Activator.CreateInstance(type);
}
}
}
Initialize() will be called by the framework after it constructs an instance of your provider, so that is the perfect place to do any additional setup work such as this.
For testing scenarios, you just set the data store property on the provider instance itself, as you will be constructing it directly in your tests.
Isn't this better? I use it with MVC3 and ninject. It's enough to add a property to your custom membership provider class. Remember to add "using System.Web.Mvc;" on top.
public IRepository Repository
{
get
{
return DependencyResolver.Current.GetService<IRepository>();
}
}
The simplest way to do dependency injection that I've seen (and actually the only one I've used so far...) is to have a constructor of your dependent class take the interface as a parameter, and assign it to a private field. If you want, you can also add a "default" constructor, which chains to the first one with a default value.
Simplified, it would look something like this:
public class DependentClass
{
private IDataStore _store;
// Use this constructor when you want strict control of the implementation
public DependentClass(IDataStore store)
{
this._store = store;
}
// Use this constructor when you don't want to create an IDataStore instance
// manually every time you create a DependentClass instance
public DependentClass() : this(new DefaultDataStore()) { }
}
The concept is called "Constructor chaining", and there's a lot of articles on the web on how to do it. I find this tutorial very explanatory of the DI pattern.