Accessing ninject kernel in Application_Start - asp.net-mvc-3

I am using Ninject and the MVC3 extension installed with nuget. My kernel setup code is in the App_Start/NinjectMVC3.cs file. Everything works great in controllers, but I can't figure out how to (properly) bind interfaces in the Global.asax.cs MvcApplication code.
I ended up using a hack (creating a public NinjectMVC3.GetKernel() method that returns bootstrap.kernel). However, that will be deprecated, and there must be a proper way to do this that I am not seeing.
Here is my code:
public class LogFilterAttribute : ActionFilterAttribute
{
private IReportingService ReportingService { get; set; }
public LogFilterAttribute( IReportingService reportingService )
{
this.ReportingService = reportingService;
}
...
}
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters( GlobalFilterCollection filters )
{
filters.Add( new HandleErrorAttribute() );
filters.Add( new LogFilterAttribute() );
}
...
protected void Application_Start()
{
...
RegisterGlobalFilters( GlobalFilters.Filters );
// NOTE hack:
var kernel = NinjectMVC3.GetKernel();
var logger = kernel.Get<ILogger>();
var bw = new BackgroundWork(logger);
Application["BackgroundWork"] = bw;
bw.Start();
}
}
There are two interfaces I am interested in. The first is just binding an object to a Global variable (the ILogger for the BackgroundWork).
And the second is for an ActionFilter. I read http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/, but I don't see how it plugs into the actual registration (filter.Add).
I don't want to use the Property Inject if I can avoid it.
Any thoughts on the proper way to do this?
Thanks

MVC 3 introduces the DependencyResolver which is populated into a singleton, and the Ninject extension supports it. You could use that in your MvcApplication class if you need it:
protected void Application_Start()
{
// ...
var logger = DependencyResolver.Current.GetService<ILogger>();
}
Now I should point out that it is unnecessary to do this with action filters. In Ninject.MVC3 you are supposed to use the BindFilter syntax, like so:
// Declare empty attribute
public class MyFilterAttribute : FilterAttribute { }
// Dependency module
public class MyModule : NinjectModule
{
public override void Load()
{
// Other bindings
// ...
this.BindFilter<MyActionFilter>(FilterScope.Action, 1)
.WhenControllerHas<MyFilterAttribute>();
}
}
Note that you have to use this because BindFilter is an extension method, and you also have to reference the Ninject.Web.Mvc.FilterBindingSyntax namespace.

Related

How can i use custom dbcontext (Audit Log) with sharprepository

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.
}
}

Windows Phone - Using generic class for PhoneApplicationPage

I have a Page which consist of AddPage.xaml and AddPage.xaml.cs. I want to create a generic class AddPage which extends from PhoneApplicationPage to outsource some repetitive code like Save or Cancel.
If I change the base class from PhoneApplicationPage to my new generic class, I get this error: Partial declarations of 'AddPage' must not specify different base classes.
To accomplish this you need to do the following.
First, create your base class
public class SaveCancelPhoneApplicationPage : PhoneApplicationPage
{
protected void Save() { ... }
protected void Cancel() { ... }
}
Then, your AddPage needs to be modified to inherit from the base class. The main places this is needed is within the code (AddPage.xaml.cs) AND within the xaml
Code:
public partial class AddPage : SaveCancelPhoneApplicationPage { ... }
Xaml:
<local:SaveCancelPhoneApplicationPage
x:Class="MyPhone.Namespace.AddPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyPhone.Namespace"
<!-- other xaml elements -->
</local:SaveCancelPhoneApplicationPage>
UPDATE: Info added based on comments
If you need to have generic like functionality and you must use the Page to do this (rather than a ViewModel) then you can still do this using generic methods
public abstract class SaveCancelPhoneApplicationPage : PhoneApplicationPage
{
protected override void OnNavigatedTo(blaa,blaa)
{
var obj = CreateMyObject();
obj.DoStuff();
}
// You should know what your objects are,
// don't make it usable by every phone dev out there
protected MyBaseObject MyObject { get; set; }
protected T GetMyObject<T>() where T : MyBaseObject
{
return MyObject as T;
}
}
public class AddPage : SaveCancelPhoneApplicationPage
{
public AddPage()
{
MyObject = new MyAddObject();
}
}
In order to outsource some functions you just declare some add class which does the common work. Having another page doesn't do that work.
public class Add
{
public bool SaveContent(string filename, string content)
{
....//some content
return true;
}
public string ViewContent(string filename)
{
string content="";
.....
return content;
}
}
Add this part of code where you thought it is redundant.
Add obj=new Add();
obj.SaveContent("myfile.txt","Hello.This is my content.");
string content("myfile.txt");
Tell me if this is what you intend or not.

