Tuesday, April 13, 2010

Working with declarative workflows Part 1

Hi All,

We all know that we can create a great workflow using visual designer provided in visual studio as well as SharePoint designer. However there is one more way, we can create workflow. Yes the technique is called declarative workflow. Declarative workflow is all about writing XML code and then feeding this XML code to workflow runtime to execute the workflow.

Let me tell you why this can be a fun element while working in workflow. Let us say that you have defined many conditions in your workflow and you have created that workflow with Visual studio. Hence you compile that workflow and use the DLL to deploy and then use in application or in SharePoint. So you have to come back to designer, change your logic and again compile, get new DLL and deploy it to use it. This is bit overhead while working with designer. However designer workflows have their own advantages as well and there cannot be two ways on this. However we are talking about declarative workflow, so here is the advantage of using declarative workflow.

You can change your condition logic right away by just modifying the existing XML and then feeding the same to workflow runtime.

To work with XML based workflow, you only need at simples notepad and as advanced XML editor or visual studio itself.

One important part to note is whenever we work with declarative workflow; we have to use two namespaces in XML.

1) http://schemas.microsoft.com/winfx/2006/xaml
2) http://schemas.microsoft.com/winfx/2006/xaml/workflow

So let us do some particle on this.

Go ahead and create one console sequential workflow and immediately add new item and call it DeclarativeWorkflow.xml.

Open the file’s property and change its Copy to Output directory property to Copy If Newer.



And start adding following XML in that file. Moment you start typing the XMLNS attribute, it gives you an options of all namespace URIs.



Make sure that you write in proper caps. Even if you miss a single alphabet in capital letter or lower letter, you will not get an idea what is wrong with the workflow and you will receive an error while starting the workflow.

<SequentialWorkflowActivity x:Name = "Workflow1"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<SequenceActivity x:Name="SequenceActivity1">
<DelayActivity TimeoutDuration="00:00:15" x:Name="DelayActivity1"></DelayActivity>
</SequenceActivity>
</SequentialWorkflowActivity>


As you can notice, how we assign ID to the controls in ASP.Net, in the same way we have to assign the Name attribute to our activities in the XML.

Here we have defined very basic workflow with one single delay activity.

Now go ahead and add one code activity in designer surface and double click to generate handler for that and simply write down the following code in it.



And now run the application to see it in action.



Read Working with declarative workflows Part 2 for further reading.

Thursday, April 8, 2010

Creating custom activity in Workflow Part – 7

Hi All,

Let us continue exploring custom sequence activity and use it in real world. Take same sample code that we generated in Creating custom activity in Workflow Part – 6.

Now I am not going to write down the code here. I have created one dummy table in my database to demonstrate this example.

I am reading the parameter that is passed from client and then writing a code that will fetch the salary of an employee in GetEmployeeSalary code activity.

And then I am sending mail based on the condition. So what I am going to show you is final version of it. After writing a code in our custom sequence activity, I drag it again on console workflow application and then run it.

Set EmployeeId to the EmpoyeeID.



And then run the application.



And if I set to other employee then,



Hope that you have got a fair idea about how sequence custom activity works now.

Tuesday, April 6, 2010

Finally the result is out

Hi All,

Finally the result is out.

We asked people if their company is migrating from SharePoint 2007 to SharePoint 2010. Well here is the answer. seems there is 50-50 for this time.

Monday, April 5, 2010

Creating custom activity in Workflow Part – 6

Hi All,

Till now what we saw is creating a basic activity and play with it. Now in this post, we will move ahead and see how to achieve the same functionality of creating custom activity. However in this post we will create custom sequence activity instead of simple basic activity.

If you haven’t gone through the previous post, then I recommend reading Creating custom activity in Workflow Part – 1 first and then continue reading further.


Remember this is not a custom composite activity, this is custom sequence activity. Creating custom composite activity will take a lot of effort. We will put on those efforts in subsequent post.

