Using Autofac with ASP.NET and the MVP pattern - asp.net

I'm trying to integrate Autofac into an exsisting ASP.NET web application.
The pages follow the MVP pattern. Each page implements a View and delegate functionality to a Presenter. The View is injected into the Presenter thru the constructor.
I was able to register the Presenter and View and the page loads fine but when a postback happens the user controls on the view are null. It seems that Autofac creates a new instance of the Page to give to the presenter instead of giving it the instance real Page instance. Is there a way to have Page instances registered with Autofac?
Has anyone use Autofac with ASP.NET and MVP?
Thanks!

There is a better way. First, enable the Web integration module. This will enable automatic property injection into the Page instance.
Since your presenter needs the view in its constructor, your page should take a dependency on a presenter factory instead of the presenter itself.
So, first you need the presenter factory, which is a delegate with the necessary parameters:
public delegate IOCTestPresenter IOCTestPresenterFactory(IIOCTestView view);
This delegate must match the parameters (type and name) of the presenter constructor:
public class IOCTestPresenter
{
public IOCTestPresenter(IIOCTestView view)
{
}
}
In your view, add a property receiving the factory delegate, and use the delegate to create the presenter:
public partial class IOCTest
{
public IOCTestPresenterFactory PresenterFactory {get;set;}
protected void Page_Load(object sender, EventArgs e)
{
var presenter = PresenterFactory(this);
}
}
In your container setup you will have to make the following registrations:
builder.Register<IOCTestPresenter>().FactoryScoped();
builder.RegisterGeneratedFactory<IOCTestPresenterFactory>();

