Monday, June 23, 2008

Intergrating Web Client Software Factory and Repository Factory

For those who uses Web Client Software Factory, you may find that it doesnt create a Data Access Layer for you and you might have wasted more than 1 day to write all the data access classes. Thanks to Codeplex, we have a repository factory that handle all them the data access functions for you.

If you are new to Repository Factory, please read the introduction first.

In this post, I will explain on how to integrate both of them into a web application to speed up your development as well as to cut down your maintenance cost.

First, Create Web Client Software Factory solution, and name it. Let's say "SampleWebApp". WCSF will generate all the default structures and files for ya.

Now, right click on the Solution, and Select Add-> New Project. You need to create 3 Class Library projects and name it as following:-
1.) Repository.Host
2.) Repository.DataAccess
3.) Repository.BusinessEntities

You may want to ask why 3? Good question, usually 1 is
sufficient but there are some bugs with the Connection String. Repository
Factory requires you to use a project to host the connection string and most of
us uses website project to hold the reponsibility, but Connection String couldnt
be found by the Repository Factory wizards when we create Business Modules/Views
using WCSF first before creating data repository class files. So if you are
using 1 Class Library project, make sure you start from repository project
first.


Besides, using 3 Class Library projects are alot easier to
maintain. For example, when you are creating Data Access or Business Entities,
the namespace of the class files will follow the Class Library project name, for
instance "Repository". So it will be very messy if Business Entities and Data
Access files fall into the same namespace. If you want to split them up in the
namespace, it will take some time for you to manually change the namespace of
each file into Repository.DataAccess or
Repository.BusinessEntities.


Next, assign the Reponsibility of each Class Library projects by right click each Class Library projects and select Repository Factory -> specify project responsibility
1.) Repository.Host -> Host
2.) Repository.DataAccess -> Data Access
3.) Repository.BusinessEntities -> Business Entities

Now, setup the database:-
1.) Create database
2.) Create tables

You have done all the necessary setup. You may start with :-

Create and Assign Connection String
1.) Connection String for Repository Factory
Right Click the Repository.Host project, Select Repository Factory -> Add Database Connection

2.) Connection String for Website
Go to the website node, and search for the master web.config. Right Click and Select Repository Factory -> Add Database Connection to Configuration file. Once you have created it, Right Click the web.config and Select Edit Enterprise Library Configuration. Select Data Access Application Block node and open Properties. Assign the default Database to the Connection String that you just created.

Create a business module and a page under the module
Using WCSF, right click Modules section and select Web Client Factory -> Add a Business Module(C#/VB). For example, named it "Member".

Under the website node, you will noticed that a Member folder is created. Right Click and select Web Client Factory -> Add a View(C#/VB). Then an aspx page will be created under Member module. To verify it, you will notice that a presenter class file is created along under the Member module node. For instance, "CreateMember.aspx"

Create Business Entities
Go to Repository.BusinessEntities project, right click and select Repository Factory->Create business entities from database. It will prompt you a wizard. Follow the wizards and complete the process.

1.) First, select the Host Project, it should be Repository.Host, and the connection string and then Click Next.
2.) Then, select the tables that you want.
3.) View the attributes and Click Finish.

The business entities class files for the tables you want are created under the project.

Create Stored Procedure
Go to Repository.DataAccess project, right click and select Repository Factory->Create CRUD Stored Procedure. Follow through the wizard again.

1.) First, select the Host Project, and the connection string and then click next.
2.) Select the tables that you want.
3.) Then you will notice that the wizard provide 5 common operations for each table. If there is any that you do not need, uncheck the checkbox for the particular operation. Change the SP name if necessary. Then click Next.
4.) In the last screen, input a file name. And click Finish.

Repository Factory has created a SQL file for you to create the stored procedures. Copy and Paste the script into Management Studio and execute it.

Before you execute it, make sure to change all the Alter Procedure to Create Procedure. Click Check and Execute. If there are errors saying procedures' names existed, Change all the Create Procedure back to Alter. Then execute it again.

Note that if you are using SQL Server 2000, there are some syntax taht you need to remove, for example, remove

begin try, end try, begin catch, end catch, RethrowError procedure

and replace

sys.objects->sysobjects

Once you have successfully execute the script, you can find all SP in the database. If you want to create a customized SP, you may need to create them manually in the Management Studio.

Create Data Repository Classes
Now it's time to create Data Repository classes. Right Click Repository.DataAccess and select Repository Factory->Create data repository classes from business entities.