First let us understand and create custom sequence activity. Add new workflow activity library project to your solution. Name it whatever you want but make sure you inherit the activity from sequence activity rather than activity.

Let me give you highlights of what are we going to do in this activity. We will have one code activity which will get the Employee ID as a parameter. Internally we will get the employee from the table and then we will have if else condition, checking for each employee’s performance rate. Based on performance rate, we will shoot mail to manager with different subject and body line in mail.

So go ahead and add one Code activity in the designer surface, then drag one if else activity on surface. And then drag code activity and place on left branch, drag one more code activity and put on right branch.

Give Name “GetEmployeeSalary” to the First Code Activity which is outside of If else condition. Give Name “SendMailForLowPerformance” to left code activity and give Name “SendMailForGoodPerformance” for right side code activity.

Double click on each code activity to generate its respective handlers. Still you will notice one red circle for not setting branching condition. So go ahead and add declarative rule based condition for left branch if else activity.

Before adding that, write down following code. You will automatically have handlers for code activities as we generated few steps ago.

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;

namespace Sequential_Custom_Activity
{
public partial class Activity1 : SequenceActivity
{
public Activity1()
{
InitializeComponent();
}

public static DependencyProperty EmployeeIDProperty = DependencyProperty.Register

("EmployeeID", typeof(string), typeof(Activity1));


public string EmployeeID
{
get
{
return Convert.ToString(base.GetValue(EmployeeIDProperty));
}
set
{
base.SetValue(EmployeeIDProperty, value);
}
}

double _PerformanceRate;

public double PerformanceRate
{
get
{
return _PerformanceRate;
}
set
{
_PerformanceRate = value;
}
}



private void GetEmployeeSalary_ExecuteCode(object sender, EventArgs e)
{

}

private void SendMailForLowPerformance_ExecuteCode(object sender, EventArgs e)
{

}

private void SendMailForGoodPerformance_ExecuteCode(object sender, EventArgs e)
{

}
}


Go ahead and add declarative condition as shown in figure below.



As of now we haven’t done anything fancy.

Build the project. You should not find any error. Now create new console application workflow. Add our custom activity DLL to the toolbox. Drag and drop the custom sequence activity to the console workflow application. So should find something like shown below. Note that you are not allowed to make any changes in any of the branching conditions or nor the code condition as they are indicated by lock symbol.



Now in next post, we will be adding code in these blocks and will make it work.

Thursday, April 1, 2010

Sharepoint Custom so called KPI

Hay Guys,

In general KPI most of the time we are having simple requirement.

Like if Risk is high or status is incomplete then it should show in RED.
If Low then Green and Medium then orange.

Same functionality we had done for listview webpart which show Red/green/yellow icon based on status.

Here is the example
In our list we had a column called criticality with dropdown values

High
Low
Medium

Check the screenshot below



And check another one after what we had done.



So you can see it looks like KPI
This is similar like
http://www.sharepointkings.com/2008/12/highlight-sharepoint-list-rows.html
but everyone is asking regarding this KPI so we had done this.

Now, What we had done
It’s nothing just a trick of javascript/jquery
Here is the code

$(document).ready(function() {
var strURL = window.location.href;
if ((strURL.toUpperCase().indexOf("Lists/Risk%20Management".toUpperCase()) != -1) ||
(strURL.toUpperCase().indexOf("Lists/Risk Management".toUpperCase()) != -1)) {
//alert('pp');
$(".ms-vb2:contains('High')").each(function() {
var tempDIV = document.createElement("DIV");
tempDIV.style.cursor = "pointer";
tempDIV.innerHTML = "<img src='_LAYOUTS/SPKings/Images/Red.gif' />"; //$(this).text();
//alert($(this).html());
$(this).text("");
$(this).append(tempDIV);

});
$(".ms-vb2:contains('Low')").each(function() {
var tempDIV = document.createElement("DIV");
tempDIV.style.cursor = "pointer";
tempDIV.innerHTML = "<img src='_LAYOUTS/SPKings/Images/Green.gif' />"; //$(this).text();
//alert($(this).html());
$(this).text("");
$(this).append(tempDIV);

});
$(".ms-vb2:contains('Medium')").each(function() {
var tempDIV = document.createElement("DIV");
tempDIV.style.cursor = "pointer";
tempDIV.innerHTML = "<img src='_LAYOUTS/SPKings/Images/Amber.gif' />"; //$(this).text();
//alert($(this).html());
$(this).text("");
$(this).append(tempDIV);

});
$(".ms-vb2:contains('No Criticality')").each(function() {
var tempDIV = document.createElement("DIV");
tempDIV.style.cursor = "pointer";
tempDIV.innerHTML = "<img src='_LAYOUTS/SPKings/Images/NoData.gif' />"; //$(this).text();
//alert($(this).html());
$(this).text("");
$(this).append(tempDIV);

});
}

});


What we had done is we are checking URL
If it is out target list, then we apply javascript and as you can see we are finding High and replacing that with Red.gif.

Same way for other criticality also

You can use image from image library also. We had used images from layouts.

Don’t forget to include jquery.JS to make it work.

Guys, this is not recommended way for authentic KPI but for time being or for demo purpose where we are not having time and have to show a lot of thing this will act as icings on the cake. :)

