« December 2007 | Main | February 2008 »

January 31, 2008

Working with MSMQ Journal Queues

In one of our internal forums, recently, someone had posted a query regarding issues in connecting and receiving messages from journal queues. The exception they were getting was "Queue ID is not registered in DS". I hadn't worked with Journal queues before, but this error seemed to me to be related to the queue path.

In my earlier blogs (here and here), I had discussed about the importance of specifying the right name for the queue and also mentioned how the path will typically look like. I decided to give it a try and created a private queue on my local machine and enabled journaling on it. Enabling journaling is as trivial as checking a checkbox in the queue property window.  You can also enable it by setting the UseJournalQueue property on the message.

Having done this, I used the syntax as described on MSDN Documentation.

            MessageQueue queue = new MessageQueue(".\\test\\journal$");

To my surprise, I got an exception stating "A workgroup installation computer does not support the operation." Well, it isn't really a surprise, since this syntax is for public queues and that's what the error message is also indicating. The following are the various syntaxes that did work for me. You could use either of the following based on your own preferences.  Note that the "test" in the queue path is name of the private queue that i created.

            MessageQueue queue = new MessageQueue(".\\private$\\test\\journal$");

            MessageQueue queue = new MessageQueue(".\\private$\\test;journal");

The casing for "journal" doesn't matter and you can very well specify it as "JOURNAL". So much for local private queue. I quickly tried accessing the journal queue for a remote private queue as well, and following worked for me

            MessageQueue queue = new MessageQueue("FormatName:DIRECT=OS:server\\private$\\remote;journal");

Where "server" is the remote machine name. Again, "journal" can be specified as "JOURNAL" as well. The following, though is an extension of what worked in case of local private queue, didn't work for remote private queue and I got a "Format name is invalid" exception.

            MessageQueue queue = new MessageQueue("FormatName:DIRECT=OS:punhjw30076\\private$\\remote\\journal$");

January 30, 2008

Hierarchical Data Categorization using LINQ to Objects in n-tier applications

The intention here is not to talk about LINQ; rather to apply LINQ in enterprise applications. A typical n-tier application consists of Presentation, Business/Service and Data layer and the communication across the layers is done through Presentation, Services/Business, Data entities. We write translator classes which maps the Data entities to their corresponding Service entities and so on. This is fine as long as the mapping is one to one. The problem arises when we have store procedures (SP) returning composite entities. The situation gets complicated when we have to parse the composite entity returned from SPs into a hierarchical parent-child structure. With LINQ to Objects this task is very much simplified.

I will try to illustrate this with an example. I have two business entities Category and SubCategory.

public class Category

{

    public int Id {get;set;}       

    public List<SubCategory> SC {get;set;} //SubCategory is the child object of category

}

 

public class SubCategory

{

    public int Id {get;set;}

    public string Name {get;set;}

}

 

Output from the SP in my Data Access Layer is combination of the above entities.

A sample output from the SP:

CategoryID

SubCategoryID

SubCategoryName

1

1

“SC1”

1

2

“SC2”

1

3

“SC3”

1

4

“SC4”

2

1

“SC5”

2

2

“SC6”

3

1

“SC7”

4

1

“SC8”

Let me assume the result is stored in an entity which maps the output. Let me call this RecordCategory

public class RecordCategory

{

    public int Id {get;set;}       

    public int SId {get;set;}

    public string SName {get;set;}

}

 

The job now is to convert the rows of records into a hierarchial data struture correspoding to Category-SubCategory entities i.e. every CategoryID should coresspond to s single Catehory object with a list of SubCategory objects having the same CategoryID.

Here is how this is done:

List<RecordCategory> rc = new List<RecordCategory>();

//rc = Retrieve data from SP

//Group the records retrieved form the SP on their

//Category Id using the group by query operattor

IEnumerable<IGrouping<int,RecordCategory>> cat = from p in rc

                                    group p by p.Id;

 

The data will be grouped hierarchially.But the business layer expects a list of Catgeory objects along with SubCategory data.

List<Category> cat1 = (from c in cat                           

    select new Category {Id = c.Key,Name = c.First().Name, SC =

        (

            from d in c

            where d.Id == c.Key

                select new SubCategory{Id = d.SId,Name=d.SName}

            ).ToList()

    }).ToList();//Return the cat1 object to BAL

 

All we are doing here is running a nested query to group all the SubCategory object inside the Category object.

We could have achieved the same result without using LINQ – but then we had to resort to endless for loops and conditions.This is how elegant our code can get using LINQ!!.

January 28, 2008

Branding in SharePoint Technologies (PART 4)

Today we will look at the option of Site Definitions and Features for modifying the Master Pages.

Site Definitions: As the name suggests, site definitions has all the required information for provisioning a site. There are different site definitions, for different purposes, which are used to provision sites. All site definition files (including the master pages) are stored on the file system; unlike, the site templates that are stored in the content database.
The process to create new site definitions for custom branding is outside the scope of this article. Following is a brief outline of the process:
1.Site definitions are located at <Drive:>\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\SiteTemplates.
2.Copy the desired definition with the name of the custom site definition
3.Change the WEBTEMP XML file with the addition of the configuration node in the templates node for the custom site definition located at the location as shown in Figure 6: Location of the WEbTemp*.xml files. The display category takes care of the tab in which it appears when a person tries to create it through the UI. For more information on the templates and their respective entries, see  http://www.sharepointblogs.com/photos/tbaginski/images/2552/original.aspx.
Note: IIS Reset needs to be done for the changes to get effected and the new site definition to appear during the site creation process.

There are two issues with this approach:
•This requires good understanding of xml files which are used for provisioning the sites. The files include onet.xml and webtemp*.xml files
If OOTB templates are modified then MS technical support will not support them. One needs to be very careful while editing any OOTB site definitions.
•The best alternative is to create a clone of a similar site definition, and edit it to meet the template requirements.
•Sites can be created using any template within a Web Application. This calls for having a one-to-one mapping for all the OOTB templates, in a way to ensure that the end users/administrators use only these templates to create the site. This calls for the discipline during the web application creation. Using OOTB template will result in branding inconsistencies as that will just have the default branding.
 

Features: ‘Features’ is a concept introduced in SharePoint to increase the modularity of the functionality/ elements developed on it. Functionalities like custom workflow, event handlers, copying files, etc can be handled using features. They are highly modular, componentized, can be applied to any site at any level within a Web Application. They can be automatically activated and deactivated.
Using this concept, the master pages for a given site collection is packaged into a feature and applied so that it is copied to the respective gallery and is applied automatically. It is not mandatory to apply the feature automatically. The administrator can apply the master page of choice by browsing through the gallery at any time. A classic OOTB example for this is the ‘SharePoint Server Publishing Infrastructure’ feature which adds master page to the gallery.

Note: Master Pages should be copied to the site collection master page gallery as the SharePoint Look and Feel option in the site settings always refer to this gallery when the admin browses to change the master page

