Last week Sunday while I was conducting a SharePoint WorkShop to my group members,before deeply getting into the agenda I just simply asked how many of you guys worked with UIP and shockingly everybody said ‘no’. I really got wondered and just realised that the software vendors are the culprit whom neither has a standard to follow or an architecture and just simply working on the projects just for revenue earning purpose.
This really made me to think a lot first of all in my experience every organization should have experienced developers as OO centric and apply UIP suppose even the system is complex , then UI process block is a must have framework as well.
Below is the article to give you an better idea about UIP if you haven’t heard about earlier.
Most UI development is dependent on pages/ screens communicating with each other. Historically there have been two approaches to UI design. Model View Controller ( also known sometimes as model 2) and the more simplistic model where every UI page/ screen knows about every other screen.This is also known as Model One architecture.
MVC UI architecture provides a clean separation of UI logic from the business code by providing a layer of separation between the two. This makes code maintainable and reusable.
Languages like Java have adopted this approach with frameworks like Struts and Web Work. ASP.NET by default is based on a the concept of a controller for every page in the form of a code behind where all the event handling occurs. However every page in this structure knows about every other page that it has to communicate to.
This lends to lots of code in the code behind class that does not easily lend to reuse. Another drawback is in testing the code behind. Since the code behind requires a container to run in, it becomes increasingly difficult to test the logic that goes in these classes.
UI Process Application block from Microsoft is an API that is written for large applications that have complex interactions.The process block does not assume a web based system. It can be used for rich clients and can be easily be extended for other custom clients
This application block provides session management, task management, state management and navigation management among other features.
This article explains techniques for testing code using UIP and other practical suggestions that will allow for understanding the application clock better. This article is focused around developing web based systems. However some of the concepts may very well be applied to other kinds of systems.
Using UIP 2.0
The main parts of the UIP block are the View and the Controller. Every page is a sub class of WebFormView. Views talk to the backend using controller. Views know only about themselves. Controllers in the application blocks are basically commands. Every view interacts with a controller.
Views are routed based on a navigation graph. Think of this as the sequence of steps or pages the user is required to go through. Here is an example of an entry in the config file
<views>
<view name=”MyHome” type=”home.aspx” controller=”MyController” />
</views>
A page called MyHome is part of a NavigationGraph called MyController which is defined in the config file as a WebFormViewManager.
Home.aspx.vb is a subclass of WebFormView, MyController is a sub class of ControllerBase.
As shown in the sequence diagram above the controller processes the users request, thus removing the call to the backend away from the code behind to a controller class.Note how a given web page is not aware of other pages. This separation is achieved by defined all the routing information in the config file
Navigation Management – Using GraphNavigator for a web based system
The UIProcess block works by trigerring a navigation path using a navigator. One such navigator is the graph navigator. Graph navigator forces the user to follow through a sequence of steps or a workflow. This feature is very useful for a system that requires such a workflow. There is the ability to disable the back button in such a way that the user will always be forced to go to the current state in the graph.
This limits the users ability to freely move around the system, which is required of many portals like news sites, health information sites( Non transactional / Non workflow based systems) . The open navigator ( instead of the graph navigator ) allows the users the ability to jump from any node in the navigation path to any other node.
Typically every application is taken to a home page when the application starts. To kick off navigation, somewhere in the beginning of the session ( like the global.asax file) the start navigation path can be initialized. The important thing to realize is that not every page in the system has to be in the control of the UI Process application block.
Pages that do not have to follow a certain graph don’t have to under the control of UIP. The problem is that things like task objects that hold on to state information will then have to be passed to such independent pages in other ways.
Here is an example that demonstrates this.
Let’s assume that a system has four pages. PageANotUnderUIPControl,PageBUnderUIPControl, PageCUnderUIPControl,PageDNotUnderUIPControl. The user starts at A and can navigate to B and then based on a user selection can go to either C or D as shown below.
PageA will basically route the user by doing the following line of code
– UIProcess.StartNavigationPath(“{The name of the path For B}”)
B- user does something that needs to be stored for the
next screen C to use.
In B we call
MyController.SomeMethod( passTheData )
and in the controller we can store in the State as MyController.State(anObject, passTheData)
State is a sub class of DictionaryBase, an abstract class that allows for strongly typed key and value pairs in its sub classes. Using the state is how caching is done in a given navigation path. This is different from the System.Web.Cache where is Key cannot be any object than a string.
Now if page B passes the call to a page D, there is no way of getting to the information in the State cache as this is outside the navigation graph. This results in duplicate cache maintained in a session.
If a user is in a particular screen in a browser he/ she can typically open a new browser instance from the same session . UI block keeps track of the various browser instances in a session and controls user entries.
On many we transactional web applications the user can click the back button and cause issues like re submit the data on the screen. Setting the allowBackButton to false in the config file would force the user to stay to go to the next valid state .
Unit testing with UI Process application block
Testing the code in the UI layer can get quite complicated. When using UIP, the view classes in a web system extend WebFormView. Such view classes are dependent on the need for running inside a ASP.NET container. But NUnit runs outside and does not have access to the the
Controller.
Classes that subclass ControllerBase have code like
Me.State.NavigateValue = "fail"
Navigate()
When writing a unit test, the code above will fail as there will be no place to navigate to when a NUnit test is running.
Controller can delegate its calls to smaller logical command classes. Those smaller classes can then be tested independently by NUnit,
Consider the method AddToCart that is a method on a controller class. It is tough to test this method using NUnit. This is because NUnit would not no what to do when Navigate is called . ( Navigate takes the user to the next aspx page)
Public Overridable Sub AddToCart(productId As Integer, quantity As
Integer)
Dim cart As New CartBusinessObject()= businessComponent.GetCart(user)
if cart.Validate()
Then
cart.AddToCart(Cart.CartItems, productId, quantity)
businessComponent.SaveCart(cart)
End If
Me.State.NavigateValue = “addItem”
Navigate()
End Sub ‘AddToCart
To overcome such issues the logic of validating and saving can be moved to a command object . Class AddProduct has a method called execute that takes the necesarry parameters for that command to succeed
Public Class AddProduct
Inherits ICommand
Public Sub New (user as User, productId As Integer, quantity As Integer)
‘Initialize here – Not shown
End Sub ‘New
Public Sub Execute()
Dim cart As New CartBusinessObject()= businessComponent.GetCart(user)
if cart.Validate()
Then
cart.AddToCart(Cart.CartItems, productId, quantity)
businessComponent.SaveCart(cart)
End If
End Sub
End Class ‘AddProduct’
This is a class that can easily be tested using NUnit . Now the controller looks as shown below
Public Overridable Sub AddToCart(productId As Integer, quantity As
Integer)
_command.Execute(productId,quantity,user)
Me.State.NavigateValue = "addItem"
Navigate()
End Sub 'AddToCart
The only thing that cannot be tested is the navigation which is certain to be tested developing the UI.