Does any one know how to setup correct IoC (Autofac) and use it with Sitecore MVC ?
I have created a specific Pipeline but it seams like resolving doesn't work when sitecore render page (Controller rendering).
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<initialize>
<processor type="MyLib.AutofacProcessor, MyLib" />
</initialize>
</pipelines>
</sitecore>
</configuration>
public class AutofacProcessor
{
public void Process(PipelineArgs args)
{
AutofacProcessor.Start();
}
public static void Start()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>().PropertiesAutowired();
var container = builder.Build();
IDependencyResolver resolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(resolver);
}
}
But my property in controller is null when sitecore call it.
How to register it in Sitecore term ? In Regular ASP MVC it is quite easy.
You also need to override Sitecore's default ControllerFactory.
<processor type="Sitecore.Mvc.Pipelines.Loader.InitializeControllerFactory, Sitecore.Mvc"/>
Here's an example for NInject, it should be easily modified to do the same with AutoFAC: http://blog.istern.dk/2012/10/23/sitecore-mvc-new-ninject-controller-factory-clean-version/
I create a blog post around how to use Autofac with Sitecore MVC in order to resolve dependencies:
http://sitecorecorner.com/2016/01/20/sitecore-mvc-autofac-dependency-resolution/
You can find the code on BitBucket
The basic idea is to create an AutofacContainerFactory - to create your Container. AutofacControllerFactory - which you are going to use to resolve the dependancy and Hijack the <processor type="Sitecore.Mvc.Pipelines.Loader.InitializeControllerFactory, Sitecore.Mvc">
processor.
Related
What is the best practice way for to wire up Ninject with both MVC5 and SignalR?
Ninject recommends having Global.asax inherit NinjectHttpApplication and implementing a CreateKernal method:
//Global.asax ([Ninject MVC Website Guidance][1])
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel(new NinjectRegistrations());
var ninjectResolver = new CustomNinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(ninjectResolver); // MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; // Web API
return kernel;
}
SignalR would like us to use their OwinStartup class register a NinjectDependencyResolver:
//OWIN Startup ([ASP.Net Website Guidance][2])
public void Configuration(IAppBuilder app)
{
var kernel = new StandardKernel();
var resolver = new NinjectSignalRDependencyResolver(kernel);
var config = new HubConfiguration();
config.Resolver = resolver;
Microsoft.AspNet.SignalR.StockTicker.Startup.ConfigureSignalR(app, config);
}
IKernel and NinjectDependencyResolver are needed in both these locations. One option is to start using Static singletons for these, but this does not seem in the spirit of the loose coupling we are shooting for by using Ninject in the first place.
Thanks for any pointers!
You only need to call MapSignalR from Owin configuration. The Ninject MVC pipeline uses WebActivator to activate Ninject, install package Ninject.MVC5.
Look here how to add SignalR to Ninject startup
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/blob/master/SignalR.EventAggregatorProxy.Demo.MVC4/App_Start/NinjectWebCommon.cs#L45
I'd like to expose a company's api by two ways:
api.company.com (pure WebApi web site)
company.com/api (add WebApi to existing MVC5 company site)
So, I placed models/controllers in a separate assembly and reference it from both web sites.
Also, I use route attributes:
[RoutePrefix("products")]
public class ProductsController : ApiController
Now, the controller above can be accessed by:
api.company.com/products which is good
company.com/products which I'd like to change to company.com/api/products
Is there a way to keep using route attributes and setup MVC project so it adds "api" for all routes?
So this is probably not the only way you could do it, but this is how I would do it:
Create your own Attribute that inherits from RoutePrefixAttribute
Override the Prefix property and add some logic in there to prepend "api" to the prefix if running on the desired server.
Based on a setting in your web.config, prepend to the route or not.
public class CustomRoutePrefixAttribute : RoutePrefixAttribute
{
public CustomRoutePrefixAttribute(string prefix) : base(prefix)
{
}
public override string Prefix
{
get
{
if (Configuration.PrependApi)
{
return "api/" + base.Prefix;
}
return base.Prefix;
}
}
}
EDIT
(The below option is no longer supported as of Web API 2.2)
Alternatively you could also specify more than one route prefix:
[RoutePrefix("api/products")]
[RoutePrefix("products")]
public class ProductsController : ApiController
You can use Map on IAppBuilder
So Startup class will looks something like this
class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map("/api", map =>
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
map.UseWebApi(config);
});
}
}
Another option would be to forward traffic from one site to your Web API. Are you set on hosting two instances? If not, you could host only the one instance under say api.company.com/products. On your MVC company site implement an HttpHandler to redirect all traffic matching /api/* to api.company.com:
a. Create the handler in your MVC app:
public class WebApiHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string url = "api.company.com" + context.Request.RawUrl.Replace("/api","");
//Create new request with context.Request's headers and content
//Write the new response headers and content to context.Response
}
}
b. Register the handler in your web.config:
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="api/*" type="Name.Space.WebApiHandler" validate="false" />
</httpHandlers>
</system.web>
</configuration>
c. Enable CORS in your Web API if you haven't done so already.
You can just implement your api service as www.mycompany.com/api.
Then use UrlRewrite to map api.mycompany.com to www.mycompany.com/api
We even support this method of UrlRewrite in link generation, so if you generate links from the api.mycompany.com, your links will point to api.mycompany.com/controller/id.
Note that this is the only form of URL rewrite that works correctly for MVC link generation (api.xxx.yyy -> www.xxx.yyy/api)
I have an existing MVC application that is using Dependency Injection with Ninject. I installed the Ninject.MVC3 nuget package and it creates a class called NinjectWebCommon in my App_Start, which completely isolates the kernel and registers all of my bindings:
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
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;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IFoo>().To<Foo>();
}
We have a new requirement that we thought SignalR would be able to satisfy, so we installed SignalR 2 nuget package into the project. I created a Hub and did some searching on how to implement Dependency Injection into the project and found an article that suggests creating a SignalRDependencyResolver. http://www.asp.net/signalr/overview/signalr-20/extensibility/dependency-injection
The article has you creating a kernel in the Startup.cs file that is used for registering SignalR in OWIN:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var kernel = new StandardKernel();
var resolver = new NinjectSignalRDependencyResolver(kernel);
kernel.Bind<IStockTicker>()
.To<Microsoft.AspNet.SignalR.StockTicker.StockTicker>() // Bind to StockTicker.
.InSingletonScope(); // Make it a singleton object.
kernel.Bind<IHubConnectionContext>().ToMethod(context =>
resolver.Resolve<IConnectionManager>().GetHubContext<StockTickerHub>().Clients
).WhenInjectedInto<IStockTicker>();
var config = new HubConfiguration()
{
Resolver = resolver
};
app.MapSignalR(config);
}
}
The problem is that this approach has me creating two different kernels and they seem to have their own set of dependencies that they know how to resolve. If I have a dependency defined in NinjectWebCommon, the Hub doesn't know how to resolve that dependency. Without exposing my kernel in NinjectWebCommon, what is the proper way to add DI into SignalR using the Ninject.MVC3 package?
None of the current answers directly answer your question. Also achieving the result you are after is very straightforward once you know exactly what to do. The "proper" way to do this is to set SignalR's dependency resolver in the CreateKernel method of the NinjectWebCommon class.
Assuming you have created a NinjectSignalRDependencyResolver class as you mention, no other code needs to be added anywhere except for the line highlighted in the code snippet below:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// THIS LINE DOES IT!!! Set our Ninject-based SignalRDependencyResolver as the SignalR resolver
GlobalHost.DependencyResolver = new NinjectSignalRDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
Apart from the above, nothing more needs to be done except declaring your bindings in the RegisterServices method of NinjectWebCommon. In your example this would look like:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IStockTicker>()
.To<Microsoft.AspNet.SignalR.StockTicker.StockTicker>() // Bind to StockTicker.
.InSingletonScope(); // Make it a singleton object.
kernel.Bind<IHubConnectionContext>().ToMethod(context =>
resolver.Resolve<IConnectionManager>().GetHubContext<StockTickerHub>().Clients
).WhenInjectedInto<IStockTicker>();
}
Except for the NinjectSignalRDependencyResolver class you created, no other code needs to be added. Importanly, the OwinStartup class remains unmodified, as follows:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
The above example achieves the following important outcomes which were what you asked in your question:
You only have a single Ninject Kernel created
The kernel and all binding configurations remain confined to NinjectWebCommon
The default SignalR resolver is your NinjectSignalRDependencyResolver
Dependency Injection into all SignalR hubs is achieved
Hopefully this helps people out.
Have you tried adding the StockTickerHub itself to your kernel?
By default, SignalR uses Activator.CreateInstance to construct Hubs without any constructor arguments. If you want to inject your own dependencies into a Hub, you can do so by registering the Hub with SignalR's dependency resolver.
https://github.com/SignalR/SignalR/blob/2.0.1/src/Microsoft.AspNet.SignalR.Core/Hubs/DefaultHubActivator.cs#L28
If you want to get really creative, you can register your own IHubActivator instead of registering all of Hubs individually.
I go into more detail in how Hubs are created by default in this answer: SignalR with IoC (Castle Windsor) - which lifetime for hubs?
There is a problem with the singleton scope. I don´t know who should get the blame here (Ninject, SignalR, MVC, etc...), but it works if you use ToConstant:
var binding = Bind<IMustBeSingleton>().ToConstant(new MustBeSingleton());
I had the same problem, and I found the solution: SignalR, WebAPI and MVC sharing the same dependency resolver kernel
I shared a complete solution with MVC, WebAPI and SignalR using the same Ninject kernel: https://drive.google.com/file/d/0B52OsuSSsroNX0I5aWFFb1VrRm8/edit?usp=sharing
That example web app, contains a single page that shows the AppDomain and GetHashCode of an object that is supposed to be unique across the three frameworks, giving a result similar to:
Dependency Test
Framework IMySingletonService instance
MVC AppDomainId:2 / HashCode:5109846
WebAPI AppDomainId:2 / HashCode:5109846
SignalR AppDomainId:2 / HashCode:5109846
I hope this helps.
I'm using castle windsor 3.1.0.0 for dependency injection in my MVC 3.0 application.
My container is setup to provide controllers like this:
container.Register(Classes.FromThisAssembly().BasedOn<IController>().LifestylePerWebRequest());
This seems to be working as I see a new controller instance created for every request. However according to the documenation: http://docs.castleproject.org/Windsor.LifeStyles.ashx, I must also place this in my web.config:
<httpModules>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor"/>
</httpModules>
which I don't have. What is the behavior of Castle Windsor if this module is missing? (The documentation says that In order to function properly per web request you must have this in your web config).
As far as I understand, the PerWebRequestLifestyle requires an IHttpModule so that it can piggy-back off the init method and the HttpApplication events such as BeginRequest.
The reason why everything seems to be working is because the module has been initialised and so the PerWebRequestLifestyle is functioning normally.
But why is that the case if you didn't include the registration module? I suspect that it is a legacy instruction and that the container will attempt a registration on its own, but this isn't documented explicitly.
If we take a peek inside CastleWindsor we find something called Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModuleRegistration. It has this method:
public static void Run()
{
Type type = Type.GetType("Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility, Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", false);
if (type == null)
{
return;
}
MethodInfo method = type.GetMethod("RegisterModule", BindingFlags.Static | BindingFlags.Public);
if (method == null)
{
return;
}
object[] objArray = new object[] { typeof(PerWebRequestLifestyleModule) };
method.Invoke(null, objArray);
}
What is DynamicModuleUtility? A quick search reveals a page written by K. Scott Allen called DynamicModuleUtility.
The DynamicModuleUtility will let you install an HTTP module into the ASP.NET pipeline without making any changes to web.config file.
This is only my speculation as to what's going on. You'd have to ask the creators of Castle Windsor for details on exactly how things are working.
thanks in advance for any help. I changed to mvc4 and start using app_start/routeconfig.cs to register routes.
Probably it dont have any relation with autofac but I cannot find a solution, does anyone know if its neccesary to declare routetable.routes in any additional place - I already declared RouteConfig.RegisterRoutes(RouteTable.Routes); in global.asax - when planning to use autofac with mvc4 razor´s internet template?.
Currently no map.route definition is working in my app. I dont know if I have to declare an instance like
RegisterInstance(RouteTable.Routes);
thank you so much.
This is basically the minimum amount of code to configure Autofac for mvc. You will need to reference Autofac.Integration.Mvc, and if you're using webapi you need to reference Autofac.Integration.Webapi too.
public static class AutofacConfig
{
public static IContainer Register()
{
var assembly = typeof(MvcApplication).Assembly;
var builder = new ContainerBuilder();
builder.RegisterControllers(assembly);
// If you don't need webapi, you can omit this, else you need Autofac.Integration.Webapi
builder.RegisterApiControllers(assembly);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// If you don't need webapi, you can omit this, else you need Autofac.Integration.Webapi
var resolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;
return container;
}
}
In Global.Asax you can then add
AutofacConfig.Register();
in the Application_Start method as one of the first calls.