The process to create new function is outside the scope of this article. Following is a brief outline of the process ((The sample will have all the required things so that the end user can customize and start using it) :

1.Create a folder under <Drive>\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES with the name of the feature
2.Place the required .css files, master pages, images required etc in this location
3.Script both the Feature and the elements manifest files
4.Make sure the master pages go to the master page gallery and the other resources go to the style gallery. Sample of this looks like

<Elements xmlns=”http://schemas.microsoft.com/sharepoint/”>
    <Module Name=”CustomMasterPage” Url=”_catalogs/masterpage” RootWebOnly=”TRUE”>      
        <File Url=”CustomPage.master” Type=”GhostableInLibrary” />  
    </Module>
    <Module Name=”CustomStyles” Url=”Style Library” RootWebOnly=”TRUE”>      
        <File Url=”Custom.css” Type=”GhostableInLibrary” />  
        <File Url=”HeaderImage.jpg” Type=”GhostableInLibrary” />  
</Module>
</Elements>

There are different options available both for the module element and the file elements (that is outside the scope of this document).
5.Once this feature is installed using the stsadm utility the master pages and the resource files will become available in their respective gallery.
6.Now this feature can be automatically activated to apply it using another feature called staper feature (The feature discussed above is called the staplee feature). For more information about defining this feature, see http://blogs.msdn.com/sharepoint/archive/2007/03/22/customizing-moss-2007-my-sites-within-the-enterprise.aspx
Note: In addition to deploying the pages into the gallery, features can also be used to deploy the pages into the file system which effectively means that pages can be deployed into site definitions as well.

The following table gives the broad guidance on the scenarios and relevant options.

Creating Multiple Versions of Workflows

In the recent past, a question that has surfaced quite often is regarding the versioning of workflows and the errors that show up when trying to do so. It is quite natural to expect an extreme level of dynamism and out-of-box features from Microsoft, but one needs to take a pragmatic view of WF.

There is a clear distinction between a Workflow Definition and a Workflow Instance. A Workflow Definition is a Template and a Workflow Instance is a runtime representation of that template. We can closely relate to the Workflow Definition and a Workflow Instance to a Class and an object respectively.

A Workflow can be authored programmatically in C# or exclusively in XAML or using a combination of both. When a workflow instance is created and persisted, it is persisted with its state and also the type information of workflow and activities used. During this cycle of instance passivation, if the definition of the workflow (or the activity used in the workflow) is changed and the assembly with the old definition is removed, then the workflow runtime throws an error. This is an expected behavior since Binary Serialization is type dependent.

Workflow Foundation does have a solution to this problem in the form of Dynamic Workflow Updates using the WorkflowChanges API. The following is one of the possible ways of mitigate the problem of workflow versioning:

1. The assembly with the new workflow definition (or activity definition) is added to the GAC (or a location where you reference your assemblies from). This will sit beside the assembly (older version) that contained the older definition. The assembly with the older definition(s) MUST be present in the GAC (or a location where you reference your assemblies from).

2. When the workflow is to be rehydrated, identify the changes between the older definition and newer definition by getting hold of the corresponding definitions and apply changes to the workflow using the WorkflowChanges API.  Once the changes are done, the workflow can be resumed. Two ways in which this can be done:

- This can be done on-demand or can be a background process. When we say on-demand, the applying of changes is done when the workflow is rehydrated by the user or application and it is resumed immediately.

- If it is a background process, the workflow instances corresponding to this workflow can be loaded into the memory; changes can be applied and the instances can be dehydrated back to the persistence store. So, when the workflow instance is next invoked by the application, it is loaded and resumed directly. This process can be accomplished using a windows service. However, the synchronization aspect should be taken care of here.

But the question definitely remains as to why there isn't a mechanism which can change the instances when there is a change to the definition of the workflow? Here is one possible reason:

A defintion is a "Stateless" entitiy while an instance has a "State". A workflow definition is either a .NET assembly or an XAML file which is used to create an instance. Any change to the definition means a change to the stateless entity and it happens at design-time. To get this reflected on to a run-time entity needs a program to do so. Moreover, the Workflow Persistence Service can be customized and this makes it an even greater challenge.

For a small set of workflows, the issue of versioning may not really be a show stopper. However, when planning a large scale use of WF, it is necessary to take an appropriate view of the versioning required and move ahead. It is important to set the expectations right before dealing with situations like these.Smile

Enterprise Collaboration - Role of Technology

Lately, there has been a lot of buzz on collaboration and how it is becoming important for rapid innovation especially in a globally distributed and culturally diverse business environment. Technology is being seen as an important enabler and catalyst for collaboration. Enterprises are viewing technology usage from different perspectives to enhance and address different aspects of collaboration.

I tend to group these into 3 perspectives: 

1. Information Perspective - Make it easy to find and share information

Most large enterprises have teams spread in several geographies. Finding information and managing shared information is becoming increasingly difficult. Most of these organizations are recognizing the need for an enterprise wide information management strategy that takes into account not just structured but unstructured data as well. If most of the documents in your enterprise are being shared using emails irrespective of number of recipients and it's hard to find information when you need it, I think you know what I am talking about.

Movement of large platform vendors and increased adoption of collaborative information management tools like Microsoft SharePoint Server is a clear indication that enterprise are taking this aspect of collaboration quite seriously. From a Microsoft point of view, this has enabled them to move from a successful information worker tools provider into the Information Management space.

2. Communication Perspective - Make it easy to express and communicate effectively

I often feel the need to walk up to the person and express myself, especially when the problem or idea is not well defined or still in conceptualization phase. With distributed teams, effective communication of ideas\problems etc is an important aspect of collaboration. Depending on factors like the number of people I am communicating with, the time zone factor, urgency level and complexity of the message, I would like to use different set of communication tools. While a plethora of tools are already available for communication in most enterprises, the disjointed manner it which these are being made available is impacting adoption (after the initial excitement). Clearly, there is need to deliver enhanced communication capabilities in an integrated and synchronized manner.

Several enterprises are already laying foundations for this through a variety of technology initiatives like VoIP enablement, messaging upgrades, integrated presence, mobility etc. However, the human aspects or the experience aspects of these still being neglected due to which a lot of money\effort is likely to be spent after the deployment in trying to make people use the technology. Clearly, there is a need to focus on human and experience aspects early and take a unified people or role oriented approach for such initiatives.

Microsoft, which has already large deployments of Exchange and Messaging software and a popular mobile platform, is investing heavily the unified communication area. These are still early days and it will be interesting to watch in what direction does the market moves.


3. People Perspective - Make it easy to find people and connect with them

One of the other aspects that people in global enterprises are struggling with is "finding the right people" and connecting with them. Most of the tools or applications are tuned to finding and managing people you already know. With talent distributed across the several locations and several people on the move, it is often hard to find the right people at the right time.  Networking opportunities like company meetings, coffee breaks, hallway conversations are also limited. However, a few enterprises are realizing how important networking opportunities are, for not just sharing and ideation, but even for executing day to day work. They are already experimenting with enterprise social networking sites to help people from different locations to "get to know" each other and establish a level of trust which is fundamental for collaboration.

As far as enterprise collaboration technologies are concerned, we are still in early days. Collaboration is an important aspect for doing business in the flat world and role of technology will become increasingly important especially in the global context. I believe that eventually, global enterprises will need to address collaboration from all the 3 perspectives - information, communication and people in an integrated fashion to realize the foundations of a "true collaboration platform".

Custom User Input Validation in WPF

Building any application that works with User Input cannot be complete usually without having some sort of validations for the input values. WPF is no exception. There is an interesting discussion around WPF validation on Paul Stovell's blog

Martin Bennedik has written a WPF Validation Block over Microsoft's Enterprise Library 3.0. WPF 3.5 also brings in additional validation support via the IDataEffortInfo Interface.

However, all said and done, these techniques typically work with data binding. One can always work with Data binding in WPF, but what if you don't have a need for that? What if there are say only one or two fields you want to validate? Also the WPF validation does provide feedback to the user when validation fails by using the ErrorTemplate, but to mark some field as mandatory, one typically still requires to be put the most used red asterix (*) near the mandatory fields.

Look at the screen shot of an application below. It has two text boxes for user's first name and last name. Both are mandatory. However instead of the asterix approach, I thought of why not the text box itself show a red border when it is empty and also a tooltip along with it to show what is required. Once the user enter's a valid value, the border can change back to the default border color. Finally, the text boxes also should be queriable for valid state so that when the form/dialog/window is submitted, I can loop through them and see if I can submit or not.

ValidationApp.jpg

First, to see how to have the TextBox check and provide feedback on it being valid. For this I used the new Extension Method functionality in C# 3.0. For a deep dive into this feature, check here. The following is the method I wrote where I just check to see if the TextBox control has some string entered or not and return true/false accordingly. Needless to say that the TextBox in the parameter below is from the System.Windows.Controls namespace, that is used in WPF.

    public static class CustomExtensions

    {

        public static bool IsValid(this TextBox obj)

        {

            if (obj.Text.Length > 0)

                return true;

 

            return false;

        }

    }

Next, to display the appropriate borders, I needed two brush resources - one, the default border brush that the TextBox uses and, two, a similar gradient brush that fills to red color to be used when the TextBox is invalid. Creating these with Expression Blend is very trivial. I saved these both as resources in the XAML file.

    <Window.Resources>

        <LinearGradientBrush x:Key="FaultyBorderBrush" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">

            <GradientStop Color="#FFABADB3" Offset="0.05"/>

            <GradientStop Color="#FFE2E3EA" Offset="0.07"/>

            <GradientStop Color="#FFFF0000" Offset="1"/>

        </LinearGradientBrush>

        <LinearGradientBrush x:Key="DefaultBorderBrush" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">

            <GradientStop Color="#FFABADB3" Offset="0.05"/>

            <GradientStop Color="#FFE2E3EA" Offset="0.07"/>

            <GradientStop Color="#FFE3E9EF" Offset="1"/>

        </LinearGradientBrush>

    </Window.Resources>

Finally, comes the logic to invoke the IsValid method at appropriate times so that the necessary feedback can be given to the user. The initial setting was done in the constructor of the Window so that i could initially show the TextBoxs with red border and the tooltip (as shown in the figure above). I also handled the TextChange event of the TextBoxes so that I could invoke the IsValid method to see if the TextBox is valid or not and change the border color appropriately. I also handled the Button's click event just to show that while submitting the form, I can invoke the same method and allow/prevent submission of the form accordingly. The following code shows the complete code behind for the Window.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Shapes;

 

namespace GenericWPFApp

{

    /// <summary>

    /// Interaction logic for MainPane.xaml

    /// </summary>

    public partial class MainPane : Window

    {

        const string _firstNameMessage = "FirstName cannot be left blank";

        //following is used with the different extension method which supports min and max lengths

        const string _lastNameMessage = "LastName should be between 0 and 100 characters";

 

        public MainPane()

        {

            InitializeComponent();

 

            //since the text boxes are initially empty, they are invalid. Initialize them accordingly

            SetTextBoxProperties(txtFirstName, false, _firstNameMessage);

            SetTextBoxProperties(txtLastName, false, _lastNameMessage);

        }

 

        private void txtFirstName_TextChanged(object sender, TextChangedEventArgs e)

        {

            TextBox box = sender as TextBox;

            if (box != null)

                SetTextBoxProperties(box, box.IsValid(), _firstNameMessage );

        }

 

        private void txtLastName_TextChanged(object sender, TextChangedEventArgs e)

        {

            TextBox box = sender as TextBox;

            if (box != null)

                SetTextBoxProperties(box, box.IsValid(0, 100), _lastNameMessage);

        }

 

        private void SetTextBoxProperties(TextBox ctrl, bool valid, string tip)

        {

            if (valid)

            {

                ctrl.BorderBrush = (Brush)TryFindResource("DefaultBorderBrush");

                ctrl.ToolTip = null;

            }

            else

            {

                ctrl.BorderBrush = (Brush)TryFindResource("FaultyBorderBrush");

                ctrl.ToolTip = tip;

            }

        }

 

        private void Button_Click(object sender, RoutedEventArgs e)

        {

            bool valid = false;

            valid = txtFirstName.IsValid();

            if (!valid)

            {

                message.Text = "Form is invalid";

                return;

            }

 

            valid = txtLastName.IsValid(0, 100);

            if (!valid)

            {

                message.Text = "Form is invalid";

                return;

            }

 

            message.Text = "Form is valid";

        }

    }

}

Disclaimer: The code isn't optimized and you may find better ways to implement the same logic. I just wanted to show that we can get some of the validation functionality without necessarily going the DataBinding way. Another caveat is that since the extension method is written for the TextBox, it will be available for all the TextBoxes used in the application. While this is good, the issue could be that you may want different logic for different TextBoxes. You can always write different implementations for the same. One such method, which works with minimum and maxium length is shown below. The challenge however will be to invoke the right method for the appropriate TextBoxes.

        public static bool IsValid(this TextBox obj, int minLen, int maxLen)

        {

            int length = obj.Text.Length;

            if ((minLen < length)  && (maxLen > length))

                return true;

 

            return false;

        }

Since extension methods can be written for any control/class, you can write similar logic for any WPF control to provide your own validation mechanisms. Comments welcome !  

 

 

 

 

January 25, 2008

Object-Relational Mapping(Part-I)

There has always been a debate on how to represent data in an application and how it should be persisted in a backend RDBMS. Why can't there be a uniform methodology for both? It has been an eternal debate but we have to live with the fact that data is represented using object-oriented methodology within an application where as it is stored in the RDBMS in accordance with the relational theory. The inherent differences between these two approaches can be attributed to the fact that the underlying methodologies, i.e. Object-Oriented and Relational theories are based on sofware-engineering and mathematical principles respectively. And the difference in the way data is represented in relational and object-oriented world is termed as object-relational impedance mismatch.

In a series of articles, I will discuss the impedance mismatch problem, some of the approaches to solve it and a few most widely used Object-Relational Mapping frameworks. In this article we will try to understand the fundamental characteristics of these two systems.

Object Systems
Characteristics of an Object model can be defined by four basic parameters: identity, state, behavior and encapsulation. The most important parameter in my point of view is identity because it is implicit to the object itself, in other words every object is uniquely identified by its identity irrespective of its state which means even if two objects have same state, they are still different and distinct. They may be similar or equivalent or a mirror image of each other but they are distinctly represented in memory. Behavior is basically a set of operations user can invoke to interact or manipulate the object. Encapsulation prevents user from reading and modifying the internal details of the object. Other important characteristics like inheritance, polymorphism, association, type etc can be derived from the above mentioned basic parameters.

Relational Systems
Relational model is completely based on predicate logic and set theory. The word Relation is used synonymously with Table in a database model contrary to the popular belief that relation is a link between different tables on the basis of some keys. Characteristics of a relational model is defined by relation, attribute, tuple, relation value and relation variable [Date 95]. A relation is a truth predicate having a set of attributes that gives some meaning to the predicate.

For example, we can define a relation "Customer" as {Customer ID, Name, Address, City, State, Zip} There exists a Customer with a Customer ID who has a Name and lives at an address specified by Address, City, State and Zip.
Attributes are statement of facts about the relation and ordering of attributes are not specified in a relation.
A tuple is a truth statement in context of a relation containing attribute values which map the required attributes in the relation. For example,

<Customer Customer ID="100001", Name="Farrukh Nizami", Address="Mehdipatnam", City="Hyderabad", State="AP", Zip="500028">

Two tuples are considered identical if their corresponding relation and attribute values are also identical. The ordering of attribute values is immaterial.
A relation value consists of a relation and a set of tuples that match the relation and a relation variable is a placeholder for a given relation and can change value with time. Therefore, inside an insurance company, a relation variable PolicyHolder can be written to hold the relation Customer and consist of the relation value

{ <Customer Customer ID="100001", Name="Farrukh Nizami", Address="Mehdipatnam", City="Hyderabad", State="AP", Zip="500028">
<Customer Customer ID="100002", Name="Kishore Gopalan", Address="BTM Layout", City="Bangalore", State="KN", Zip="560034>
<Customer Customer ID="100003", Name="Noor Mohammed", Address="Tollichowki", City="Hyderabad", State="AP", Zip="500028">
}


Commonly used words for these are Table (Relation Variable), Rows (Tuples), Columns (Attributes) and a collection of relation variables is called Database. These basic characteristics are combined against one another with the help of some operators like join, union, intersection etc. to form the basis for SQL. The use of operators allow us to create derived relation variables which are relations that are created from other relation values in the database.

Already you can see the difference in the way the two worlds view the system. I will elaborate these differences in the next article, so keep watching this space for more on Object-Relational Mapping concepts.

January 24, 2008

Better business decision making with Performance Point Server 2007

Recent days there are lot of competitions floating around the business world. One is struggling to make an effective business decision with the data they have in their enterprise. But just having data is not going to help improving your business, all you need is 'Information'. How one can make use of these information to achieve what they are looking for? Microsoft provides set of business intelligence tools to deliver a holistic approach to convert business information into actionable insight by providing an integrated platform for analyzing & monitoring enterprise performance metrics and planning your business. Microsoft Office Performance Point Server 2007(Commonly Known as PPS) is one such tool which allows one to identify the KPIs, maps those KPIs with various business metrics, build scorecards, reports and dashboards.

 

Performance Point Server is built on top of SQL Server 2005. It has two components
1.     Dashboard Designer
2.     Planning Business Modeler


Dashboard Designer:

A dashboard is a collection of graphs, reports, and Key Performance Indicators that can help you monitor your business. The following components are available in the dashboard designer

1.     Data Source - Analysis Services, ODBC, Excel Services, Excel 2007, SharePoint Lists, SQL Server table
2.     KPI - Blank KPIs, KPIs import from Analysis Services
3.     Scorecards - Blank Scorecard, Analysis Services, Fixed value, Excel Services, Excel 2007, SharePoint Lists, SQL Server table
4.     Reports - Analytic chart, Analytic Grid, Excel Services, Pivot chart, Pivot table, ProClarity Analytic server page, SQL Server report, Strategy map, Trend analysis chart, web page
5.     Indicators - Variety of indicators available to highlight the performance of different metrics. One can also have custom indicators 

Creating dashboard is the simplest task with PPS. Al you need to do is drag and drop the required Scorecards, reports and filters and position them as per your need. Finally the dashboard can be published to a SharePoint Portal (MOSS 2007 & SPS 2003) using simple navigational screens.  

Planning Business Modeler:

Microsoft Office PerformancePoint Server 2007 can help you drive consistency throughout your organization, span planning needs across your enterprise, extend your investments in Microsoft, and provide every employee with a stake in the corporate performance management process.

Office PerformancePoint Server 2007 makes it easy to:

  • Import data from multiple sources, including multiple general ledger systems.
  • Easily feed data automatically into a centralized, trusted data store.
  • Embed standardized business rules and processes.
  • Provide everyone with a single interface.
  • Ensure that people only see appropriate and relevant information.
  • Track changes automatically.
  • Manage planning and budgeting processes.


PerformancePoint Server 2007 delivers on these goals first by utilizing Microsoft Office Excel as the end-user interface for planning, budgeting, and forecasting. With PerformancePoint Server 2007, Excel is where people contribute, interact, and build reports. And Excel is where end users ultimately write their changes back to a central data model that contains data on actual side-by-side with planning data.

PerformancePoint Server 2007 data models are built to support the range of business models used in your organization, from sophisticated financial modeling to straightforward budget planning.

Built on top of the proven enterprise capabilities of Microsoft SQL Server 2005, PerformancePoint Server 2007 ensures that your performance management application can scale to meet a large user base.

Importance of Application.DoEvents

Recently a colleague of mine shared a code that he was working on where he was playing around with Asynch ADO.NET. He had a simple WinForm application. On the click of a button, he was making calls to the DB to get data. To try out the asynch features, he had introduced delays in the code.

The code looked something like below

        private void button1_Click(object sender, EventArgs e)

        {

            //start with empty text boxes and these get populated once the DB query returns

            textBox1.Text = string.Empty;

            textBox2.Text = string.Empty;

            textBox3.Text = string.Empty;

 

            SqlCommand com1 = null; SqlCommand com2 = null; SqlCommand com3 = null;

            SqlConnection con1 = null; SqlConnection con2 = null; SqlConnection con3 = null;

            SqlDataReader dr1 = null; SqlDataReader dr2 = null; SqlDataReader dr3 = null;

            string str1 = string.Empty;

 

            try

            {

                string connection = "Data Source=.;Asynchronous Processing=true;Initial Catalog = pubs;Integrated Security=True";

                con1 = new SqlConnection(connection);

                con1.Open();

                com1 = new SqlCommand("SELECT * FROM authors", con1);

 

                con2 = new SqlConnection(connection);

                con2.Open();

                com2 = new SqlCommand("waitfor delay '00:00:05';SELECT * FROM authors", con2);

 

                con3 = new SqlConnection(connection);

                con3.Open();

                com3 = new SqlCommand("waitfor delay '00:00:10';SELECT * FROM authors", con3);

 

                IAsyncResult ar1 = com1.BeginExecuteReader();

                IAsyncResult ar2 = com2.BeginExecuteReader();

                IAsyncResult ar3 = com3.BeginExecuteReader();

 

                WaitHandle[] handles = new WaitHandle[3];

                handles[0] = ar1.AsyncWaitHandle;

                handles[1] = ar2.AsyncWaitHandle;

                handles[2] = ar3.AsyncWaitHandle;

 

                for (int results = 0; results < handles.GetLength(0); results++)

                {

                    // wait for any handle, then process results as they come

 

                    int index = WaitHandle.WaitAny(handles, -1, false); // infinite secs

                    //depending on which call completed, update the appropriate text box

                    if (index == 0)

                    {

                        dr1 = com1.EndExecuteReader(ar1);

                        while (dr1.Read())

                        {

                            str1 = str1 + dr1[0] + " " + dr1[1] + " " + dr1[2] + "\n";

                        }

                        textBox1.Text = str1;

                    }

                    else if (index == 1)

                    {

                        dr2 = com2.EndExecuteReader(ar2);

                        while (dr2.Read())

                        {

                            str1 = str1 + dr2[0] + " " + dr2[1] + " " + dr2[2] + "\n";

                        }

                        textBox2.Text = str1;

                    }

                    else if (index == 2)

                    {

                        dr3 = com3.EndExecuteReader(ar3);

                        while (dr3.Read())

                        {

                            str1 = str1 + dr3[0] + " " + dr3[1] + " " + dr3[2] + "\n";

                        }

                        textBox3.Text = str1;

                    }

                }

            }

            catch (Exception ex)

            {

                MessageBox.Show(ex.Message);

            }

            finally

            {

                con1.Close();

                con2.Close();

                con3.Close();

            }

        }

Is this the best code that could be written is debatable. One could write separate handlers to handle the completion of each of the Asynch queries. But that's not the point. Let's for the sake of argument assume there is a specific need to have written the code in this manner. When you run this code, you would get some unexpected results

1. If after return of all 3 queries, you click the button again, you would expect the text boxes to clear up and then get filled up again when the queries  return after 5 and 10 secs. But that doesn't happen and the text boxes don't seem to clear up.

2. Each time you re-run the application, the way in which the results get populated in the text boxes is unpredictable. Sometimes, it will appear to work find while in most cases, the data for all three text boxes gets displayed at one shot (essentially after the last query has also returned)

So what's happening here? If you have experience only with the current .net programming only, it will be difficult to understand. Those of you who have programmed for Windows applications using the Win32 APIs directly like say with Visual C++ 1.5 or 2.0 or even with MFC would recall some of the key concepts there

1. Windows relies heavily on messaging infrastructure. Actions on the windows/controls etc generate messages that the code handles by picking messages from a queue and then passing them to a windows procedure. While processing of a message is happening, other messages will wait in the queue to be picked up.

2. The messages in the queue have different priorities. Those with higher priority even if come in while some messages are already in the queue, will get pushed foward and will be processed before the low priority messages.

3. The visual rendering of windows and controls there-in happens by processing the WM_PAINT message. During the processing of this message, the code uses the device context provided to it (which is usually the display device context) and draws the contents on it, which show up on the desktop display

4. Each time a control is invalidated (property change) like say text is entered into a text box, it needs to redraw itself so that it can show the currently set text. This is done by calling a Win32 API to invalidate itself, which causes a WM_PAINT message to be posted to the message queue. When the application gets a chance to process the message, the text box will update itself and show the new text.

The key to the issue with the above code is related to all these points with specific focus on the last point. In the sample code above, the text box has been updated by setting its Text property. It would have in turn generated a WM_PAINT message, but since the code above is in a loop, it essentially doesn't allows the processing of the message queue and hence the WM_PAINT message isn't processed on time.

It is in such scenarios that the Application.DoEvents API is useful. As you would see in the documentation, it mentions that a call to this allows Windows to immediately process all messages in the queue. So if we add this  call at appropriate places (as shown below in bold face), the behavior of the UI will be more in line with what we expect. 

        private void button1_Click(object sender, EventArgs e)

        {

            //start with empty text boxes and these get populated once the DB query returns

            textBox1.Text = string.Empty;

            textBox2.Text = string.Empty;

            textBox3.Text = string.Empty;

            Application.DoEvents();

 

            SqlCommand com1 = null; SqlCommand com2 = null; SqlCommand com3 = null;

            SqlConnection con1 = null; SqlConnection con2 = null; SqlConnection con3 = null;

            SqlDataReader dr1 = null; SqlDataReader dr2 = null; SqlDataReader dr3 = null;

            string str1 = string.Empty;

 

            try

            {

                string connection = "Data Source=.;Asynchronous Processing=true;Initial Catalog = pubs;Integrated Security=True";

                con1 = new SqlConnection(connection);

                con1.Open();

                com1 = new SqlCommand("SELECT * FROM authors", con1);

 

                con2 = new SqlConnection(connection);

                con2.Open();

                com2 = new SqlCommand("waitfor delay '00:00:05';SELECT * FROM authors", con2);

 

                con3 = new SqlConnection(connection);

                con3.Open();

                com3 = new SqlCommand("waitfor delay '00:00:10';SELECT * FROM authors", con3);

 

                IAsyncResult ar1 = com1.BeginExecuteReader();

                IAsyncResult ar2 = com2.BeginExecuteReader();

                IAsyncResult ar3 = com3.BeginExecuteReader();

 

                WaitHandle[] handles = new WaitHandle[3];

                handles[0] = ar1.AsyncWaitHandle;

                handles[1] = ar2.AsyncWaitHandle;

                handles[2] = ar3.AsyncWaitHandle;

 

                for (int results = 0; results < handles.GetLength(0); results++)

                {

                    // wait for any handle, then process results as they come

 

                    int index = WaitHandle.WaitAny(handles, -1, false); // infinite secs

                    //depending on which call completed, update the appropriate text box

                    if (index == 0)

                    {

                        dr1 = com1.EndExecuteReader(ar1);

                        while (dr1.Read())

                        {

                            str1 = str1 + dr1[0] + " " + dr1[1] + " " + dr1[2] + "\n";

                        }

                        textBox1.Text = str1;

                        Application.DoEvents();

                    }

                    else if (index == 1)

                    {

                        dr2 = com2.EndExecuteReader(ar2);

                        while (dr2.Read())

                        {

                            str1 = str1 + dr2[0] + " " + dr2[1] + " " + dr2[2] + "\n";

                        }

                        textBox2.Text = str1;

                        Application.DoEvents();

                    }

                    else if (index == 2)

                    {

                        dr3 = com3.EndExecuteReader(ar3);

                        while (dr3.Read())

                        {

                            str1 = str1 + dr3[0] + " " + dr3[1] + " " + dr3[2] + "\n";

                        }

                        textBox3.Text = str1;

                  Application.DoEvents();

                    }

                }

            }

            catch (Exception ex)

            {

                MessageBox.Show(ex.Message);

            }

            finally

            {

                con1.Close();

                con2.Close();

                con3.Close();

            }

        }

A quick look into the .net code using Lutz Roeder's Reflector shows that Application.DoEvents invokes the aptly named RunMessageLoop on current ThreadContext class. This in turn calls the RunMessageLoopInner. The actual message processing happens inside the LocalModelMessageLoop of the ThreadContext class.

To summarize, if you want the UI to be responsive (apart from getting into multi-threading) do ensure that you call Application.DoEvents at appropriate places to refresh the UI.  

 

January 23, 2008

Unit Test Trust Issue on Vista

Further to my unit testing experiments that I have been blogging about in the last few days, I was playing around with the DashCommerce starter kit. After installing and configuring the site, I started by creating some tests for the code in the App_code folder.

The test creation was successful and I was all set to run. But luck was against me and I got compilation errors regarding missing namespace. As I had mentioned in my earlier blog, the testing happens via private accessor and since its creation happened successfully, ideally I shouldn't  have had a need for adding explicit references and namespaces to my test project.

It turns, out that this happened due to the particular component for which I had generated the test to refer to an external assembly (SubSonic.dll), which in turn depended on the code in App_code folder. This caused something like circular reference and hence when the private accessor was created, it required the web site's code be added as reference. The workaround we followed was to publish the site and then refer to the generated App_Code.dll.

This wasn't the main issue that I wanted to describe here. When the compilation errors resolved, when I tried to run the test, I got an exception of type "Microsoft.VisualStudio.TestTools.TestManagement.ExecutionException". It pointed to a "Test Run deployment issue" and stated that the "file or location of the SubSonic.dll isn't trusted". This was strange since I had ensured that necessary permissions were granted on the folder so why this error.

I recalled from my earlier experiments on Vista about the file streams and how the files downloaded from the internet get tagged with additional file streams that marks it unsafe for execution. So I unblocked the file via File > Properties as shown in the image below.  

Unblock.jpg

After this I got similar error for another file and I realized that since this is a code that I downloaded from the net, all files have been tagged in similar way and I will need to unblock all. Doing that eventually worked and I was able to complete the testing successfully.

The one painful item was having had to unblock all files manually. Selecting all and right clicking to check Properties didn't help. Then later I found this which will help unblock multiple files.

January 22, 2008

Debugging ASP.NET Unit Tests with VS 2008

In my previous blogs (here and here), I have been discussing about unit testing on an ASP.NET web site that is hosted on IIS. While doing the work on that, I also had a need to debug my test case. The documentation on MSDN talks about putting break points and attaching to w3wp process and then debug the tests.

This however didn't work for me on VS 2008. What worked was adding the System.Diagnostics.Debugger.Break() call in my code and then running the tests like normal. When the code hit the Debugger.Break line, it asked me, which debugger to use and I selected the already open VS 2008 instance and it took me to the correct line of code and i was able to debug.

January 21, 2008

WSS 3.0 v/s MOSS 2007

MOSS 2007 is built using WSS 3.0 and leverages services like security, WF, search, storage, and administration that are provided by WSS 3.0. Also a major portion of one of the pillars, namely Collaboration is a part of WSS 3.0.

Some of the functionalities such as BI Delivery Platform, BDC and Portal are available only with MOSS 2007 and not with WSS 3.0. Therefore, the decision to use MOSS 2007 becomes very simple if an organization requires these features. WSS 3.0 on the other hand has a major set of features fine tuned for Collaboration and hence, it becomes difficult to choose between the two if Collaboration is the only requirement for the organization. A tenet that can be followed for the selection between the two is that for the organizations, which require Portal and Search capability across all the sites under the portal and even on Line of Business applications data, MOSS 2007 can be used to aggregate organize and present the information. However, for low (project) level sites i.e. sites lower in the organization, WSS 3.0 will suffice from the perspective of Collaboration.

Note:    WSS 3.0 Search can index content only within the site and its sub-sites. There are certain other features as well, which are not available with WSS 3.0 like personal sites, news, and site directory. For the entire list of differences between WSS 3.0 and MOSS 2007 please refer to the following Web site:

http://office.microsoft.com/en-us/sharepointserver/HA101978031033.aspx

Branding in SharePoint Technologies (PART 3)

Today we will look 3 options available for the modification of Site Master Pages. They include SP Designer, Site Template and File System options.

 

SP Designer: SP Designer is the newer version of front page extensions with additional capabilities to do some of the basic functionalities of SharePoint like editing the master page, page layouts, pages including designing simple workflows for the lists and libraries. This tool can be used to do branding (customizing the master pages) for a given Web Application/ Site Collection.

As discussed in the Table in Part 2  (Types of Master Page), all master pages which are site pages ( but not application pages) are specific to a site collection and there will be one default site collection in every Web Application. When one says the branding is being done in SP Designer for a Web Application, it is actually the branding done for the default site collection; since, the master pages are site-collection specific. 

To do the customization, the developer has to go to the master page gallery and modify the master page after checkout, and then do check-in back. Once saved, this will be saved to the content database as an un-ghosted page.

So the question is what if the Web Application has lot of site collections within it in addition to the default site collection. If one has to use this approach, then the developer will have to go to each and every site collection, and then go to the master page gallery and replace the master pages to keep them in synch with the rest. 

So to summarize this approach, it will be a good option as long as the number of site collections is very small preferably one for a Web Application. With the increase in the number of site collections, the maintenance effort increases and this option may cease to be a good fit.

Site Template: Before we get into the details of branding using the site template option, let us first understand what a site template is. A Template is an entity that is used to rapidly create items matching its structure. A Site Template does the same thing. It is used to create sites matching the structure of the site, which is a part of the template. It is typically stored as a Site Template Pack (STP)file. This can be created using any one of the following options:
·  Using the ‘save as site template’ using the look and feel section of the modify site settings page
·  Using SharePoint Designer
·  Using the savetmpl.aspx in the layouts folder


Note: Publishing sites have an issue in using the stp file. For more information on this and the related KB article, see http://blogs.technet.com/stefan_gossner/archive/2007/09/19/save-site-as-template-option-and-the-publishing-feature.aspx

In this approach, all the changes required for the master pages are saved (un-ghosted) into the database. On creation of the stp file, all these details will be stored in the file so that when a new site is created using this template then the branding is automatically ensured.
Some of the issues associated with this approach are:
·  If the end user/ administrator use any of the out of the box templates, the custom branding will not be applied and will result in inconsistencies.
·  Maintenance will be tedious owing to the high number of custom templates. A one-to-one mapping of templates creation is required for all the out of box templates.
·   Post-provision of the sites if the Templates are changed for branding reasons, the existing sites will continue to have the old branding as the work of the template gets over once the site is provisioned. Sites newly provisioned using these templates will have the changed branding.

File System: This is the simplest of all the options. When a site is being provisioned from site definitions, the site gets created using the master pages that reside on the file system which are mapped to the site definitions. These various master pages that reside on the file system are edited to match the custom requirements. This can be done in any editor and is outside the scope of any Web Application as it is done at the file system level. However caution as to be exercised for two reasons:
·   Since all the site definitions use these files during site provisioning, the same branding will be made available to all the sites/Web Applications that are provisioned in that machine/Farm

If Microsoft releases a patch or a service pack that updates these files, caution has to be exercised before applying the same since they might overwrite the files

We will look at the other 2 options of Site Definitions and Features in the next blog part of this series

ASP.NET Unit Testing on IIS

In my previous blog I had mentioned about the issue in generating private accessors for ASP.NET code that is hosted on IIS. Does this mean that we can't test the web site if hosted on IIS?

You can, but it will be a bit more complex and you may not be able to cover all scenarios. The idea is to work with the PrivateObject that is available from the test context. In the previous blog, I had talked about a web site with a Calculator class in the App_Code folder that i wanted to test. Let's continue with the same example.

In order to run the application, I had a page that had two text boxes from which I would enter the input values and it had four buttons, one each for invoking Add, Subtract, Multiply and Divide functionality and finally another text box that would capture the results.

Before being able to invoke the buttons, I had to ensure that the text boxes had appropriate values set. For this I used the MyTestInitialize routine so that the values will be set before each test is executed. The initialization I did was as follows

        //Use TestInitialize to run code before running each test

        [TestInitialize()]

        public void MyTestInitialize()

        {

            x = 20;

            y = 5;

 

            Page page = testContextInstance.RequestedPage;

            TextBox t1 = (TextBox)page.FindControl("TextBox1");

            t1.Text = x.ToString();

            TextBox t2 = (TextBox)page.FindControl("TextBox2");

            t2.Text = y.ToString();

        }

The test context allows access to the current page which can be set via the UrlToTest attribute set on each test method. Using this page object, I accessed the two text boxes and initialized them. Then came the actual test method and it looked something like below

        /// <summary>

        ///A test for Subtract

        ///</summary>

        [TestMethod()]

        [HostType("ASP.NET")]

        [UrlToTest("http://localhost/GenericWebApp")]

        public void SubtractTest()

        {

            Page page = testContextInstance.RequestedPage;

            Button b = (Button)page.FindControl("btnSubtract");

 

            PrivateObject po = new PrivateObject(page);

            po.Invoke("btnSubtract_Click", b, EventArgs.Empty);

 

            TextBox t = (TextBox)page.FindControl("TextBox3");

            int actual = Convert.ToInt32(t.Text);

            int result = 15;

            Assert.AreEqual<int>(result, actual);

        }

Few things to note in the above method

1. I used the PrivateObject to invoke the Subtract button's event handler in the page's code behind code.
2. The second parameter to the Invoke method could have been set as null also. If you are making use of the sender parameter in the button click event handler, then you need to send it, else you can very well just sent a null.
3. I used the generics overload of the Assert method to ensure that I can pass int to save on a bit of performance overhead of otherwise boxing and unboxing.

In a similar way, I can test all the other methods of my Calculator class. Needless to say this is a pretty simple scenario and hence invoking methods via the RequestPage object is easy. As the logic becomes complex, the effort to write the test method will increase as you may have to access multiple controls on the page and initialize them appropriately.

Comments are always welcome !

 

January 18, 2008

ASP.NET Unit Testing issue on IIS with VS 2008

I was recently trying to dirty my hands on using the Unit test framework that comes with Visual Studio. I decided to give it a try on my newly installed VS 2008. I created a pretty trivial ASP.NET site hosted on IIS with a Calculator class that I put in App_Code folder and generated the tests.

One of the key differences in working with Unit test framework for ASP.NET as compared to other projects like Winform or Class library is that the code in ASP.NET gets compiled dynamicall into various assemblies and hence we can't bind to a specific assembly upfront. Check more details on this here.

Hence to successfully test code in ASP.NET App_Code folder, the creation of private accessor is very important. However when the test case got generated, I saw the following code in the test method

        /// <summary>

        ///A test for Subtract

        ///</summary>

        [TestMethod()]

        [HostType("ASP.NET")]

        [UrlToTest("http://localhost/GenericWebApp")]

        public void SubtractTest()

        {

            // Creation of the private accessor for 'Microsoft.VisualStudio.TestTools.TypesAndSymbols.Assembly' failed

            Assert.Inconclusive("Creation of the private accessor for \'Microsoft.VisualStudio.TestTools.TypesAndSy" +

                    "mbols.Assembly\' failed");

        }

And I didnt' see any private accessor created for me. I opened the Calculator class code (from the App_Code) folder and from the context menu invoked the "Create Private Accessor" command, but got a message stating that "Private accessor creation failed for http://localhost/GenericWebApp". This was strange and needless to say that I wasn't able to run the tests.

While creating the tests, I had been prompted that Network Service didn't had sufficient rights on a particular folder and I had selected "Yes" to provide those rights. But still things didn't work. I then created an exact same ASP.NET Web site but this time on file folder. Again I created the tests and this time it worked like a breeze. See the code that got generated for one of the methods in the Calculator class.

        /// <summary>

        ///A test for Subtract

        ///</summary>

        [TestMethod()]

        [HostType("ASP.NET")]

        [AspNetDevelopmentServerHost("%PathToWebRoot%\\FileSystemWebApp", "/FileSystemWebApp")]

        [UrlToTest("http://localhost/FileSystemWebApp")]

        public void SubtractTest()

        {

            Calculator_Accessor target = new Calculator_Accessor(); // TODO: Initialize to an appropriate value

            int x = 0; // TODO: Initialize to an appropriate value

            int y = 0; // TODO: Initialize to an appropriate value

            int expected = 0; // TODO: Initialize to an appropriate value

            int actual;

            actual = target.Subtract(x, y);

            Assert.AreEqual(expected, actual);

            Assert.Inconclusive("Verify the correctness of this test method.");

        }

Clearly the private accessor (Calculator_Accessor) got created this time and after commenting the last Assert.Inconclusive line, I was able to successfully run the tests (the test would be more meaningful after making suitable changes to the values as well like x could be set to 10, y to 5 and hence expected will be 5).

This meant there was some issue in the way the tests were generated on IIS. I also did ensure that I was running VS as administrator (since I was working on Vista). I hence raised a query on the forum and got a confirmation that this is a bug in VS 2008 and we should get a fix in SP1. Till then, we will have to either test by having the site on a file folder or using the PrivateObject to test. I will discuss that in my next blog, so keep watching !

 

January 14, 2008

Branding in SharePoint Technologies (PART 2)

In this Part 2 blog I will focus more on Master Pages and will leave the css and themes out of scope of this blog 4 part blog series on branding. To start of let us understand what is a master page all about? Though most of us are aware of this, just to ensure everybody understands the same...

Master page is the portion of the page which will retain the common portion of the site/application like the header, footer, navigation, etc. Master Pages in SharePoint can reside on both the File System as well the SharePoint database. A page on file system is referred to as ghosted page and the one in database is referred to as un-ghosted page. Master Page along with the content page together forms the published page which will be finally rendered in the browser.

 

There are 2 types of Master Pages

·         Site Master Pages
·         Application Master Pages

The classification of the Master pages into the two types is based on portion of the website the master page applies to as discussed in the table below.


 

 

 

Site Master Pages
Application Master Pages
Purpose
Applied to the user facing pages
Applied to pages other than the user facing pages
E.g.
Master page applied to Default.aspx like Blue band, default based on the site template chosen
Master page applied to Site Actions, View all Site content, Workflow, Search page
Location
Master Page Gallery (Library)
On the file System in Layouts Folder (virtual directory name is called _layouts)
Is it generic
Specific for a site collection in a Web Application
Common across all the Web Applications/ Site Collections
Can they be modified
They can be modified within SharePoint Designer and once modified they will be stored in the Application specific SharePoint database
They can be changed but will reside in the file system only

Now that we understand what is a master page and it types, next we need to understand what are the typical challenges that exists in branding wrt Master Pages.

The requirements of the Web Applications vary from organization to organization or rather even from department to department. The Web application being developed might be a onetime activity or may be a couple of Web Applications might get added in the future. There might be scenarios where there will be only one Web Application but the number of site collections will keep increasing, and can run into hundreds of them. Architects need to ensure that the required branding is applied on the site collections/Web Applications, and at the same time be changed in a controlled fashion if required. If changes need to be done for the Site Master Pages, how does one control them? What is the governance model to be put in place for all of these pages are some of the key challenges an architect will have to address. The subsequent parts of this blog will explain the options that are possible along with the pros and cons of the approaches so that depending on the situation the architect can take an appropriate decision ... Happy reading

 

Control Flow Patterns in Workflows

There is a lot of potential in Workflow Foundation that is seldom uncovered. Due to the existence of different business processes for different industries, an architect who would prefer to model these processes using workflows will look for more useful control flow patterns (explicitly available or an opportunity to develop one) than the ones that are shipped out-of-box with WF i.e. the Sequential and State Machine Workflow Patterns.

It is very important to understand that WF is a part of the .NET Framework 3.0. It is a “Framework” and not a “Solution” in itself. The onus lies on the developers and designers to put this framework to best use and develop customized solutions according their business needs.

WF provides the flexibility to create customized control flow patterns. So what is a Control Flow Pattern? Let us briefly understand the existing out-of-box patterns:

Sequential Workflow – In this workflow pattern a set of activities are organized in a sequence from top to bottom. When the workflow is executed, the control flows from one activity to the next in sequence.

State Machine Workflow – In this workflow pattern an entity moves from one state to another. Each state is an Activity. The control flows based on the external stimulus received from the client and moves the entity to another state accordingly.

There can be business processes which may require different flow patterns. For example,

- An activity can execute only if a set of activities preceding it have executed successfully.

- The control should move from one activity to another based on the user input i.e. the user explicitly decides which activity to execute next.

- An activity may proceed to one of the next few activities possible based on the input it receives. A small difference from the above case will be that the user cannot explicitly mention the activity that will be executed next.

- If in a sequence, a set of activities may be re-executed before the workflow is completed. The number of activities that will be re-executed and the number of times such a thing should happen may be unknown.

Can we accomplish anything like the above??? Fortunately, the answer is YES! So what does it take to develop such customized control flow patterns?

The first concept to be painted on the wall: “Every Workflow is an Activity; a Composite Activity”. The next step to take will be to understand the root of the execution of activities in a workflow (and the workflow itself) which is the Activity Execution Context (AEC). AEC enables us to interact with the underlying scheduler component of the workflow i.e. it is an abstraction for the scheduler and the work queue components of the WF Runtime. This becomes the ground for developing customized control flow patterns, from the simplest to extremely exotic and complex ones.

A very good resource that WF developers/designers in this regard will be the book:

Essential Windows Workflow Foundation - Dharma Shukla, Bob Schmidt

The book provides an in-depth insight into the details of the AEC and the possible control flow patterns that one can develop. The programmers will have something to cheer about since these flow patterns are explained with code.

I should honestly admit that the effort required to develop such complex patterns will be a little more than usual. But, such an effort is justified if it can solve the most critical business problems. However, it is very important to pay due diligence before a decision is taken to develop such complex patterns right from scratch. If a pattern can be tailored out from the existing patterns (Sequential or State Machine), it will be a good idea to pursue the same.

January 8, 2008

Branding in SharePoint Technologies

With SharePoint Technologies (Microsoft Office SharePoint Server (MOSS) 2007 and Windows SharePoint Services (WSS) 3.0 collectively referred to as) entering the mainstream development arena on the Microsoft platform, it is imperative for decision-makers to decide upon a strategy for adopting this technology.

SharePoint Technologies is based on the following theme: Connecting People, Processes, Tools and Information. This new version of SharePoint Technologies offers significant enhancements to the existing features and also introduces many new features like Collaboration, automation of simple Business Processes involving documents, Enterprise Search, and Business Intelligence. Thus it acts as a sort of default choice for the organizations for a variety of requirements from Intranet/Internet Portal, Content Management System, etc. With all of this Branding all the applications gains greater importance.

I will have a 3 part series on this explaining the various options available for branding and which one suits better in what scenario. Before that we will get into the details of what branding is all about? Branding as a concept has been there for years since the beginning days of Web Application development. Earlier it was done using basic rudimentary things like Header, Footer include files (*.inc), Frames, standard Navigation, etc. However, with ASP.Net 2.0, the way this is implemented has been changed to the usage of Master Pages, css class, themes, etc.
Branding, is the identity of an organization (or department) applied to an application (portal is also a type of application). This is generally done for various reasons - to ensure consistent look-and-feel, for better user experience, or to enforce standards of the organization/department, etc.  It includes things like the top banner, footer, various navigations like the left navigation, global navigation, basic search, page layout, etc.
Branding, which is also regarded as an artifact-based development since it does not involve assembly based coding (involving VS.Net), is conceptualized in the early stage of the development cycle as it can potentially impact the look-and-feel and UI experience of the entire site.

Though MOSS 2007 provides flexible options for branding it requires careful selection of the option choice based on the needs. A clear understanding of the options and their relevance needs to be understood. These options and guidance are not easily available in the public documentation. This blog provides overview of branding options available in MOSS 2007 and selection criteria 

With this we will get into the details on Master Pages in the next part.


 

January 7, 2008

Categorizing and Developing Custom Activities and Workflows

Developers working with WF often come across situations where they have to author custom activities and workflows. The questions that immediately strike:


-          Should there be a single assembly for all the activities?
-          Should there be an assembly for each activity?
-          How should the activities be categorized?


A decision on the developing the assemblies can be taken based on what’s common among the activities or workflows.

For example, if we have 3 activities/workflows which belong to the same domain or a module, author them under a single assembly. We may decide to make a single activity as an assembly if the functionality of such an activity is unique. An example for this can be “EmailActivity”.


Same applies to workflows as well. In case of modifications to the category of the workflows/activities, the “Type” can be moved from one assembly to another without recompiling the clients that consume the initial assembly. This feature in .NET is called Type Forwarding.
 

However, for both custom activities and workflows, business requirements play a vital role to categorize them.


Based on the business requirements,
1.     Identify at a high level all the possible workflows.
2.     Find what is common among them and categorize them.
3.     Identify the custom activities that should be created.
4.     Repeat Step 2.
 

This may not be a problem for a small set of workflows/activities. When there are many workflows, which cut across an Enterprise, this can prove to be quite a task.
 

The ultimate goal should be to completely avoid redundancy and establish an optimal authoring pattern of activities and workflows.

January 2, 2008

Querying user details from Active Directory

During a recent project, we had need for querying and working with Active Directory. Searching on net, gave lots of help, but most were around creating and managing users. Our need was simple - to get some user specific details from AD.

The trickest part of working with AD is the AD structure and what properties have been defined and hence available for querying. Without really knowing this, one can continue to grop in dark for long hours without much success.

Fortunately, there is a very handy free tool from Softerra called LDAPBrowser. Using this tool, you can get very useful insight into the AD structure that you want to work against and try your search queries to find the right syntax.

Once you download the tool, you need to do minimal configuration to work with it. Run the application and select "New Profile" from the File menu. Give a name of your liking for the profile and click Next. The figure below shows the screen where you need to configure the host information. The host name will be the name of your ad like for example test.com as shown in the figure below. If you aren't sure of what Base DN you want to work with, click the "Fetch DNs (only LDAP v.3)" button. As the name indicates this works only if your AD supports LDAP protocol version 3.

LDAPProfile.jpg

This will fetch a list and you can select one from that. Typically you may want to select something that looks like DC=test,DC=com as this the root path and all other objects in the AD will be inside of this. When working with AD, a few abbreviations are used and these are

CN - common name
DN - distinguished name
OU - organizational unit
DC - domain object class

Further to providing the host name and Base DN, you will then need to provide a user id and password using which you will query the AD. This will be a valid domain account. When accessing AD programmatically, you can always use the secure authentication mechanism to query AD without having to provide a user id and password.

With the profile created, you can navigate the AD structure and drill down to individual items. Checking their properties will show the PATH to that object which you can use to fine tune your queries. Usually queries will work with the root path as well, but if you can narrow your search by using a more detailed path, you will save time in obtaining query results. Needless to say that AD querying is highly optimized and in my minimal experimentation, i didn't find much difference between getting results using the root path or a more selective path.

Following code snippet shows how to query for a particular user

ADCode.jpg 

Similar code will work for both web or windows application. Once you have access to the User's directory entry, you can query a host of properties using the specific string name key. To find out these keys, the LDAPBrowser will come handy.

Hope this helps. Comments welcome. 

Subscribe to this blog's feed

Follow us on

Blogger Profiles

Infosys on Twitter