RavenDB with Ninject in ASP.NET MVC3

I want to use RavenDB with ninject in my asp.net mvc3 project, Any idea how I have to configure this?
kernel.Bind<Raven.Client.IDocumentSession>()
.To<Raven.Client.Document.DocumentStore>()
.InSingletonScope()
.WithConstructorArgument("ConnectionString", ConfigurationManager.ConnectionStrings["RavenDB"].ConnectionString);
Here's how I do mine:
If you install Ninject with Nuget, you'll get an /App_start/ NinjectMVC3.cs file. In there:
private static void RegisterServices(IKernel kernel)
{
kernel.Load<RavenModule>();
}
Here's the RavenModule class:
public class RavenModule : NinjectModule
{
public override void Load()
{
Bind<IDocumentStore>()
.ToMethod(InitDocStore)
.InSingletonScope();
Bind<IDocumentSession>()
.ToMethod(c => c.Kernel.Get<IDocumentStore>().OpenSession())
.InRequestScope();
}
private IDocumentStore InitDocStore(IContext context)
{
DocumentStore ds = new DocumentStore { ConnectionStringName = "Raven" };
RavenProfiler.InitializeFor(ds);
// also good to setup the glimpse plugin here
ds.Initialize();
RavenIndexes.CreateIndexes(ds);
return ds;
}
}
And for completeness here's my index creation class:
public static class RavenIndexes
{
public static void CreateIndexes(IDocumentStore docStore)
{
IndexCreation.CreateIndexes(typeof(RavenIndexes).Assembly, docStore);
}
public class SearchIndex : AbstractMultiMapIndexCreationTask<SearchIndex.Result>
{
// implementation omitted
}
}
I hope this helps!
I recommend using a custom Ninject Provider to set up your RavenDB DocumentStore. First place this in your code block that registers your Ninject services.
kernel.Bind<IDocumentStore>().ToProvider<RavenDocumentStoreProvider>().InSingletonScope();
Next, add this class that implements the Ninject Provider.
public class RavenDocumentStoreProvider : Provider<IDocumentStore>
{
var store = new DocumentStore { ConnectionName = "RavenDB" };
store.Conventions.IdentityPartsSeparator = "-"; // Nice for using IDs in routing
store.Initialize();
return store;
}
The IDocumentStore needs to be a singleton, but do not make the IDocumentSession a singleton. I recommend that you simply create a new IDocumentSession using OpenSession() on the IDocumentStore instance Ninject gives you whenever you need to interact with RavenDB. IDocumentSession objects are very lightweight, follow the unit-of-work pattern, are not thread-safe, and are meant to be used and quickly disposed where needed.
As others have done, you might also consider implementing a base MVC controller that overrides the OnActionExecuting and OnActionExecuted methods to open a session and save changes, respectively.

Need help converting PRISM Unity Module Init to PRISM MEF Module Init