Access denied error when I use web services in InfoPath

Hi All,
When I use user profile service or any other web service in InfoPath and run it on my local server it works fine and when I deploy same form on production server where there is SharePoint farm it fails to run and give access denied error. I have used host header for SharePoint site and I refer that host header to open that site.
The solution for this problem is to disable the loopback check on each SharePoint server in farm.
To set the DisableLoopbackCheck registry key yourself, follow these steps:
Set the DisableStrictNameChecking registry entry to
  1. For more information about how to do this, click the following article number to view the article in the Microsoft Knowledge Base:
    (http://support.microsoft.com/kb/281308/ ) Connecting to SMB share on a Windows 2000-based computer or a Windows Server 2003-based computer may not work with an alias name
  2. Click Start, click Run, type regedit, and then click OK.
  3. In Registry Editor, locate and then click the following registry key:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
  4. Right-click Lsa, point to New, and then click DWORD Value.
  5. Type DisableLoopbackCheck, and then press ENTER.
  6. Right-click DisableLoopbackCheck, and then click Modify.
  7. In the Value data box, type 1, and then click OK.
  8. Quit Registry Editor, and then restart your computer.
    And run IISRESET on each server
    Reference: http://support.microsoft.com/kb/896861

Wednesday, March 31, 2010

Using Workflow as web service Part – 2

Hi All,

If you haven’t read previous post, then I recommend you read Using Workflow as web service Part - 1 and then continue reading here.

Now in this post we will deep dive into real practical example where in we will create on workflow and then expose the workflow as web service and then we will consume that web service from one console application.

If you have gone through consuming web service in workflow post, you must have remembered that we created web service of calculating square root of given number and consumed it from our workflow. Well, we will do the same stuff here. However our workflow will act as web service here.

First let us create one project. Add project with type sequential workflow library. Name it as a SquareRootService.

Now right click the project and add new class. Name it ISquareRoot.cs.

Change the definition from class to interface.

Add following method definition.

double GetSquareRoot(double dblNumber);

Now drag WebserviceInput activity to the designer surface.

Bind the interfaceType property to the one that we create just now.



Set IsActivating property to true and MethodName to GetSquareRoot.



Select dblNumber proprty now, and click on … to bring the bind dialogue box and create new propoerty to bind it with dblNumber paramter of the input.



Now double click on InputRecieved method and generate it’s method.



Write down following code.

private void webServiceInputActivity1_InputReceived(object sender, EventArgs e)
{
double inputvalue = this.webServiceInputActivity1_dblNumber1;

webServiceOutputActivity1__ReturnValue_1 = (double)Math.Sqrt(inputvalue);


}


Go ahead and add one webserviceoutput activity. Bind it with InputActivity by giving inputactivityName to the webServiceInputActivity1. Set return value to the property



Now go ahead and right click on project and publish as a web service. This is really a cool feature that workflow provides. We need not to worry about anything. Just clicking on the button does the wonder.



Rename the newly generated file with SquareRootService.asmx

Now build that newly created web service.

Now add one console application for the test. And then add web reference; find web service in the solution.



Write down a very simple line to call a web service, which actually call our workflow.

static void Main(string[] args)
{

SquareRootService.Workflow1_WebService objService = new ConsoleWorkflowTest.SquareRootService.Workflow1_WebService();

double returnvalue = objService.GetSquareRoot(49);

Console.WriteLine("Square Root of 49 is : " + returnvalue.ToString());

Console.ReadLine();

}


And see the output.



That is it. Your job is done. Feel free to ask any query.

Tuesday, March 30, 2010

How to know the site template out of the box

Hi All,

Many times we come across to a situation where we cannot write a code and site is completely branded. Hence we cannot make a decision on which template the site is created with.

Here is a way to know which template site is created in. you must be a site collection administrator to do this.

1) Save site as template into site template gallery.
2) Save that template from gallery to your local machine.
3) Change the file extension to the .cab.
4) Extract manifest.xml file.
5) Check out the TemplateID in that.
6) This ID tells you which template the site was created in.


