Thursday 30 September 2010

Update the Nintex workflow to multiple lists and libraries in a SharePoint site

Special thanks to Vadim Tabakman.
 It is a special requirement. Nintex workflows are very  helpful in some scenarios to achieve things in simple and easy way. I got a requirement that I have to implement a workflow which needs to be used in many document libraries and list. As we know the SharePoint limitation, we can not apply the workflow for the content type. So, the only way we can do is adding workflow to each and every library needed. This is difficult, but I believe this is the only way we have to proceed. The big problem here is, when we have the requirement to change the workflow according to new changes then the problem starts. We have to change it in each and every library or list where workflow is deployed. This is very difficult in real time. So, we need some other way which we have to do automation. I am googling for the solution and luckily I found a wonderful solution here.

I will explain you very detail what "Vadim Tabakman" solution is.
He has created a document library and custom list which are used to add or update the custom nintex workflow in all libraries and lists.

 Lists Used:
  1. Master List of Workflows [Document library]
  2. Workflow to List Map [Generic List] [Columns: Workflow Name [Title field renamed to Workflow Name], Destination Workflow Name, List Name]
Master List of Workflows: This is the main library which is holding the Nintex workflow files which we have to add to all document libraries [.NWF file]. And according to his solution, he has provided the nwf file which runs and updates the uploaded nwf file to the libraries. So, for removing confusion I will explain you clearly what we need to do.
  1. We have to upload the actual custom NWF file which you have created to the document library. Which is the file we have to add or update all document libraries in the site.
  2. To update all document libraries we need another workflow. So, according to his solution there is a NWF file named "Update Workflows" he written and which does that job for us.
Workflow to List Map: This is the generic custom SharePoint list which holds the records of what workflow to be added to which library or list and what name we have to give for the workflow. SharePoint also has another limitation that the workflow names should not be same across the site. So, we have to use different names for each workflow.
Workflow Name field should be same as, the name you are uploading to the Master List of Workflows.

I believe you understood what we are doing and why the need of two lists.

So, now download the UpdateWorkflows.nwf file from his site and add this to the Master List of Workflows library. And upload the original custom nintex workflow you have developed to the library. Once you are done please add all entries in the Workflow to List Map list. Now, go back to library and select the workflow which one you want to add to all libraries and manually fire the update workflow.

That's it. Once you run it, the update workflow will add the custom nintex workflow to all list and libraries you have mentioned in the Workflow to List Map list.

Note: You have to change the user and password in the update workflows nwf file.

Hope this will be a big help as it helped me alot. So, use it and make your life easy.

Tuesday 28 September 2010

Replace single quote with two quotes in XSLT

I know most of the people will not need it as very rare this requirement comes and because of it we have to waste hours and hours. In net there are plenty of articles, posts says about how to do replace in XSLT. But, most of them has some requirements like the replace() built in method needs XSLT 2.0 version, or some thing something.... But, if you need simple replace method regardless of the version you have, then you are at right place. There are lot of custom functions written on this already. But, no one of them works for the requirement I have. That is replacing the single quote with two quotes in XSLT. 

The main requirement here is, I am more of SharePoint guy, I use infopath forms for collecting data from users and save them to backend[database]. In the process of it, I have comments fields in the form. There are chances that user may enter single quotes['] in their comments. But, while saving them to the database, the single quote ['] giving problems. Everyone knows that this is the basic problem. So, I have to replace single quote with two single quotes so that the problem will go away.

Complete XSLT file for replacing a string with some other string:
<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <html>
  <body>Replace Single Quote with two single quotes
<br />
Original string: Praveen's World
<br />
Replaced String: 
<xsl:variable name="sq">'</xsl:variable>
<xsl:variable name="tsq">''</xsl:variable>
<xsl:variable name="orgString">Praveen's World</xsl:variable>
<xsl:variable name="replacedString">
    <xsl:call-template name="replace_single_quote">
      <xsl:with-param name="string" select="$orgString" />
            <xsl:with-param name="find" select="$sq" />
            <xsl:with-param name="replace" select="$tsq" />
    </xsl:call-template>
  </xsl:variable>
<xsl:value-of select="$replacedString"/>
  </body>
  </html>
