I have ASP.NET MVC3 project where I want to use custom membership provider. Also I want to use Unity for resolving my dependency injection.
this is code from Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var container = new UnityContainer();
container.RegisterType<IAuthentification, Authentification>();
container.RegisterType<IRepository, Repository>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
this is code from my membership provider:
public class CustomMembershipProvider : MembershipProvider
{
[Dependency]
private IProveaRepository Repository { get; set; }
public override bool ValidateUser(string username, string password)
{
.....
}
Problem is when I put breakpoint to ValidateUser method I see that Repository property not initialized. But this construction:
[Dependency]
private IProveaRepository Repository { get; set; }
for example, works fine in controllers.
Does anybody know why it is so and what to do?
I had the same problem over the last couple of days. I ended up with the following solution (type and field names changed to match yours).
public class CustomMembershipProvider : MembershipProvider
{
private IProveaRepository repository;
public CustomMembershipProvider()
: this (DependencyResolver.Current.GetService<IProveaRepository>())
{ }
public CustomMembershipProvider(IProveaRepository repository)
{
this.repository= repository;
}
public override bool ValidateUser(string username, string password)
{
...
}
}
So even though Unity is not in control of the building of the CustomMembershipProvider, the parameterless constructor gets Unity involed (via the MVC3 DependencyResolver) to supply the correct repository instance.
If you're unit testing the CustomMembershipProvider then you can just build an instance with Unity directly, which will use the second constructor and avoid the call to DependencyResolver.
Unity cannot inject IProveaRepository instance into you custom membership provider because :
You did not configured it to do so
CustomMembershipProvider is not resolved by unity so it has no control on injecting into it the dependencies
If you're using your membership priovider class in your code you could do the following :
Try to wrapp your customMembershipProvider in an abstraction for example IMembershipProvider that has only signature for methods that you use. The result is like that :
public class CustomMembershipProvider : MembershipProvider, IMembershipProvider
Then you could register it in unity :
container.RegisterType<IMembershipProvider, CustomMembershipProvider>(new InjectionProperty(new ResolvedParameter<IProveaRepository>()));
Then the constraint is to pass the dependency in your controller like that :
public class HomeController : Controller
{
private IMembershipProvider _membershipprovider;
public HomeController(IMembershipProvider membershipProvider)
{
_membershipProvider = membershipProvider
}
// some actions
}
But it would be event better to not user the property injection but the constructor injection like that :
public class CustomMembershipProvider : MembershipProvider
{
private IProveaRepository Repository { get; set; }
public CustomMembershipProvider(IProveaRepository proveaRepository)
{
Repository = proveaRepository
}
public override bool ValidateUser(string username, string password)
{
.....
}
It's the way I understand it and would do it. But maybe there is a better approach or I'm ignoring some of Unity API that would help to achieve it easier.
Anyway I hope it helps.
While as others said Unity cannot inject dependencies in providers because they're not known
to the container and, even if could be a registration of a provider, you haven't a "factory point" where building the provider through the container, there's a solution which doesn't violate good design principles. (This because, even if most people ignore this, using a ServiceFactory is too close to an antipattern...)
But, a good solution could be the association of using the [Dependency] attribute in conjunction with the Unity BuildUp method.
So taking your example, to get what you're trying to do, leave all the things as they are, and put in the provider constructor the BuildUp call
public class CustomMembershipProvider : MembershipProvider
{
[Dependency]
private IProveaRepository Repository { get; set; }
public CustomMembershipProvider()
{
//contextual obtained container reference
unityContainer.BuildUp(this);
.....
}
public override bool ValidateUser(string username, string password)
{
.....
}
I hope it helps.
Related
I have a custom dbcontext which name is Tracker-enabled DbContext (https://github.com/bilal-fazlani/tracker-enabled-dbcontext).I want to use it for audit log
And how can I implement EFRepository?
I implemented tracker-enabled-context but i cant solve how override sharp repo commit method.
public class HayEntities : TrackerContext
{
static HayEntities()
{
Database.SetInitializer<HayEntities>(null);
}
public HayEntities() : base(HayEntities)
{
this.Configuration.ProxyCreationEnabled = false;
this.Configuration.LazyLoadingEnabled = true;
this.Configuration.ValidateOnSaveEnabled = false;
}
public DbSet<Dummy> Dummys{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new DummyConfiguration());
} }
}
public class DummyRepository : ConfigurationBasedRepository<DE.Dummy, long>, IDummyRepository
{
private readonly IRepository<DE.Dummy, long> _servisHasarRepository;
public DummyRepository (HayEntities hayEntities, ICachingStrategy<DE.Dummy, long> cachingStrategy = null)
{this.CachingEnabled = false;
_dummyRepository = new EfRepository<DE.Dummy, long>(hayEntities, cachingStrategy);
}
public void UpdateOrCreate() {
//In this area how can override save/commit method
}
}
You will want to tell SharpRepository to use an IoC provider to inject the DbContext. This will take care of getting the proper DbContext for your EfRepository.
If you want to control things based on the configuration and have custom repositories so you can implement your own mehods like UpdateOrCreate() then you would inherit from ConfigurationBasedRepository as you have in the example.
There are more details on setting up IoC with SharpRepository here: http://fairwaytech.com/2013/02/sharprepository-configuration/ (look in the "Entity Framework and Sharing the DbContext" section)
First look on NuGet for SharpRepository.Ioc.* to find the specific IoC you are using. If you are using StructureMap then you would do something like this.
In your StructureMap configuration:
// Hybrid (once per thread or ASP.NET request if you’re in a web application)
For<DbContext>()
.HybridHttpOrThreadLocalScoped()
.Use<HayEntities>()
.Ctor<string>("connectionString").Is(entityConnectionString);
Then you need to tell SharpRepository to use StructureMap by calling this in your startup code:
RepositoryDependencyResolver.SetDependencyResolver(new StructureMapDependencyResolver(ObjectFactory.Container));
After doing these things, then if you use EfRepository then it will know to ask StructureMap for the DbContext.
Now in your example above where you are using ConfigurationBasedRepository, I would suggest setting the caching in the configuration file instead of in code since you are using the configuration to load the repository. Since IoC is handling the DbContext you don't need to do anyhing with that and you can focus on the custom method you want to write.
public class DummyRepository : ConfigurationBasedRepository<DE.Dummy, long>, IDummyRepository
{
public void UpdateOrCreate()
{
// You have access to the underlying IRepository<> which is going to be an EfRepository in your case assuming you did that in the config file
// here you can call Repository.Add(), or Reposiory.Find(), etc.
}
}
I using Ninject 3 in Repository pattern in mvc 3 (steven sanderson Scaffolder).
and in ninject i have the class "NinjectWebCommon" which in the "RegisterServices" method i resolved the dependencies and i think im ready to go.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICityRepository>().To<CityRepository>();
kernel.Bind<IVillageRepository >().To<VillageRepository>();
}
i using my repositories in controllers using constructor injection and everything is fine.
public class CityController : Controller
{
private readonly ICityRepository cityRepository;
// If you are using Dependency Injection, you can delete the following constructor
//public CityController() : this(new CityRepository())
//{
//}
public CityController(ICityRepository cityRepository)
{
this.cityRepository = cityRepository;
}
// .........
}
but when i use this repositories in other classes like Model(Entity) classes using property injection or field injection the dependency doesn't resolved and i get null reference exception on my Property or field.
[MetadataType(typeof(CityMetadata))]
public partial class City : IValidatableObject
{
[Inject]
public IVillageRepository VillageRepo { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var village = VillageRepo.Find(5); // will throw null reference exception on "VillageRepo"
}
}
public partial class CityMetadata
{
[ScaffoldColumn(false)]
public int ID { get; set; }
[Required(ErrorMessage = MetadataErrorMessages.Required)]
[StringLength(50, ErrorMessage = MetadataErrorMessages.ExceedMaxLength)]
public string Name { get; set; }
}
i don't know why this happening. so whats the problem and how can i use the repositories in non-controller classes?
thanks in advance.
Your problem is, you're expecting magic. You inject an implementation for your repository, and then you expect that data objects created by that repository are injected with references of the creating repository.
First of all, that doesn't work like that. The implementation of the repository will call new() (or Activator.CreateInstance) on your entities, not ask for an instance from a Ninject Kernel or Factory. You could rewrite the repository (it'll get trickier if you're using EF there...) but it's probably not worth the hassle.
On the top of it all, you shouldn't be needing that at all. Entities shouldn't depend on repositories, imho not even their interfaces.
EDIT: now I see why you want to see a repo in your model. What I recommend is a static factory maybe.
public class Factories
{
public static readonly Instance = new Factories();
[Inject]
public Func<IVillageRepository> VillageRepo {get; set;}
}
Then call Kernel.Inject(Factories.Instance); from your Ninject initialization code (where you bind IVillageRepository). Then modify your validatable implementation to Factories.Instance.VillageRepo().Find(...);
I created a web application using ASP.Net MVC 3 and EF 4.1, and I am using the UnitOfWork pattern, but nothing is getting committed to the database. All this is quite new to me, and I don't know where to start to resolve this issue.
I based myself on this post to create my web application:
http://weblogs.asp.net/shijuvarghese/archive/2011/01/06/developing-web-apps-using-asp-net-mvc-3-razor-and-ef-code-first-part-1.aspx
The final code, which can be obtained here also has a service layer and the UnitOfWOrk is being injected into the services.
Instead of using the custom injector based on Unity 2 as they are in that project, I am using Unity.Mvc3.
Here is my IUnitOfWork class:
public interface IUnitOfWork
{
void Commit();
}
And here is my UnitOfWork class:
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory databaseFactory;
private MyProjectContext dataContext;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
}
protected MyProjectContext DataContext
{
get { return dataContext ?? (dataContext = databaseFactory.Get()); }
}
public void Commit()
{
DataContext.Commit();
}
}
And here is how one of my service class look like:
public class RegionService : IRegionService
{
private readonly IRegionRepository regionRepository;
private readonly IUnitOfWork unitOfWork;
public RegionService(IRegionRepository regionRepository, IUnitOfWork unitOfWork)
{
this.regionRepository = regionRepository;
this.unitOfWork = unitOfWork;
}
...
}
At start-up, my UnitOfWork component is being registered like this:
container.RegisterType<IUnitOfWork, UnitOfWork>();
Now, no matter whether I try to insert, update or delete, no request is being sent to the database. What am my missing here?
UPDATE:
Here is the content of DataContext.Commit():
public class MyProjectContext : DbContext
{
public DbSet<Region> Regions { get; set; }
public virtual void Commit()
{
base.SaveChanges();
}
}
And here is databaseFactory.Get():
public interface IDatabaseFactory : IDisposable
{
MyProjectContext Get();
}
UPDATE #2:
Using the debugger, I am noticing that my Region service and controller constructors are getting called once when performing only a select, but they are called twice when performing an update. Is this normal?
Ok, I found the culprit. It has to do with how I was registering my database factory.
Instead of
container.RegisterType<IDatabaseFactory, DatabaseFactory>();
I needed
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new HierarchicalLifetimeManager());
I found the information on this web site:
http://www.devtrends.co.uk/blog/introducing-the-unity.mvc3-nuget-package-to-reconcile-mvc3-unity-and-idisposable
That's an awfully complex implementation of Unit of Work. I actually prefer this one:
http://azurecoding.net/blogs/brownie/archive/2010/09/22/irepository-lt-t-gt-and-iunitofwork.aspx
Much simpler, and much more flexible. Although you do have to work out a few things for yourself.
May just be a typo but in UnitOfWork your private MyProjectContext is called dataContext (lowercase d)
But in your commit method your calling DataContext.Commit. Any chance that's actually calling a static method that you didn't intend to call? More likely a typo but thought I'd point it out.
+1 for an overly complex implementation of UnitOfWork.
Consider the following code:
public class InboxMenuItemDynamicProvider : DynamicNodeProviderBase
{
private IMyService _myService { get; set; }
public InboxMenuItemDynamicProvider(IActionService actionService)
{
_myService = myService;
}
public override IEnumerable<DynamicNode> GetDynamicNodeCollection()
{
// use _myService here....e.g. db access
}
}
}
How do I go about injecting a service dependency into a Mvc Sitemap DynamicNodeProvider using StructureMap and MVC3? I'm using the MVC3 dependency resolver.
However, on running the app, I get a 'no default constructor' error. I need to somehow inject service dependencies into the provider, but I'm at a total loss as to where/how I can inject them. I don't even know if its possible as Mvc Site Map might be outside of the depency resolver.
See this link:
http://mvcsitemap.codeplex.com/discussions/263971
I think you could just use:
private IMyService _myService
{
get
{
return DependencyResolver.Current.GetService<IMyService>();
}
}
and do nothing specific in your constructor
I am creating an application in mvc3 and wondering how to deal with database data which is required for all application requests, some of them depends on a session, some of them depends on url pattern basically all data is in database.
Like to know best practice
What I do in my applications and consider to be the best practice is to load your common data to the ViewBag on the Controller constructor.
For every project, I have a DefaultController abstract class that extends Controller. So, every controller in the project must inherit from DefaultController, instead of Controller. In that class' constructor, I load all data common to the whole project, like so:
// DefaultController.cs
public abstract class DefaultController : Controller
{
protected IRepository Repo { get; private set; }
protected DefaultController(IRepository repo)
{
Repo = repo;
ViewBag.CurrentUser = GetLoggedInUser();
}
protected User GetLoggedInUser()
{
// your logic for retrieving the data here
}
}
// HomeController.cs
public class HomeController : DefaultController
{
public HomeController(IRepository repo) : base(repo)
{
}
// ... your action methods
}
That way you will always have the logged in user available in your views.
I do the same as #rdumont but with one exception: I create a CommonViewModel which I use to define all common properties that I use.
public class CommonViewModel
{
public string UserName {get;set;}
public string Extension {get;set; }
}
Declare a property in the base controller:
public abstract class BaseController : Controller
{
protected CommonViewModel Commons { get; private set; }
protected virtual void OnResultExecuting(ResultExecutingContext filterContext)
{
ViewBag.Commons = Commons;
}
}
By doing so I get everything almost typed. The only cast that I need to do is to cast ViewBag.Commons to the CommonViewModel.
Best is to avoid ViewBag at all.
See this answer, which details how to use Html.RenderAction() for that purpose:
Best way to show account information in layout file in MVC3
I'd suggest using a base ViewModel class.
So a base class with properties/functions which should be available at any point.