Go through the wizard again.
1.) Select the Host project and connection string and click Next
2.) Select the business entities project and click Next
3.) Select the entity that you want and click Next
4.) Then, in this screen you will find that the wizard has created all the common operations for you except GetBy operations.

Auto Created Operations: Insert, Update, Delete, and GetAll

5.) Now you need to create GetByPK (Get One) by clicking add, select the right stored proc and check the mapping. if correct click finish.
6.)Then you need to create GetByFK (this one usually Get Many) if applicable.

I assume you know how to create them. Once you have done, click finish and all the data repository classes will be created.

If you want to modify the namespace, you may do so. Else save and build it. Make sure you do not have any error.

NOTE: Do not overwrite any repository classes. Must Remember! Delete it before you copy over.

Create function to access Data Access Layer
Go to Module section, look for Member module (if you are working on member module)
1.) right click References and select Add References.
2.) under the Projects tab, add Repository.BusinessEntities and Repository.DataAccess. (So that you have the reference to those projects and use their fucntions).
3.) you will also need to add reference for Microsoft.Practises.Repository.dll into the module references. you can find it in C:/Program Files/Microsoft Patterns & Practices/Data Access Guidance Package Setup/.
4.) Open the controller file. In this case, MemberController.cs and insert the following codes:

using Repository.BusinessEntities;
using Repository.DataAccess;
using Repository.DataAccess.MemberRepositoryArtifacts;

//In the MemberController Class, insert the following codes:

IMemberRepository _member;


public void CreateMember(member obj)
{
_member = new memberRepository();
_member.Add(obj);
}


5.) Save and Close.

Create a business function for insert member operation in Presenter
If you have created a View/Page under Member module, for e.g. CreateMember.aspx, you will notice a CreateMemberPresenter file in the same module under View folder.

1.) Open it and if the controller object is commented, uncomment it.
2.) Create a function as follow:-

public void OnCreateMember(member obj)
{
_controller.CreateMember(obj);
}

To simulate the outcome
1.) create a link button in Default.aspx under Member folder in the website node.
2.) In the code behind, insert the following codes into the link button OnClick event handler.

Response.Redirect("/DevelopmentWebsite/Member/CreateMember.aspx");

Then, Im going to simulate an insert during a page initialize/load.

3.) Open CreateMemberPresenter.cs or vb.
4.) Look for the function OnViewInitialized().
5.) In the function write the following codes:


public override void OnViewInitialized()
{
member mem = new member();
// I did not insert value for "id" because it is set auto-increment in the table.

mem.name = "Chris";
mem.age = 26;

this.OnCreateMember(mem);
}

Finish
In real project, you may want to supply the data using form or by user input. So you may ignore the Simulate section as it is just to verify the result.

Hope it helps.

Performing Insert, Update and Delete using ObjectContainerDataSource

It is very easy and effective to use ObjectContainerDataSource to handle insert, update and delete event. When the user performs an update operations, insert operation, or delete operation in a data-bound control, the data source control raises the following events.

C#

public event EventHandler Updated;
public event EventHandler Inserted;
public event EventHandler Deleted;

For example, if you are using DetailsView and ObjectContainerDataSource in your page to create a Insert form,

1.) Named your ObjectContainerDataSource, like MemberDataSource
2.) Set your DataObjectTypeName.
3.) Named your Details View, like dvCreateMember
4.) Set the DataKeyNames="id" in Details View, most of the time it should be the primary key.
5.) Set the DataSourceID="MemberDataSource" Details View
6.) Set the DefaultMode="Insert" in Details View
7.) In the ObjectContainerDataSource, set the OnInserted event name.

Codes will look like this:-


<div>
<asp:DetailsView ID="dvCreateMember" DataKeyNames="id" DefaultMode="Insert" runat="server" AutoGenerateRows="False" DataSourceID="MemberDataSource">
<Fields>
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="age" HeaderText="Age" SortExpression="age" />
<asp:CommandField ButtonType="Button" InsertText="Create" NewText="Add New" ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
<br />
</div>
<pp:ObjectContainerDataSource ID="MemberDataSource" runat="server" DataObjectTypeName="Repository.BusinessEntities.member" OnInserted="MemberDataSource_Inserted" />
In the Code Behind Page, the event handler function will look like this:-


using Microsoft.Practices.Web.UI.WebControls;

protected void MemberDataSource_Inserted(object sender,
ObjectContainerDataSourceStatusEventArgs
e)
{
_presenter.onCreateMember((member)e.Instance);
}


