unity.mvc4: how to get a reference - asp.net-mvc

I've setup Unity in Bootstrapper.cs of my MVC application, all is working well for constructor injection on my controllers...
My question is when I'm in an ActionResult within a controller I need to get a reference to the container I previously created in Bootstrapper.cs so I can use it to resolve classes for me.
e.g:
public ActionResult Index()
{
//-- container needs a reference to unity container
var testService = container.Resolve<ITestService>();
return View(testService);
}

I need to get a reference to the container
No you don't. You should never need to reference the container (or the DependencyResolver) from within your application.
Use constructor injection instead:
public class HomeController : Controller
{
private readonly ITestService testService;
// constructor
public HomeController(ITestService testService)
{
this.testService = testService;
}
public ActionResult Index()
{
return View(this.testService);
}
}
Since you are using the MVC3 integration package for unity, you probably registered a Unity specific DependencyResolver in the startup path of your application. That looks much like this:
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
When you've done this, your custom DependencyResolver will delegate the creation of controllers to the Unity container and the Unity container is able to inject depdencies of the constructor's of the controllers.
The next thing you should never do is letting views do any work and making them dependent on your services. Views should be dumb and do nothing more than map the data they get from the controller and transform them to HTML (or JSON or whatever).
In other words, do not pass on the testService to the view. Calling the testService from within the view hides that logic, makes the view more complicated, and makes the system hard to test. Since you're using an ITestService abstraction, I assume you want to be able to test your code, but testing the view is not easy (or at least, not as easy as you can test the controller).
What you should do is let the controller call the testService and gather the data that is needed for the view to use. Than pass on that data (perhaps combined in a single class, a view model) to the view.

Related

Where Do I Declare Unity Container?

I'm just getting started with Unity, and I'm having trouble finding any advice about where to declare my UnityContainer object. Most of the examples that I've seen consist of just a single method where the UnityContainer object is declared at the top, then its mappings are defined, then a few object types are resolved. But how do you handle the container when you need to access it in several places throughout the program? For example, the user clicks on a button which opens a new window and that window needs a controller, which itself needs to resolve several services? I also want some of the services that Unity manages to be singletons, so wouldn't that mean that I'd have to have only a single instance of my UnityContainer throughout my program to manage those singletons?
My first thought is to have my main Program class have a static UnityContainer property or expose some sort of UnityContainerFactory class which manages a singleton UnityContainer instance, but both of those methods seem bad because they create a global property which a lot of things are dependent on.
What's the accepted way of doing this?
As noted in the other answer, you should compose the entire object graph in the Composition Root.
Don't declare the container as a static field since this would encourage developers to use it as a service locator which is an anti-pattern.
How to solve your problem?
Use Dependency Injection.
Here is an example for your special WinForms case:
In your Program.Main method, create the container, register the service (the dependency that you need to use from the other window) and then resolve the main form and run it like this:
UnityContainer container = new UnityContainer();
container.RegisterType<IService, Service>();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(container.Resolve<MainForm>());
In the MainForm, declare a dependency on a Func<SecondForm> where SecondForm is the form that you need to create from the main form when the button is clicked. Consider the following code inside your main form file:
public partial class MainForm : Form
{
private readonly Func<SecondForm> m_SecondFormFactory;
public MainForm(Func<SecondForm> second_form_factory)
{
m_SecondFormFactory = second_form_factory;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
SecondForm second_form = m_SecondFormFactory();
second_form.Show();
}
}
Please note that Func<SecondForm> acts as some kind of factory. I use it in this case because unity has a feature to support late construction of dependencies via Func.
The SecondForm has a dependency on IService like this:
public partial class SecondForm : Form
{
private readonly IService m_Service;
public SecondForm(IService service)
{
m_Service = sevice;
InitializeComponent();
}
//Use service here
}
You can now use IService from the second form.
Using Seemann words:
As close as possible to the application's entry point.
Give a look at http://blog.ploeh.dk/2011/07/28/CompositionRoot/ from the great Seemann.
I think that is totally acceptable for the main container to be a static field that get disposed together with your application, just remember to don't tie your classes to your container.
Get noticed of the so called "Service Locator" (again from Seemann: http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/)
Where to declare it really depends on the application, I'd go for the startup class of an owin application or the Main method of a console/WPF app.

Partially mocking an ASP.Net MVC action method in Rhino Mock?