I need help converting the following class for use in a program that I am developing. The original was a demo program from IdeaBlade called "PRISM EXPLORER" based on Unity. I need help converting one part from UNITY to MEF. I handled everything else. Just stuck on this one. I already marked my classes with the MEF "[EXPORT(typeof(XXX))]" and I think I need to use the "ComposeExportedValue" somehow. The confusing part is finding the equivelant for this line:
var provider =
(IEntityManagerProvider) _container.Resolve<IPersistenceGateway>();
_container.RegisterInstance<IEntityManagerProvider>(provider);
THANKS!
The following is the entire class I need to convert. You can find the original here: Ideablade PRISM Page
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.Regions;
using Microsoft.Practices.Unity;
using PrismExplorer.Infrastructure;
namespace ModelExplorer.Explorer {
public class ExplorerModule : IModule {
private readonly IUnityContainer _container;
public ExplorerModule(IUnityContainer container) {
_container = container;
}
public void Initialize() {
InitializeContainer();
SetViews();
}
// ToDo: Consider getting from configuration
private void InitializeContainer() {
RegisterGatewayAndEntityManagerProvider();
_container.RegisterType<IQueryRepository, QueryRepository>(
new ContainerControlledLifetimeManager()); // singleton
}
private void RegisterGatewayAndEntityManagerProvider() {
_container.RegisterType<IPersistenceGateway, PrismExplorerPersistenceGateway>(
new ContainerControlledLifetimeManager()); // singleton
var provider =
(IEntityManagerProvider) _container.Resolve<IPersistenceGateway>();
_container.RegisterInstance<IEntityManagerProvider>(provider);
}
private void SetViews() {
var regionManager = _container.Resolve<IRegionManager>();
var view = _container.Resolve<ExplorerView>();
regionManager.AddToRegion(RegionNames.MainRegion, view);
regionManager.RegisterViewWithRegion(RegionNames.MainRegion, typeof(ExplorerView));
}
// Destructor strictly to demonstrate when module is GC'd
//~MevModule() {
// System.Console.WriteLine("Goodbye, MevModule");
//}
}
}
The two corresponding methods on a CompositionContainer are ComposeExportedValue<T>(...), which allows you to add a specific instance to the container, and GetExportedValue<T>(...) which gets an instance of T from the container.
If you can design your types in a way to reduce this use of service location and try and prefer constructor injection, it will make your code much easier to maintain and test. E.g., could your code be transformed into:
[Export(typeof(IModule))]
public class ExplorerModule : IModule
{
[ImportingConstructor]
public ExplorerModule(IPersistenceGateway gateway)
{
}
}

Where to define AutoMapper mappings?

Where in my ASP.NET MVC application should I define my AutoMapper mappings?
Mapper.CreateMap<User, UserViewModel>();
Presently I am defining these in the constructor of a BaseController, which all my Controlllers derive from. Is this the best place?
I think it's kind of late to answer the question, but maybe someone can use my answer.
I use Ninject to resolve dependencies, so I've created Ninject Module for AutoMapper. Here is the code:
public class AutoMapperModule : NinjectModule
{
public override void Load()
{
Bind<IConfiguration>().ToMethod(context => Mapper.Configuration);
Bind<IMappingEngine>().ToMethod(context => Mapper.Engine);
SetupMappings(Kernel.Get<IConfiguration>());
Mapper.AssertConfigurationIsValid();
}
private static void SetupMappings(IConfiguration configuration)
{
IEnumerable<IViewModelMapping> mappings = typeof(IViewModelMapping).Assembly
.GetExportedTypes()
.Where(x => !x.IsAbstract &&
typeof(IViewModelMapping).IsAssignableFrom(x))
.Select(Activator.CreateInstance)
.Cast<IViewModelMapping>();
foreach (IViewModelMapping mapping in mappings)
mapping.Create(configuration);
}
}
As you can see on load it scans assembly for implementaion of IViewModelMapping and then runs Create method.
Here is the code of IViewModelMapping:
interface IViewModelMapping
{
void Create(IConfiguration configuration);
}
Typical implementation of IViewModelMapping looks like this:
public class RestaurantMap : IViewModelMapping
{
public void Create(IConfiguration configuration)
{
if (configuration == null)
throw new ArgumentNullException("configuration");
IMappingExpression<RestaurantViewModel, Restaurant> map =
configuration.CreateMap<RestaurantViewModel, Restaurant>();
// some code to set up proper mapping
map.ForMember(x => x.Categories, o => o.Ignore());
}
}
As mentioned in this answer, AutoMapper has now introduced configuration profiles to organise your mapping configuration.
So for example, you could define a class to set up your mapping configuration:
public class ProfileToOrganiseMappings : Profile
{
protected override void Configure()
{
Mapper.CreateMap<SourceModel, DestinationModel>();
//other mappings could be defined here
}
}
And then define a class to initialise the mappings:
public static class AutoMapperWebConfiguration
{
public static void Configure()
{
Mapper.Initialize(cfg =>
{
cfg.AddProfile(new ProfileToOrganiseMappings());
//other profiles could be registered here
});
}
}
And then finally, call that class in your global.asax Application_Start() to configure those mappings:
protected void Application_Start()
{
...
AutoMapperWebConfiguration.Configure();
}
The code you are referencing looks like AutoMapper, not StructureMap.
If you're using the static Mapper
method, configuration only needs to
happen once per AppDomain. That means
the best place to put the
configuration code is in application
startup, such as the Global.asax file
for ASP.NET applications. Typically,
the configuration bootstrapper class
is in its own class, and this
bootstrapper class is called from the
startup method.
http://automapper.codeplex.com/wikipage?title=Getting%20Started&referringTitle=Home

Resources