Today I´m a proud programmer!
Today was one of the most amazing days for me in programming NMvp.
I´ll explain why!
First Production Application
We, at the company I work for, have just finished our first production application using NMvp. This application was built by 8 people.
So while people were building it I observed two things:
- Creating load methods in ContainerPresenters is just not intuitive. People asked me a couple of times: "Why should the Load method be in the ContainerPresenter and the Save method in the ContainerItemPresenter?" to which I kept answering that the load method is done once for all container items, while the save method is called for each item of the container (in a way that one item knows how to save himself). Even after clarification this didn´t get very clear in their heads.
- People just won´t do unit tests. And they told me why: "Bernardo, we have VERY little time to deliver the application. If we just had to write the unit tests, fine, we´d do it. But we have to write a ton of mocks first. And mocks are hard to write.". Ok, here I believe that people are just not used to TDD, but anyway I had to find a solution.
So after giving a deep thought on both issues (not so deep anyway, lol), I came up with the solutions:
- Change MvpContainer so it can be bound to ObjectDataSource
- Create a MockFactory class that allows for easy mocking
So I had to enable databinding in the MvpContainer to enhance ASP.Net integration and I had to enable easy mocking to enhance Unit Testing (I know, I know! Windows Forms will be next!).
DataBindable MvpContainer
So this morning I got up early and started to change the MvpContainer. I ended up VERY HAPPY with this code:
<uc2:ProjectMembersContainer ID="ProjectMembersContainer1" runat="server" DataSourceId="projectMembers" />
<asp:ObjectDataSource ID="projectMembers" runat="server"
TypeName="NMvp.TestModel.Project.Rules.ProjectMemberManager"
SelectMethod="GetProjectMembers"> <SelectParameters>
<mvp:PageParameter PropertyName="InstanceId" Name="projectId" Type="int32" Direction="input" /> </SelectParameters>
</asp:ObjectDataSource>
Before you ask: the GetProjectMember method returns a List<Data.ProjectMember>. Yeah that´s right, your old and faithful Data Object, now disguised as a Mvp View. And no, PageParameter does not come with ASP.Net. I implemented it, since the InstanceId variable tend to be used a lot and it´s only available in the Page.
If anyone wants to use the page parameter feel free to use it (code in the end of this post).
So after a few quirks the NMvp.Web.MvpContainer control now supports databinding to an ObjectDataSource. Yes I will support other data source types. In the FUTURE!
MockFactory - Making mocks easier on the user
Now onto the second issue at hand. This one was a lot more tricky (even though at first I thought it was the easy one).
My problem was:
I need my framework users to create mocks like this:
IProjectDetails pdm = MockFactory.CreateViewMock<IProjectDetails>();
IProjectMembers pmm = MockFactory.CreateContainerMock<IProjectMembers, ProjectMemberPresenter>();
As you can see, no need to create any mock classes anymore. The framework does the job for you (it even creates ContainerItem mocks for you). The MockFactory class has 3 methods as of now:
CreateHostMock - Creates a mock instance of IHost.
CreateViewMock - Creates a mock instance of IContract.
CreateContainerMock - Creates a mock instance of IContainer and a mock instance of ContainerItem (to be used in the IContainer). It gets a Presenter type so it can infer the container item contract for you (and create the presenter as well).
Now let me explain why this was tricky: It´s all created at runtime. Yeah you got it right: CODEDOM! And let me tell you, it´s not for the faint of heart!
I´ll post an article at a later time on how to use this feature and how it was developed.
When will all this be available for me?
I´m trying my best here people! Today I woke up at 06:00, worked in the framework until 08:00, went to work, got back and worked in it from 21:00 to 1:15.
So my best guess is that it will be released this Saturday (03-Feb) or Sunday (04-Feb).
How can I learn all this great stuff?
Last but not least, I´m writing a book on NMvp. It will be called NMVP Inside-Out, and it will be released in hard cover and paper back. Oh, did I mention that it will be released as PDF free-of-charge? If not, forget I said anything and please buy the book, lol! Just kidding... My goal here is that people will get as excited about this framework and the MVP and CMVP patterns as I am. Hope it helps.
Ok, that was all very nice but I WANT THE PAGEPARAMETER!
Ok, Ok, easy! Here it goes: (please be a nice fella and keep my name in it, ok?)
/// <summary>
/// Parameter that gets a property from the page.
/// </summary>
/// <remarks>This was built by Bernardo Heynemann
/// (heynemann@gmail.com) for project NMVP.
/// </remarks>
public class PageParameter : System.Web.UI.WebControls.Parameter {
private string propertyName;
/// <summary>
/// Name of the property to evaluate.
/// </summary>
public string PropertyName {
get { return propertyName; }
set { propertyName = value; }
}
/// <summary>
/// Default constructor.
/// </summary>
public PageParameter() : base() { }
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="original">Original parameter.</param>
public PageParameter(PageParameter original)
: base(original) {
this.PropertyName = original.PropertyName;
}
/// <summary>
/// Evaluates the value to return to the datasource.
/// </summary>
/// <param name="context">Context of the ASP.Net application.</param>
/// <param name="control">Control that owns the parameter.</param>
/// <returns>Returns the value to the datasource.</returns>
protected override object Evaluate(HttpContext context, Control control) {
PropertyInfo pi = control.Page.GetType().GetProperty(PropertyName);
if (pi != null) {
return pi.GetValue(control.Page, null);
}
return null;
}
/// <summary>
/// Clones this parameter.
/// </summary>
/// <returns></returns>
protected override Parameter Clone() {
return new PageParameter(this);
}
}

#93