</xsl:template>
<xsl:template name="replace_single_quote">
    <xsl:param name="string" select="''"/>
    <xsl:param name="find" select="''"/>
    <xsl:param name="replace" select="''"/>
    <xsl:choose>
        <xsl:when test="contains($string,$find)">
            <xsl:value-of select="concat(substring-before($string,$find),$replace)"/>
            <xsl:call-template name="replace_single_quote">
                <xsl:with-param name="string" select="substring-after($string,$find)"/>
                <xsl:with-param name="find" select="$find"/>
                <xsl:with-param name="replace" select="$replace"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$string"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>

For testing purpose, you can use the online XSLT editor from W3schools.
On the right side editor, remove all the code and copy, paste the above XSLT. And now, click on the button "Edit and Click Me >>". You will see the XSLT working.
But, you may confuse by seeing above code that I have given complete document to you. Everyone is not really good at XSLT as it is being used by very less people. So, I will try to describe it clearly for better understanding.

Declaring variables and calling the replace method:
<xsl:variable name="sq">'</xsl:variable>
<xsl:variable name="tsq">''</xsl:variable>
<xsl:variable name="orgString">Praveen's World</xsl:variable>
<xsl:variable name="replacedString">
    <xsl:call-template name="replace_single_quote">
      <xsl:with-param name="string" select="$orgString" />
            <xsl:with-param name="find" select="$sq" />
            <xsl:with-param name="replace" select="$tsq" />
    </xsl:call-template>
  </xsl:variable>
<xsl:value-of select="$replacedString"/>

Here is the simple explanation:
We have declared 4 variables as described below.
  1. sq - single quote - I have assigned single quote to it.
  2. tsq - two single quotes - I have assigned two single quotes to it.
  3. orgString - original string to replace.
  4. replacedString - The final output string.
  5. Finally, after the replace logic called and executed, I am printing the replaced string at last line mentioned above.
  6. If you observe, the variable "replacedString" I have assigned the return value of the template/function named "replace_single_quote". I am calling it with call-template tag and it will call the template and returns some value. 
The template "replace_single_quote" is what the actual function which takes three parameters.
  1. Original string
  2. string to find.
  3. string to replace.
The template returns the replaced string if any found.
Note: You can pass whatever string you want in place of the sq [find] and tsq[replace] variables.

I hope you understood it well and it solved your problem.

Saturday 25 September 2010

This session has exceeded the amount of allowable resources - Infopath form error

If you are working with infopath forms and your form is really big [I mean, having lot of controls and with so many actions] then you should get this error at some point. Most of the developers did not get it as it will come very rarely.

Error details:
"This session has exceeded the amount of allowable resources."

Event Viewer details:

Event Type:      Error
Event Source: Office SharePoint Server
Event Category: Forms Services Runtime
Event ID: 5737
Description:
Number of form actions 208, has exceeded 200, the maximum allowable value 
per request. This value is configurable and can be changed by the administrator.
So, when we see the log description, it is saying that the form actions is beyond the SharePoint default form actions allowed. SharePoint by default allows 200 form actions per postback of a form. But, here the form I have used is using more than 200. My case it is 208. So, it will not allow to save or submit the form and throw the above error.

Solution:
To resolve this error, increase the form actions in configuring infopath services section as shown below.
  1. Go to Central Administration of the SharePoint server.
  2. Click on Application Management.
  3. In the section "Infopath Forms Services", select Configure Infopath Forms Services.
  4. In the Number of Actions per Postback enter the value of what even viewer shown[In this example 208] or enter some max value around 250 or 300 depends on your requirement.
  5. There are chances that the error may retain same even after we increase the number of actions per postback. The second thing we have to increase is the value of "Maximum size of form session state" to 8192. By default it is 4092, by increasing it to 8192 the error should go away.  

 Please let me know, if you have any problems or questions. Hope this will solve the problem.

GridView and export to excel

This is very simple to implement in ASP.NET. But, there are possibilities to get problems in exporting to excel from grid view. When you bind data to gridview and write some logic to export to excel then it will not be enough. We have to check or write some additional logic which will help us to solve the problems. Below is the explanation for all problems we may get in the complete process along with detailed solution.