I figured out a solution. Basically, you would register the page instance during the Page_PreInit event and then call the container to inject the dependencies. Ex.
public partial class IOCTest : System.Web.UI.Page, IIOCTestView
{
protected void Page_PreInit(object sender, EventArgs e)
{
var containerProviderAccessor = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
var containerProvider = containerProviderAccessor.ContainerProvider;
var builder = new ContainerBuilder();
builder.Register(this).ExternallyOwned().As<IIOCTestView>();
builder.Build(containerProvider.RequestContainer);
containerProvider.RequestContainer.InjectProperties(this);
}
public IOCTestPresenter Presenter { get; set; }
I'm not sure if there is a better way, but this seems to work.

Related

How to link button event.click with xamarin.driod from xamarin.form

Am new to xamarin.form having a blockage...
This is what I want to do.
I have a button in welcome.xaml in xamarin.form and I want to perform a click event but I want a method from xamarin.driod to be implemented in the click.event.
Those this makes sense to anyone?
You need to write a custom control.
So you could handle the click event in the Android or IOS.
Read here about how to create a custom controls in xamarin.forms
You could also assign a static class that exist in the shared project from your driod project.
I typically prefer using IOC and Interfaces to implement platform specific logic in the Core project, but simple way to do it may just be to set a static Action on your pages code behind.
public partial class WelcomePage
{
public static Action DroidAction { get; set; }
private void Button_OnClicked(object sender, EventArgs e)
{
if (DroidAction == null)
{
Debug.WriteLine("Action was not set");
}
DroidAction?.Invoke();
}
Your Droids OnCreate could be an option of where to do this.
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
WelcomePage.DroidAction = new Action(() => Debug.WriteLine("I a platform specific action!"));
}

Applying Dependency Injection on an ASP.NET web forms application built using MVP Pattern

I am creating an ASP.NET Web forms application with MVP pattern. The structure of my view is something like this:
public partial class ShipperView : System.Web.UI.Page, IShipperView
{
ShipperPresenter presenter;
public ShipperOperationsView()
{
IShipperOperations operations = new ShipperOperations();
INavigator navigator = new Navigator();
presenter = new ShipperPresenter(this,operations,navigator); //Instantiating presenter
}
...
}
The basic structure of my presenter is something like this:
public class ShipperPresenter
{
IShipper shipperView;
IShipperOperations operations;
INavigator navigator;
public ShipperPresenter(IShipperView view,IShipperOperations operations,INavigator navigator)
{
shipperView = view;
this.operations = operations;
this.navigator = navigator;
}
...
}
I don't want to instantiate my presenter using the new keyword, I would like to replace it with resolving dependency. During the dependency resolution, I want to pass the instance of the present view to the dependency resolver. I tried searching a lot on this but did not get any satisfactory answer.
Can this issue be resolved using any of the IoC containers like StructureMap, Ninject, Unity or MEF? Any pointer would be of great help.
To solve this problem you could use property injection.
First, register ShipperOperations, Navigator and ShipperPresenter in the DI container.
Then, in the Page_Load method of your view, invoke the resolve method of the DI container of your choice.
public class ShipperPresenter
{
IShipper shipperView;
IShipperOperations operations;
INavigator navigator;
public ShipperPresenter(IShipperOperations operations,INavigator navigator)
{
this.operations = operations;
this.navigator = navigator;
}
public IShipper ShipperView
{
get { return shipperView; }
set { shipperView = value; }
}
...
}
And the view would look like this:
public partial class ShipperView : System.Web.UI.Page, IShipperView
{
ShipperPresenter presenter;
protected void Page_Load(object sender, EventArgs e)
{
presenter = YourIOC.Resolve<ShipperPresenter>();
presenter.ShipperView = this;
}
...
}
You could also use a factory to create the presenter at runtime, while passing it the parameters of your choice. In fact, in a DI world, this is THE way to proceed when you want to instantiate objects with dependencies that are only known at runtime. There is a nice mechanism for this in Castle Windsor, it's called typed factories.
Using a factory, no need to modify the presenter class. Instead, create an interface for the factory:
public interface IShipperPresenterFactory
{
ShipperPresenter Create(IShipper shipperView);
}
If using Windsor, the only thing that you have to do is to register this interface as a typed factory. With other DI containers, you will have to implement a class that uses the DI container internally to resolve the presenter.
The Page_Load method of the view would then use the factory like this:
protected void Page_Load(object sender, EventArgs e)
{
var factory = YourIOC.Resolve<IShipperPresenterFactory>();
presenter = factory.Create(this);
}

how can i inject a presenter into a view without the view having a reference to the presenter

in a classic Passive-MVP pattern, how can i avoid a reference of the presenter in my view completely & still inject the presenter instance which needs the view instance as a parameter.
with asp.net as an example:
my implemented views (web project) should not have a reference to the Presenters. (Neither IPresenter nor the concrete ones)
when the view instantiates, (basically my web page), the presenter should be instantiated with the current view's reference.
i am using unity as my ioc container.
right now what i do in the web page's code behind is this:
public partial class SomePage : MyBasePage, ISomeView
{
private readonly ISomePresenter presenter;
public SomePage()
{
this.presenter = ResolveSomeWay(this);
}
}
for this i have a reference of the 'Presenter Contracts DLL' in my view implementation. is there a way to avoid this reference completely & still hook up the presenter with the view instance, when the view instantiates?
i just care about the presenter instantiation, since the presenter's constructor can set the passed parameter-view-instance to its View Property & it subscribes to the view's events, for any future communication.
thanks folks for your time.
You could "publish" a new View was instantiated to a Message Bus, to which a Presenter factory could "bind" the instantiated View to a Presenter. Although the View would be agnostic of the presenter, it would not be of the Message Bus.
public partial class SomePage : MyBasePage, ISomeView
{
// Alternative #1
public SomePage(IMessageBus messageBus)
{
// You publish a message saying that a handler for ISomeView is to handle the
// message.
messageBus.Publish<ISomeView>(this);
}
// Alternative #2
public SomePage()
{
Resolver.Resolve<IMessageBus>().Publish<ISomeView>(this);
}
}
// This could be somewhere else in your application (this could be a separate DLL), but
// I will use the Global.asax.cs here, for simplicity
public void Application_Start()
{
Container.Resolve<IMessageBus>()
.Subscribe<ISomeView>(someView =>
{
var presenter = new SomePresenter(someView);
});
}
public interface ISomeView {
event Action<ISomeView> SomeEvent;
}
public class SomePresenter
{
public SomePresenter(ISomeView view) {
// if you attach the presenter to the View event,
// the Garbage Collector won't finalize the Presenter until
// the View is finalized too
view.SomeEvent += SomeEventHandler;
}
private void SomeEventHandler(ISomeView view) {
// handle the event
}
}

Callling business logic layer method from PageMethods

I've a static page method in web form application and I want to call method on private class level variable from it as shown below. I'm using jQuery to call the page method.
private readonly ICatalogBLL _catalogBLL = new CatalogBLL();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
_catalogBLL.GetSomething();
}
}
[WebMethod]
public static UpdateSomething(int i)
{
//Want to do as below. But can't call it from a static method.
_catalogBLL.UpdateSomething();
}
UPDATE
If I call it as said by John Saunders, won't it use the same instance for requests from different users as it is within a static method?
You can't. The page method is static. Your _catalogBLL is an instance member.
However, since you create a new instance of CatalogBLL on every request, why not do so once more?
[WebMethod]
public static UpdateSomething(int i)
{
CatalogBLL catalogBLL = new CatalogBLL();
catalogBLL.UpdateSomething();
}
You can't call because pagemethods are static...
A static method is simply one that is disassociated from any instance of its containing class. The more common alternative is an instance method, which is a method whose result is dependent on the state of a particular instance of the class it belongs to.
Look at John saunder's answer..