The data that inserted into the details view will be automatically stored into the e.instance when it is passed to ObjectContainerDataSource. Hence, there is no need to have extra code to map the data from UI to back end codes.

Noticed that there is a function onCreateMember() being called in the Inserted event. It is the function defined in Presenter Layer.

### Presenter Class File###


public void onCreateMember(member
obj)
{
_controller.CreateMember(obj);
}

And, CreateMember() function is defined in Controller layer.

###Controller Class File###


public void CreateMember(member obj)
{
_member = new memberRepository();
_member.Add(obj);
}

In the above function, it is call the add function from Data Access layer. You may use Repository Factory to generate those.

Friday, June 20, 2008

ObjectContainerDataSource in Web Client Software Factory

The Web Client Software Factory contains the data source control ObjectContainerDataSource. This control implements data binding in a way that easily integrates with the View-Presenter pattern.

You can think of the ObjectContainerDataSource control as a container of objects. You programmatically populate the container, and the container raises events when changes occur to any of the contained objects. This design allows the view (Web page) to delegate the responsibility of performing select operations, update operations, delete operations, and insert operations to the presenter.

How to Use ObjectContainerDataSource?

To add ObjectContainerDataSource controll into the toolbox:
right-click the Data tab in the Toolbox, and then select Choose Items. On the .NET FrameworkComponents tab, click Browse, select the Microsoft.Practices.Web.UI.WebControls.dll assembly, and then click Open. Select the ObjectContainerDataSource control in the list of components, and then click OK.

to use it, Drag and drop the control into the UI. Then
1.) Go into Design Mode and click on the Show Smart Tag, and select Configure Data Source..
2.) Noticed that you need to specify a Data Object Type. Select an appropriate object.
3.) Named the container. for instance, MemberDataSource.

For example, to show items when view loads:-
1.) First create a property for set operation in the page code behind.

Public IList memberDS
{
set { MemberDataSource.DataSource = value};
}


2.)To be visible in Presenter, Open IMemberView in the Member module and add a definition as following:


IList memberDS {set;}


3.) go to MemberPresenter, inside the OnViewInitialized method, put this the code.

This.View.memberDS = data... ;


4.) In the page, drag and drop a Grid View, and set its data source attribute to MemberDataSource.

Business Module, Foundation Module and Page in Web Client Software Factory v1.1

Dear all,

It has been some time I have not posted anything about web client software factory as I was busy with my rl work. Web Client Software Factory is my favourite tool when creating a web client. I suggest everybody should give a try on it.

Recently, I have given a sharing session about Web Client Software Factory for a bunch of interns who are about to graduate from university (Multimedia University) and I realized I should continue writing more about it so that it can help others to get more details on what exactly WCSF does.

If you do not know what Web Client Software Factory is, please visit Introduction to Web Client Software Factory post to have some kick starts. Web Client Software Factory uses Model-View-Presenter architectural pattern to encourage reuse of the individual User Controls (referred to in CAB as "SmartParts") by not coupling them with their underlying data elements or presentation code.

The structure will look like this:

Page <--> Presenter <--> Controller

In this post, I will cover a few essential fundamentals about WCSF.
1.) Business Modules
2.) Foundational Modules
3.) Page/View

1.0 What is a Business Modules?
Business Module is a type of Module that encapsulate a set of concerns of the application at Module Level. The logics created in a particular business module will be shared accross the module. When a user create a business module in WCSF, a default web page will be created under the website node in the module name's folder.

Files Created by WCSF:-
Website Node: a folder named as the module name which contains a web.config, Default.aspx and Default.aspx Code Behind.
Module Node: a folder named as the module name which contains a Presenter Class file for Default.aspx, and View Interface for Default.aspx, Controller Class file and ModuleIntializer Class file.

1.1 How to Create a Business Modules
To Create a Business Module, select the MODULE node and right Click. You will notice a menu item named "Web Client Factory". Click on it and Select "Add Business Module (C# or VB)".

An add business module wizard will appear:-
1.) Add New Project: Give a name to the module and give a path(if it is different from the default).
2.) Module Details: Check the checkbox for Unit Test if you require it.
3.) Click Finish.
4.) Debug it and you will notice a new menu named as the module name added into the website.

2.0 What is Foundational Module
It is quite similar to Business Module, but it does not allow you to create Page/View under this module. Which means, Foundational Module does not have Presenters nor have Controller. It also will not create a folder with default page in the website node like how Business Module does. The set of concerns that encapsulate in this type of module is shared across the whole application. Usually, Global services are created in this module and each application will have only 1 foundational module.