You may encounter below errors when you try to implement the export to excel for gridview.
1. Control of type "GridView" must be placed inside of the form tag with runat="server"
This is very well known error to ASP.NET developers and by seeing it, we think that the control is not inside the form with runat server. But this is not correct. This error will come even if we put the GridView inside form with runat server. The reason is, in the export to excel logic we are calling RenderControl() method of GridView. So, to render it without any issues we have to override the "VerifyRenderingInServerForm" in our code.  Below is the syntax of the event. Add this to the c# code in code behind file. Remember this event is a Page event means this method you should place in ASPX page. If you are using user control to implement this export to excel logic then below are the ways to go.
1. If your user control is using by less than 3-4 pages then go to each and every page and add this event to the page.
2. If your user control is using by more than 5 pages then the best solution is to create a base page [Which inherits from System.Web.UI.Page class] and all your ASPX pages should inherit from this base page.

public override void VerifyRenderingInServerForm(Control control)
{
//Confirms that an HtmlForm control is rendered for the specified ASP.NET
//server control at run time.
}
Now, after we added the event to page, the error will go away for sure.

2. Even when you add the above code/event to the page, this is not enough if you have the paging, sorting enabled on gridview. If you enable paging or sorting then you encounter the below error.

"RegisterForEventValidation can only be called during Render();"

This error is coming because we are doing paging and sorting. If no paging or sorting enabled this error will not come. To resolve this error, please follow below steps.
1. In your export to excel button click event, first disable the paging, sorting on gridview and do data bind.
2. Call export to excel logic.
3. Re-enable paging, sorting on gridview and databind.
Below is the logic we have to use in export to excel button click event.
gvReport.AllowPaging = false;
gvReport.AllowSorting = false;
gvReport.DataBind();
ExportToExcel();//Method to use export to excel.
gvReport.AllowPaging = true;
gvReport.AllowSorting = false;
gvReport.DataBind();
Now, you are clear with all errors and the logic will export all data in gridview to excel.
FYI, I am placing a sample of ExportToExcel() functionality here.
private void ExportToExcel()
{
Response.Clear();
Response.AddHeader("content-disposition", string.Format("attachment;filename=excel_report.xls"));
Response.Charset = "";

// Response.Cache.SetCacheability(HttpCacheability.NoCache);

Response.ContentType = "application/vnd.xls";
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
gvReport.RenderControl(htmlWrite);
Response.Write(stringWrite.ToString());
Response.End();
}
Note: gvReport is the gridview control name in my example. And there are lot of posts in internet guide you incorrect to resolve the above error. For example, they will say set EnableEventValidation="false" in the <%@ Page directive Or disable validation in web.config level to resolve the error. Please do not set it.

Hope this helps to solve all problems you are facing.

Saturday 11 September 2010

The assembly from form template conflicts with a same named assembly in form template

This is the exception which was coming when I tried to deploy the infopath forms to SharePoint environment.

This is the background of the problem. I have infopath project created in visual studio and infopath has 3 views. According to my requirement I have to publish each view as a single infopath form. So totally 3 infopath forms as output. The infopath form has form code in c#. So, we have to deploy dll as well. But, as one version of infopath is already in production, I have to move the new version to production. But, according to some dependency problems, I have to keep the dll of the infopath project as same version as production. So, what I did was opening the AssemblyInfo.cs and changed the assembly version to hard coded like 1.0.3098.12321. There it started the problem. When I tried to deploy the infopath forms below is the exception it was coming.

The assembly infopathproject.dll from form template someform.xsn conflicts with a same named assembly in form template another.xsn

So, after research around 1-2 hours, I found that the three xsn forms are pointing the same dll [I mean along with version]. So, infopath forms are having same dll reference and leads the conflict.

The resolution for this problem is, reverting back the assembly information back to 1.0.* solved the problem. Now infopath forms are pointing to same dll but with different versions. So, problem resolved.

So, if you have the same requirement like same dll using for different infopath forms then, please don't forget to make auto generate versioning for the assembly like 1.0.*.

Hope this helps to solve the problem.

Thursday 9 September 2010

Setting views dynamically in infopath form through code

When working with infopath forms, there are lot of things we have to know. This is not very easy to implement, publish and using it. So, we have to know complete details about infopath in all aspects. I had a requirement in infopath, while loading depends on some scenario I have to switch the view. While form is loading I have logic written to know what view I have to set. But, once I got the view name from logic, how to set that to infopath form? Below is the simple code which works for that requirement.
e.SetDefaultView("PBB"); 
the "e" used in this code is the LoadingEventArgs object in the form event. It has the method named SetDefaultView(), Which takes the view name as the parameter. So, once you set it, it will apply the view to the infopath and display the view on the form.

Hope this helps to understand better the infopath and code.