Injecting Lower Layer Dependency in Presenter in an ASP.NET MVP Application

I recently read Phil Haack's post where he gives an example of implementing Model View Presenter for ASP.NET. One of the code snippets shows how the code for the view class.
public partial class _Default : System.Web.UI.Page, IPostEditView
{
PostEditController controller;
public _Default()
{
this.controller = new PostEditController(this, new BlogDataService());
}
}
However, here the view constructs the instance of the BlogDataService and passes it along to the presenter. Ideally the view should not know about BlogDataService or any of the presenter's lower layer dependencies. But i also prefer to keep the BlogDataService as a constructor injected dependency of the presenter as it makes the dependencies of the presenter explicit.
This same question has been asked on stackoverflow here.
One of the answers suggests using a service locator to get the instance of the BlogDataService and passing it along to the presenter's constructor.This solution however does not solve the problem of the view knowing about the BlogDataService and needing to explicitly get a reference to it.
Is there a way to automatically construct the presenter object using an IoC or DI container tool such that the view does not have to deal with explicitly creating the BlogDataService object and also injecting the view and service instances into the presenter's constructor. I prefer to use the constructor injection pattern as far as possible.
Or is there a better design available to solve the problem?. Can there be a better way to implement this If i am building a WinForms application instead of a ASP.NET WebForms application?
Thanks for any feedback.
Yes there is. For example using StructureMap in a webform constructor:
public partial class AttributeDetails : EntityDetailView<AttributeDetailPresenter>, IAttributeDetailView
{
public AttributeDetails()
{
_presenter = ObjectFactory.With<IAttributeDetailView>(this).GetInstance<AttributeDetailPresenter>();
}
....
}
and as you can see here presenter needs view and service injected
public AttributeDetailPresenter(IAttributeDetailView view, IAttributeService attributeService)
{
MyForm = view;
AppService = attributeService;
}
You can also use StructureMap BuildUp feature for webforms so that you can avoid using ObjectFactory directly in your view.
I did exactly this. The solution is based on Autofac, but can be implemented on top of any container.
First, define an interface representing the authority for presenting views in a request to the MVP system:
public interface IMvpRequest
{
void Present(object view);
}
Next, create a base page which has a property of that type:
public abstract class PageView : Page
{
public IMvpRequest MvpRequest { get; set; }
}
At this point, set up dependency injection for pages. Most containers have ASP.NET integration, usually in the form of HTTP modules. Because we don't create the page instance, we can't use constructor injection, and have to use property injection here only.
After that is set up, create event arguments representing a view which is ready to be presented:
public class PresentableEventArgs : EventArgs
{}
Now, catch the events in PageView and pass them to the request (present the page as well):
protected override bool OnBubbleEvent(object source, EventArgs args)
{
var cancel = false;
if(args is PresentableEventArgs)
{
cancel = true;
Present(source);
}
else
{
cancel = base.OnBubbleEvent(source, args);
}
return cancel;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Present(this);
}
private void Present(object view)
{
if(MvpRequest != null && view != null)
{
MvpRequest.Present(view);
}
}
Finally, create base classes for each type of control you'd like to serve as a view (master pages, composite controls, etc.):
public abstract class UserControlView : UserControl
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();
RaiseBubbleEvent(this, new PresentableEventArgs());
}
}
This connects the control tree to the MVP system via IMvpRequest, which you'll now have to implement and register in the application-level container. The ASP.NET integration should take care of injecting the implementation into the page. This decouples the page entirely from presenter creation, relying on IMvpRequest to do the mapping.
The implementation of IMvpRequest will be container-specific. Presenters will be registered in the container like other types, meaning their constructors will automatically be resolved.
You will have some sort of map from view types to presenter types:
public interface IPresenterMap
{
Type GetPresenterType(Type viewType);
}
These are the types you will resolve from the container.
(The one gotcha here is that the view already exists, meaning the container doesn't create the instance or ever know about it. You will have to pass it in as a resolution parameter, another concept supported by most containers.)
A decent default mapping might look like this:
[Presenter(typeof(LogOnPresenter))]
public class LogOnPage : PageView, ILogOnView
{
// ...
}

Resources