2.1 How to create a Foundational Module
To Create a Foundational Module, select the MODULE node and right Click. You will notice a menu item named "Web Client Factory". Click on it and Select "Add Foundational Module (C# or VB)".

An add foundational module wizard will appear:-
1.) Add New Project: Give a name to the module and give a path(if it is different from the default).
2.) Module Details: Check the checkbox for Unit Test if you require it.
3.) Click Finish and Verify it at the MODULE node.

3.0 What is a Page/View
Page is a web page so it has .aspx extension and a Code Behind Class file. User can add UI elements to a page.

3.1 How to Create a Page
To create a page, you need to consider which business module it belongs to. For instance, a CreateMember.aspx will fall into Member module or it is directly under the root node (Website node).
1.) Right click on the module folder under the website node or right click on the root node
2.) Select "Web Client Factory" and Click on Add a View(C#/VB).

a Wizard will be appeared and Change the name for the particular View and click Finish.

You will notice that (for e.g CreateMember) a CreateMember.aspx created under the Member folder(if it is created in Member folder), and under the Member module, CreateMemberPresenter and ICreateMemberView are created.

I hope this will give you more understanding on how Web Client Software Factory does.

Tuesday, June 10, 2008

Repository Factory Error: Object reference not set to an instance of an object.

Problem Statement
If you are using repository factory to create your data access layer and you get error in page showing

"Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object."

And the problem is pointing you at the Repository Object, for example:

Line xx: public sampleRepository()
Line xx: : base()

The problem comes from the connection string. You have not specified a default connection that you are using.

Solution
1.) Open your web.config with your Enterprise Library Editor, and select Data Access Application Block node and open it in Propertise.
2.) In the DefaultDatabase field, select your connection string that you have created.

Compile the project and run again. It should work now.

Creating Data Access Layer using Repository Factory

Repository Factory is a guidance package that automates creation of entity classes that map to database tables and repository classes to read and write those entity classes.

There is an existing blog that has done a good job in demostrating how it works so I dont think I need to rewrite a new one. Please visit http://developer.bracora.com/Articles/DataAccessLayer.aspx

If the link is broken, do let me know and I shall consider writing a new one.

Web Client Software Factory error "Failed to map the path /" in Vista


There is a problem when developer trying to debug a WCSF project in Vista. The page will show something similiar above. "Server Error in '/DevelopmentWebsite' Application" and "Failed to map the path '/'"
But not too worry, to solve the problem, you have to quit the Visual Studio program and restart the Visual Studio program (either 2005 or 2008) by right clicking the exe and select RUN AS ADMINISTRATOR.
Then it should work fine.


Monday, June 9, 2008

How to make Repository Factory supported in VS 2008?

I believe this has been an issue to alot of developers that have used to build the data access layer using Repository Factory for the past years using VS 2005. Unforturenately, Microsoft has shown no more interest in upgrading the current package to support VS 2008 and .net 3.0 above.

However, the community has taken alot of test to move it to VS 2008. I wish to give a big thank to 2 developers who have provided us a workaround, Jose Escrich and Noel Anderton!

Noel Anderton 's piece
"So we have taken the Source for the Guidance and opened in vs2008 this updated the guidance to vs2008 projects with out incident. We made sure we had the VS 2008 Guidance package for creating guidance packages installed and enabled the package. We then ran the Register guidance recipe which successfully registered the Repository Package Guidance. We opened another version of VS2008 and used the repository guidance to create a solution.. Great. So we tried the installer. We updated the registry paths in the launch conditions of the set up project and after unregistering in vs the guidance package we ran the installer. The installation was ran without error but when we attempted to use the repository guidance package we could not enable it. It did not show up. "

the above content can be found in http://www.codeplex.com/RepositoryFactory/Thread/View.aspx?ThreadId=23088

Jose Escrich's piece
To achieve that you must add/change some arguments in all the custom actions as follow:

/Hive=9.0 /Configuration="[TARGETDIR]MyGP.xml"

the argument that you have to change is /Hive=9.0 and also you can specify something like /Hive=9.0Exp /RANU in case that if you want to register the guidance package into the experimental hive and RANU mode. Note that changes applies just for the installer so, if you want to change the registration hive in design time, that's when you register a GP through Visual Studio, you have to add under the GuidancePackage element a HostData child element as follow:
<HostData>
<RegistrationSettings>/Hive=9.0</RegistrationSettings>
</HostData>


the above content can be found in http://forums.msdn.microsoft.com/en-US/vsgatk/thread/194e5c70-aa51-4de6-96df-cfda1c8832be