If site template is any of the below, then it is that site. If it’s above 1000, then it should be custom.

ID 0 = Global, Configuration 0 = Global Template
ID 1 = STS or SharePoint Team Site, Config 0 = Team Site
ID 1, Config 1 = Blank Site
ID 1, Config 2 = Document Workspace
ID 2 = MPS, or Meeting Place Sites, Config 0 = Basic Meeting Workspace
ID 2, Config 1 = Blank Meeting Workspace
ID 2, Config 2 = Decision Meeting Workspace
ID 2, Config 3 = Social Meeting Workspace
ID 2, Config 4 = Multipage Meeting Workspace
ID 3 = Centraladmin, config 0 - Central Admin Site
ID 4 = WIKI, Config 0 = Wiki site
ID5, Config 0 = Blog

Thanks to John Creevy for this solution.

Hope this will help you.

Monday, March 29, 2010

Using Workflow as web service Part - 1

Hi All,

In last post, we saw how we can use web service in our workflow. In other word, we saw how we can consume web service in our workflow. So now in this post, we will perform the reverse operation. We will see how our workflow acts as a web service and how other applications can use the workflow as a web service.

It is not simple as creating a web service and just taking a reference from other application. It is much more than this. However Visual studio and workflow give us the great command to convert the entire workflow in web service. How can we use this feature? Well, we will see it later in this post.

First let us understand what all things are required for exposing workflow as web service. We will be using WebServiceInput and WebServiceOutput activities.

We must have at least one Input and at least one output activity in the workflow. We cannot have input activity without associating output activity and we cannot have output activity without associating it with some input activity.

Let us go ahead and deep dive into webserviceinput activity.

For Webserviceinput activity you need to set some properties and handle one event. Properties are as follows.

1) Interface Type: Get or Set the Interface data type for which we are going to expose our methods as web methods.

2) Is Activating: At least one of the activities must have this property set to true. This indicates that by calling this method, use can start the workflow. You can have more than one activity which has this property set true. However, if this is the case, then all these activities can start the workflow.

3) MethodName: Name of the method that can be exported as web method.

Out of these three properties, Is Activating is default set to false. All above properties must have values assigned otherwise be ready for validation errors.

Let us go ahead and now understand webserviceoutput activity.

