Tweaking asp.net mvc - 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.

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

ASP.NET MVC 3 Preview configure for ninject

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.

Controller Test problems

I want to test a mvc controller. I'm using Moq to mock the services, but I don't know how to mock this.Request.Files["Attachement1"] and this.Server.MapPath("~/Temp") ("this" is the controller)
I tried to create a new Mock<HttpRequestBase>(); but this.Request doesn't have a setter.
Help me please with an advise. Thanks
I had a similar problem as your - I used the set of fake classes from Stephen Walther's blog.
Asp.Net MVC Tips - Faking the Controller Context
I had to modify some of the classes slightly but it should do what you want and it's definitely a lot easier to setup than having to mock the entire context every time.
For the folder name resolutions such as: this.Server.MapPath("~/Temp") I use public properties, and getter returns this so I can easily test it.
For the Request.Files, I prefer using FormCollection dictionary
If you have a look at the TestHelper in the MVCContrib project, it can easily be extended to Mock other bits of the Http elements. (It has some Request elements already to use as a template.)
Kindness,
Dan

ASP.NET MVC ViewManager equivalent

I'm looking into ASP.NET MVC, and whether or not to make the switch. One thing that I do a heck of a lot in ASP.NET, is to render HTML on AJAX callbacks and sent back to the client. I use a generic ViewManager for rendering User Controls.
I created a sample MVC App from the templates, and was looking for the RenderUserControl method inside a Controller. I found: System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial but that doesn't seem to be what I'm looking for in this context.
Is there an equivalent to the ASP.NET ViewManager in MVC?
What you want to do is return a partial view:
public ActionResult IWillCallThisViaAjax()
{
return PartialView("MyUserControlName");
}

Any way to handle Put and Delete verbs in ASP.Net MVC?

just wondering if anyone knows of a truly restful Put/delete implementation asp.net mvc preview 5 preferably.
Check out the mvccontrib project at http://www.mvccontrib.org.
In the source code a restful implementation has been added and it is current up to Preview 5. Check out the source code here - http://mvccontrib.googlecode.com/svn/trunk/src/MVCContrib/SimplyRestful
Rails uses a "method" parameter in the form and then fakes it, but calls the appropriate method if you designate it.
I understand most clients won't support restful stack, but can asp.net mvc, auto-negotiate these verbs and place them in the appropriately deemed actions?
I've been covering this in my blog http://shouldersofgiants.co.uk/blog/ where I'm looking at an entire RESTful web service based on ASP.Net and MVC
I don't know of one off the top of my head, but you might look into the way that Rails handles it if you don't find anything else, and try porting it over. Rails utilizes POST, GET, PUT, and DELETE, but it apparently has to do some fakery for PUT. Could be worth looking into if you come up dry here.
I think that the new AcceptVerbsAttribute in preview 5 should be capable of directing any type of request to a designated action. Marking a method like below in theory allows handling of all verbs but I haven't explicitly tested put or delete.
[AcceptVerbs("delete")]
public object DoDeleteAction()
With MVC Beta, u can now use an HttpVerbs enumeration.
here's an example...
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index()
{ ... }
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update()
{ ... }
[AcceptVerbs(HttpVerbs.Delete)]
public ActionResult Delete()
{ ... }
you get the idea.
hth :)

Resources