ASP.NET MVC 3 Preview configure for ninject - asp.net-mvc

I'm giving ASP.NET MVC 3 Preview 1 a spin and want to configure ninject with it. Is the best way still to use ninject.web.mvc extension? The sample Scott Gu posts doesn't run. It throws an "Error activating IControllerFactory" exception.

You don't need "Ninject.Web.Mvc" to configure Ninject in MVC 3, as I've blogged in a post titled "Dependency Injection in ASP.NET MVC 3 using Ninject".

I believe Scott Gu's code should read...
public static void RegisterServices(IKernel kernel)
{
kernel.Bind<IProductRepository>().To<SqlProductRepository>();
kernel.Bind<IControllerFactory>().To<NinjectControllerFactory>();
}
Where the NinjectControllerFactory is found in...
using Ninject.Web.Mvc;
So yes, you do still need the mvc extension for Ninject.
Perhaps there is a better/newer way to define the default controller factory in MVC 3, but that is how I did it.
There may also be some strange behavior coming from MvcServiceLocator as indicated in this post.

Make sure that when you're calling using the ninject kernel from your IDependencyResolver, that you're calling
_kernel.TryGet(serviceType)
The MVC framework will try to grab a different IControllerFactory if it is available, if you call "TryGet", it will return null and the framework will use the default Controller Factory instead.
If you're using unity instead, make sure you wrap the resolve in a try/catch block and return null in the catch. Although that will be kind of slow, because you don't really want to have a catch block be treated as a normal part of execution flow.

Related

Working with helpers in the dotnetcore DI world

