All,

There are some challenges in using Model/View/Presenter with Async pages in ASP.NET 2.0.

Here is a simple example where I want to ’screen scrape’ an HTTP Stream from another web site.

To do this I:

1) Define a delegate in a lower level assembly (not in the UI) with the following signature:

public delegate ScrapePage ExecuteSearch(String hiddenFormTarget, String getQueryString, String LastBaseURL, WebScrape oWeb, String CurrentURL, NameValueCollection oNVC, int ActiveSearch);

Don’t worry about why I am passing in so many parameters to this delegate. You will see why in a minute.

So first ensure your page has this in the @Page declaration:

Page Async=”true”

Now enter the Model/View/Presenter pattern.

1) Ensure your partial page implements the proper view interface as such:

public partial class websearch : Page, IWebView

2) Create a Concrete class for your Presenter and create it in page_load.

//This is MVP Pattern
WebPresenter presenter = new WebPresenter(this);

//This is required for Async processing and MVP
AddOnPreRenderCompleteAsync(
new BeginEventHandler(presenter.BeginGetAsyncData),
new EndEventHandler(presenter.InitView));

Rememeber that as soon as your presenter.BeginGetAsyncData ends (which is fast as it is Async), the thread you were using is returned to the thread-pool. This is a good thing, however you now are lost when you enter presenter.InitView as you DO NOT have access to HttpContext (and in my experimentation CallContext is bust as well which makes sense).

So that is why I must pass so many variables in.

As this is an Async operation here is the signature (it must be) for InitView:

public void (IAsyncResult itfAR)

The cool thing is it is in this method that I populate the view.

For example, here is the code:

public void InitView(IAsyncResult itfAR)
{

AsyncResult ar = (AsyncResult)itfAR;
ExecuteSearch GetHTML = (ExecuteSearch)ar.AsyncDelegate;
object Result = null;
ScrapePage oPage;

Result = GetHTML.EndInvoke(itfAR);
oPage = Result as ScrapePage;

if (oPage == null)
{
_View.CurrentDisplay = “”;
}
else
{

if (!oPage.IsPDF)
{
_View.LastBasePage = oPage.BasePage;
_View.CurrentDisplay = oPage.PageBody;

}
else
_View.PDFDisplay(oPage);
}
}

Notice how I reference the _View. I am actually updating the screen here (I also have this running with Unit Tests with a mock view).

When I say:

_View.CurrentDisplay = oPage.PageBody;

This actually calls this on the page:

public string CurrentDisplay
{
set
{
litSearchResults.Text = value;

}
}

So I am completely abstracted from UI Controls and presentation detail. There is a lot more to this, so if you are interested contact me.

Thanks,
Damon

Post a Comment