I'm new to Rhino, and wondered how to mock a local variable/object inside a method of a class I'd also be mocking. In this case I'd be doing it with an ASP.Net MVC controller & action method.
Here's what the controller looks like, simplified:
public class HomeController : Controller {
public myObjectType myMockedObject; //I want to mock this
public myNonMockedObject; //don't want to mock this
public ViewResult Index() {
//call various methods on the mocked and nonmocked members
return View();
}
}
In other words, I'd like to create a mock home controller and mock some local variables within it and their methods-- but not all of them. Is this possible using Rhino?
You can inject these through constructor parameters. Just write constructor that takes myObjectType as parameter. Within this constructor just initialize your fields.
Note1: in case to run MVC, you will need also parameterless ctro, or modify ConstructorFactory (e.g. here https://www.codeproject.com/Articles/560798/ASP-NET-MVC-Controller-Dependency-Injection-for-Be). Or just think about using some IoC container (e.g. https://www.nuget.org/packages/Unity/) that can inject whatever you want inside the controller (mock or normal class).
Note2: you should extract an interface from myObjectType class and mock that interface instead of concrete class (Rhino handles that better).
Note3: I am usually trying to put all the logic (and test that separately) outside of controller since it is quite tough to test the controller (you need to initialize a lot of stuff there what involves another mocking).

WP7 and Ninject,how to force the app to get view instances from IoC container

I am using Ninject to inject view model instances into the DataContext property of each view, to avoid using a ServiceLocator, and am using the following syntax inside a NinjectModule as suggested here:
public class TestingModule : NinjectModule
{
public override void Load()
{
Bind<MainPage>().ToMethod(ctx => new MainPage() { DataContext = new MainPageViewModel() }).InSingletonScope();
}
}
If I use:
var x = Kernel.Get<MainPage>();
Then the DataContext property inside x is set to an instance of MainPageViewModel, which is great.
The problem is that the Application does not get the view instances from the DI container when navigating to pages or when starting up, so the DataContext property is never set in any of the views when running the app on a device or inside the emulator.
Does anyone know how I can intercept the creation of views so that I can force the app to retrieve view instances from the DI container?
Have a look at one of the various MVVM frameworks like Caliburn Micro instead of reinventing the wheel. They did a great job making it easy to tie views and view models together while using an IoC container.
Here is a blog post about how to setup Caliburn Micro with Ninject on WP7: http://devlicio.us/blogs/derik_whittaker/archive/2011/07/08/using-ninject-with-commonservicelocator-with-caliburn-micro-on-wp7.aspx
You can add this line into MainPage constructor:
DataContext = Kernel.Get<MainPageViewModel>();

ASP.net MVC -How to use castle windsor's capability to resolve an object inside the view

I have the requirement where I need to make a call to my service from inside of my view. The service I need to call has dependencies to my repositories.
So instead of doing like -
IUserService _userService = new UserService(new UserRepository() );
I would like to obtain the _userService object from Windsor, as it already has all the dependencies resolved.
How can I achieve this ?
The viewwhere I need to call the IUserService is _layout.cshtml inside the Shared Folder. There is no controller specific to this. So where should I be injecting the dependency from?
The functionality I need inside the view is to check for Role based access which I have implemented via UserService. I have 2 choices -
1. Either to use COntext.User.IsInRole inside my view (which is not a testable piece of code)
2. Or call the my UserService from view (which is supported by tests).
I had to choose lesser of two evils so I went with the 2nd choice.
Any inputs will be highly appreciated.
You asked for input. IMO you should not be making calls to a repository from within a view.
I can think of two better options.
Option 1
Put the users roles into a ViewModel which you then pass to the view. Then you query the ViewModel for the roles.
Option 2
Call a ChildAction on your AccountController and return a partial view.
Something like this:
In your View:
Html.Action("GetUserRoles", "Account");
In your Controller:
[ChildActionOnly]
[Transaction]
public PartialViewResult GetUserRoles(string userId)
{
var viewModel = userService.GetRolesForUser(userId);
return PartialView(viewModel);
}
Now you can just inject IUserService via the Controller constructor.
IMO Appart from simple iterations and similar stuff, Views should not contain any code, especially not data access code. That's the whole premise of the MVC pattern.

How do I Access the RequestContext Outside the Controller?

Background
I am trying to move business logic out from the controllers into their own services.
Controller
public class AccountController : Controller
{
private readonly IAccountService _accountService;
public AccountController(IAccountService accountService)
{
_accountService = accountService;
}
....
}
I'm using Unity to inject dependencies. I'd like to use the Url.GenerateUrl() helper method within the implementation of IAccountService but Url is a property against the controller.
I looked at the MVC source to see how this is done but it requires me to access the RequestContext from outside of the controller, and I don't know how to do that.
Question
How do I access the RequestContext from outside the controller? If that won't solve my problem, how do I solve the problem given my setup?
This might not be quite right because I'm unable to test it at the moment, but I think that you can do something like this in .NET 4+:
using System.Web;
using System.Web.Mvc;
// ...
var helper = new UrlHelper(HttpContext.Current.Request.RequestContext);
string url = helper.GenerateUrl(/* ... */);
It might make more sense to pass the context from the controller to your IAccountService implementation rather than grabbing it directly from HttpContext.Current.
However i'd like to use the Url.GenerateUrl helper methods within my implementation of IAccountService
Simply pass this information as parameter. Example:
public ActionResult Index()
{
var someUrl = Url.Action("about");
_accountService.Foo(someUrl);
}
Now you no longer need UrlHelper inside your service classes. Everything that needs interacting with MVC infrastructure shouldn't be placed in your service classes. They shouldn't depend on any Request, Response, Session, ... It's the controller's responsibility to work with those objects and glue them together with your service classes.

Resources