I like to have static helper classes in my apps for common plumbing stuff, like checking roles, or Razor Html helpers and stuff... but how do you do this in the DI world?
Like lets say I want an extension helper to check if a user is an admin
public static async Task<bool> IsAdmin(this ApplicationUser user)
...
if(user.IsAdmin()){...}
So pre-core I could just ignore DI and create a UserManager all inside IsAdmin do whatever I need to do. But now is there no way to get the UserManager in these helpers to just use? The only way I can see is to inject it into the Controller, then pass along into the method (which I find ugly). Then there's the issue of trying to do user.IsAdmin() in the Razor view, would I need to add the UserManager to the ViewData collection to get it into the view markup?
Am I just missing something here?
Thanks,
Steve
First of all if you just asked how to use static class with di, i would say that your question is duplicate of How to use DI inside a static Method in Asp.net Core rc1
But as i see, you have some other question?
But now is there no way to get the UserManager in these helpers to
just use?
Yes there is a way : Service Locator pattern. But it is an anti pattern (see this article) . As far as possible you should avoid to use this pattern. Also see discussion in github.
The only way I can see is to inject it into the Controller, then pass
along into the method (which I find ugly)
I think this way is better than you want. I would prefer this.
Then there's the issue of trying to do user.IsAdmin() in the Razor
view, would I need to add the UserManager to the ViewData collection
to get it into the view markup?
In Aspnet core you can inject a dependency into a view, so you don't need to use ViewData. Simply you can inject UserManager into your view and then pass it as parameter to method. Take a look at official docs
Well you are talking about a cross-cutting concern here and one way how I've seen cross cutting concerns solved in ASP.NET Core MVC is with attributes (like [Authorize] for example). Which I think is an elegant solution.
So, if I understand your question correctly I think you can solve this with an Action Filter. Damien Bod described a few days ago how to use ActionFilters: https://damienbod.com/2016/09/09/asp-net-core-action-arguments-validation-using-an-actionfilter/.
So in short, you inherit from ActionFilterAttribute and make your own curstom filter called MyCustomFilter or whatever. Have this MyCustomFilter request UserManager in its constructor via DI. Then above any action method in a controller you say:
ServiceFilter[typeof(MyCustomFilter)]
And in MyCustomFilter you ofcourse have logic to check if User is IsAdmin and then take action accordingly.
Now, I've always used Microsoft's Unity to handle cross cutting concerns via interception (you can read more about that here: https://dannyvanderkraan.wordpress.com/2015/09/30/real-world-example-of-adding-auditing-with-dependency-injections-interception/. But last time I checked there is no Unity container for asp.net core yet. But this guy has a great article about porting it to core: https://dzimchuk.net/post/bring-your-own-di-container-to-aspnet-5-unity. I would really like my Interception back! Very elegant solution to cross cutting concerns. They are working on it though: https://github.com/unitycontainer/unity/issues/66. Fingers crossed...

Render Razor View inside of WCF service

It's a quite odd task to do, but I can't change the requirements. We have to write a WCF service (SOAP, not REST) and return an HTML as a property on response object.
I don't want to use:
hard-coded strings and use string.Format() to fill in some values;
t4 template as not many people can support this approach in the future;
WebForm controls as most of our developers are used to work with MVC projects.
I already know how to render some ActionResult to a string. So, ideally, I would like to be be able to create a controller, invoke some action and get an ActionResult.
For that, I created MVC application and added service.svc file to it. Service work fine - I can invoke its methods and receive results. But my problems start when I try to render Razor View. If I simply create an instance of any controller and then invoke an action, controller's property ControllerContext is null and hence View can't be rendered. I tried crafting ControllerContext on the fly, but seems like I'm missing something.
I found very similar question here, but the solution offered there didn't work for me as HttpContext.Current is null inside of wcf methods.
Does any body know how to achieve that? Or maybe somebody can sugggest other simple and flexible way to render HTML inside of WCF method?
You should also have a look at the Nancy framework (http://nancyfx.org), as their implementation of the RazorEngine is more lightweight.
I've had a fair amount of success using Nancy to generate HTML on demand - because it was designed as being inherently testable, you can abuse it to your own ends as a templating framework pretty easily.
You will need to host the Razor Engine in your app. Look at this article Rendering ASP.NET MVC Views to String, especially the section "Rendering without a ControllerContext"
Also, much more info can be found in this answer Render a view as a string. (The are several "correct" answers, with different contexts)

Up to date ASP.Net MVC 3 Request-Handling Pipeline Diagram?

Can anyone point me to an up-to date diagram of the ASP.Net MVC 3 request handling pipeline?
I've got an older version (MVC v1, v2), but it's no longer accurate, given the introduction of IControllerActivator in MVC3 (and possibly other framework changes).
This is somewhat late for an answer but this could help someone (definitely helped me)
ASP.NET MVC Pipeline
Taken from this great article: An Introduction to ASP.NET MVC Extensibility
This is a Request-handling Pipeline for ASP.NET MVC 2: http://ajaxus.net/wp-content/uploads/2010/01/asp_net_mvc_poster.pdf (or see page 228, Pro ASP.NET MVC 2 by Steven Sanderson).
The request pipeline is (maybe) not change in V3, but MVC 3 is extend some point to allow injection in every node of pipeline.
Example:
- At node: Controller factory:
+ ControllerBuilder create an instance of IControllerFactory (ex: the default factory)
+ factory implement Create() of IControllerFactory by:
++ Using an instance of IControllerActivation (activation)
++ Call activation.Create() of IControllerActivation to get instance of controller
So, IControllerActivation is work in DefaultControllerFactory. We can still use DefaultControllerFactory and replace IControllerActivation, or replace the DefaultControllerFactory with custom IControllerFactory (with or without use IControllerActivation)

Castle.Windsor and HttpContextWrapper

HttpContextWrapper and HttpContextBase, as explained here, were introduced to make HttpContext more mockable/testable.
I'm trying to use it with S#arp Architecture, and hitting some problems.
My MVC Controllers are set up to accept an HttpContextBase argument in the constructor, and during Application_Start, HttpContextBase is registered with Castle.Windor as follows:
container.Register(Component.For<HttpContextBase>().UsingFactoryMethod(
() => new HttpContextWrapper(HttpContext.Current)));
This seemed to work OK for a bit, but then I realised Castle is only running that Factory method once, so all requests get the original HttpContextWrapper. Really it needs to be re-created for every request. The Castle.Windsor command for that would be:
container.Register(Component.For<HttpContextBase().
LifeStyle.PerWebRequest.UsingFactoryMethod(
() => new HttpContextWrapper(HttpContext.Current)));
... but it turns out that Castle.Windsor doesn't allow LifeStyle.PerWebRequest to be used within Application_Start (as explained here)
What should I be doing? Is there an easy way round this or should I give up on HttpContextWrapper and inject my own factory to make new ones as needed?
My MVC Controllers are set up to accept an HttpContextBase argument in the constructor
You gotta be doing something extremely wrong here, so stop before it's too late and damage has been caused (material, moral and human casualties :-)). You already have the HttpContext inside the controller.
Don't register any HttpContexts in your DI framework. The HttpContext handling is the job of ASP.NET.
As Darin noted, it makes no sense to inject an HttpContext into an MVC controller. However, if you need it for other kind of services and also need it in Application_Start(), use an hybrid perwebrequest-transient lifestyle. Or, since it's trivial to build, just make it transient.
As others have stated - you are doing it wrong. My big question is:
What are you doing that requires you to inject HttpContextBase in your controller? It might be more helpful to people wanting to help you if you would provide us more context about what you are really trying to do. Lets take Castle out of it and get down to what your controller is doing.
BTW, your controller already has a reference to HttpContext. If you are doing this for testability, there is nothing you need to do at the controller level. You would just need to mock the HttpContextBase object as needed in your controller tests.

Tweaking asp.net mvc

I really love the "one model in - one model out" idea of Fubu MVC. A controller would look something like this
public class MyController
{
public OutputModel MyAction(InputModel inputModel)
{
//..
}
}
and the service locator would automagically fill in all the required dependencies in the constructor.
This makes the controller very easy to test.
So my question is: How would you go about tweaking asp.net mvc to allow this simplicity in the controllers ?
What you're looking for the is the ControllerActionInvoker. You'll have to implement your own and override/take over handling a lot of the pipeline work that ASP.NET MVC.
For reference, check out Jonathon Carter's 2-part post on doing ControllerActionInvokers:
http://lostintangent.com/2008/07/03/aspnet-mvc-controlleractioninvoker-part-1/
and
http://lostintangent.com/2008/07/07/aspnet-mvc-controlleractioninvoker-part-2/
Also, the Oxite team did this in the 2nd release of Oxite, you can check out their source here:
http://oxite.codeplex.com/SourceControl/changeset/view/30544
Here's a link directly to their ControllerActionInvoker implementation:
http://oxite.codeplex.com/SourceControl/changeset/view/30544#442766
Never really dug deep inside ASP.NET MVC internals, but I guess custom ModelBinder and ActionResult will do the job.

Resources