Webserviceoutput activity must be bind with any of the webserviceinput activity for which you want to return the output. You must assign InputActivity name to the webserviceoutputactivity, otherwise validation error will be thrown.

If method returns void, then no need to bind the return parameter to the webserviceoutput, else you need to bind the appropriate return parameter to the webserviceoutputactivity.

More than one webserviceoutputactivity can be associated with one webserviceinputactivity. Reason being, let us say, we have one if else condition and in that we are processing some activities. Or we have parallel activities going on and it can take any of the branch path, then for each path ends, we need to return some values. Hence for each path end can be bind to the single input activity.

There is one more activity that we have to use in the workflow if we want to expose the workflow as web service.

Webservicefalut activity is same as webserviceoutputactivity and must be bind with the webserviceinputactivity. Only difference is that webservicefaultactivity is binded to the field or parameter of type Exception and to be set in Fault parameter of this property. This will ensure that if anything goes wrong, we need to send the exception or proper message to the calling client method.

Read Using Workflow as web service Part – 2 for further reading.

Tuesday, March 23, 2010

Consuming web service in workflow

Hi All,

Workflow gives us very decent and useful activity for fetching web service from your local computer, network or even from internet.

Let’s us directly dive in to the way how we can achieve calling web service from the workflow. We do not have to write any custom activity or write some code to call web service method. All is given by the built in activity called Invoke web service.

To demonstrate the example here, I have created one small ASP.Net web service project which calculates the square root for the given number. Now I know. This is not something very useful in real world. As I said earlier as well, that I believe in giving simple example and then leave user to play with complex example. Most welcome for any query.

The moment you drop the Invoke Web Service activity on designer surface, it opens up the window asking you for the web service URL, it is very similar to what you see when you add web reference in normal ASP.NeT project.

I have web service in my own machine so I chose find in machine option, if you have to use any of the service residing anywhere in the world, give that as a URL and fetch the web service.

Workflow does all the work for you for creating proxy class ready for you to use and call the methods.

(You can take console workflow as test project here)

Interesting part of this activity is, it knows about the parameter binding. Now there can be one or more parameters for the specific method. Now I have default Helloworld method and my own method called GetSquareRoot which takes parameter of type double.

Moment you are done with setting the web reference with your web service, you can see the red circle error showing you that the MethodName is not set. Hence we are going to go ahead and set the MethodName to my own method.





Now as you can see we have been asked for setting the number value which is the parameter for the GetQuareRoot method. Also notice return value at the top in property window. There has to be a return value after calculating the square root. So go ahead and click on each one of them and bind it to new properties.

Just make sure that you create properties, not fields.





Now go ahead and add two more code activities. One before invokewebservice activity and one after that as shown in figure below.



Double click on Code Activity1 and write following code. Here we are setting the value of our input parameter that we have given as input to the method.

private void codeActivity1_ExecuteCode_1(object sender, EventArgs e)
{
this.InputNumber = 49;
}


And then double click on Code Activity2 and write following code. Here we are fetching the value from the web service and storing the result of the return value from web service method and then writing a simple statement so that we can come to know the output.

private void codeActivity2_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Square root of " + this.InputNumber + " is : " + this.ReturnNumber);
Console.Read();

}


See the result. In this way we have now consumed web service from the workflow with the help of very helpful InvokeWebservice activity.




Share your SharePoint Experiences with us...
As good as the SharePointKings is, we want to make it even better. One of our most valuable sources of input for our Blog Posts comes from ever enthusiastic Visitors/Readers. We welcome every Visitor/Reader to contribute their experiences with SharePoint. It may be in the form of a code stub, snippet, any tips and trick or any crazy thing you have tried with SharePoint.
Send your Articles to sharepointkings@gmail.com with your Profile Summary. We will Post them. The idea is to act as a bridge between you Readers!!!

If anyone would like to have their advertisement posted on this blog, please send us the requirement details to sharepointkings@gmail.com