Thursday, 29 November 2012

How to open InfoPath form in browser from workflow status page even though InfoPath client is installed


Hello,

Today again with new SharePoint challenge and solution/observation found.

In our project we have browser enabled InfoPath form and workflow. Whenever we tried to open InfoPath form from workflow status page (WrkStat.aspx) page, if InfoPath client is installed on client machine then it always opened InfoPath form in InfoPath client even though InfoPath form is browser enabled.

Our customer has requirement that InfoPath form must be opened in browser irrespective of InfoPath client is installed or not.

So after doing research we found an alternative, if we add a query string parameter to InfoPath form XML URL, ?OpenIn=Browser then InfoPath form always opens in browser even though InfoPath client is installed.

Now to implement this solution we have two options,

1.   Either modify OOB workflow status page
2.   Copy and have our own separate workflow status page and then change it

Definitely first option is not the recommended solution. So we copied OOB workflow status page and then modified it.

In workflow status page, there is variable called StrUrlItem which contains the URL of InfoPath form xml. The original code is like

<TD nowrap width=180>
<%
      if (!string.IsNullOrEmpty(StrUrlItem))
            {
%>
            <a href=<%SPHttpUtility.AddQuote(SPHttpUtility.HtmlUrlAttributeEncode(StrUrlItem),Response.Output);%> onclick=<%SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(StrOnClickItem),Response.Output);%>>
<%
      }
      SPHttpUtility.HtmlEncode(StrNameItem,Response.Output);
      if (!string.IsNullOrEmpty(StrUrlItem))
      {
%>
            </a>
<%
      }
%>
</TD>

So we changed the above code and made it as follows

<TD nowrap width=180>
<%
      if (!string.IsNullOrEmpty(StrUrlItem))
            {
                StrUrlItem = StrUrlItem + "?OpenIn=Browser";
%>
            <a href=<%SPHttpUtility.AddQuote(SPHttpUtility.HtmlUrlAttributeEncode(StrUrlItem),Response.Output);%> onclick=<%SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(StrOnClickItem),Response.Output);%>>
<%
      }
      SPHttpUtility.HtmlEncode(StrNameItem,Response.Output);
      if (!string.IsNullOrEmpty(StrUrlItem))
      {
%>
            </a>
<%
      }
%>
</TD>

Now once workflow status page get customized we need to change the URL of workflow status page in workflow.xml file as

<StatusPageUrl>_layouts/{Our folder}/WrkStat.aspx</StatusPageUrl>

and we are done.

Thanks!

As usual your comments / feedback / suggestions are most welcome!

Enjoy SharePoint J

Tuesday, 20 November 2012

Adding our custom web part on wiki page programmatically


 Hello Again, Today again new point J

We have a requirement like whenever our one custom site is get created, on welcome page one of our custom web part should be added by default. Since our custom site is based on OOB team site template, welcome page of the site is wiki page.
So here I will discuss steps to add our custom web part on wiki page.

Here problem with Wiki page is we do not have web part zone so that we can’t directly add into given zone. Here on wiki page we have content field available and we need to put some mark up as the value of this field.

So written one web level feature and in feature activated added code

Steps:
1.   Getting the web instance

SPWeb web = properties.Feature.Parent as SPWeb;

2.   Get the welcome page

string welcomePageUrl = web.RootFolder.WelcomePage;
SPFile welcomePage = web.GetFile(welcomePageUrl);

3.   Check out the welcome page

welcomePage.CheckOut(); // Here make sure that Check out type of welcome page //is none or checked out to current user then only check out the welcome page

4.   Get the webpart manager as

SPLimitedWebPartManager wpmgr = welcomePage.GetLimitedWebPartManager(PersonalizationScope.Shared) // Use Using //for this in actual code

5.   Create the instance of our custom webpart and add using webpartmanager
//Generate the id for the web part, this id is also used in markup which we  
//will assign content field

Guid wpStorageKey = Guid.NewGuid();
       string webpartpId = String.Format("g_{0}"wpStorageKey.ToString().Replace('-', '_'));

//My custom wp
      MyCustomWp myCustomWP = new MyCustomWp();
      myCustomWP.ID = webpartpId;
      myCustomWP.ChromeType = PartChromeType.None;
      myCustomWP.Title = “My Custom WP”;

      wpmgr.AddWebPart(myCustomWP, "wpz", 0);

6.   Set the MarkUp required to Content field for the wiki page

       string markup = string.Format(CultureInfo.InvariantCulture, "<div class=\"ms-rtestate-read ms-rte-wpbox\" contentEditable=\"false\"><div class=\"ms-rtestate-read {0}\" id=\"div_{0}\"></div><div style='display:none' id=\"vid_{0}\"></div></div>", new object[] { wpStorageKey .ToString("D") });

       //Get the list item to read the field
SPListItem item = welcomePage.Item;
        
//Wiki field
item[SPBuiltInFieldId.WikiField] = markup;
       item.Update();
       welcomePage.Update();

7.   Finally check in the page

       welcomePage.CheckIn(string.Empty, SPCheckinType.MajorCheckIn);

Thanks! Enjoy SharePointJ

As usual your comments/suggestions/feedback is most welcome!

Friday, 16 November 2012

Regarding contact field control and user profile picture

Hello Again,

Today new issue, new topic J.

Problem: In our project on page layout we have added the ContactFieldControl(Microsoft.SharePoint.Portal.WebControls) which shows the picture of user which specified as a contact, also shows users status and designation.
One of the user has deleted his profile picture then contact field control started showing the “red cross” for image of the user rather than OOB “Person (_layouts/images/person.gif)” image.  

Solution: Actually on page ContactFieldControl get the users image URL from hidden User Information List (/_catalogs/users/) and in this list, Picture field points out to URL of medium thumbnail image from User Photos library from MySite.

When user uploads his picture in his profile either through MySite or Central Admin, SharePoint creates three thumbnail images from the user picture and add those in User Photos library. Say for example user has uploaded his picture user.gif then SharePoint will create three different images (large thumbnail, medium thumbnail and small thumbnail) for user.gif in User Photos library on My Site.

When user first time log in to the site a record for the user is added into hidden User Information List and picture field of list is updated with medium thumbnail image url from User Photos from My Site.

But when user deletes his picture SharePoint removes the all three images from User Photos list but User Information List still points the same medium thumbnail image url and that’s why in ContactFieldControl it shows red cross rather than Person.gif.

So workaround to resolve this issue is set the Picture field value to null in User Information list using PowerShell script as follow:

#Get your root web
$web=Get-SPWeb "your web URL"

#Get the User Information list
$list= $web.SiteUserInfoList

#Get the respective user
$user=$web.Ensureuser("Your user display name")

#get the user from User Information List
$listitem=$list.GetItemById($user.Id)

#set the value of picture field to empty
$listitem["Picture"]=""

#update the current list item
$listitem.update()

//update current list
$list.update()

I hope this will look interesting to you J Enjoy SharePoint J

As usual your Thoughts / Comments / Feedback are most welcome.

Monday, 12 November 2012

Deleting the web part from page using PowerShell scripts


Hello Again,

One of the requirements we have in our project is to delete the web part from page. So one of the obvious options is delete the web part using PowerShell script.

So here I will again step by step discuss how we achieved it using PowerShell script.


Here we are considering name of the deleting web part is “MyCustomWP”, available in ZoneId 1 and order 


1.     Create the web instance and get publishing web as follows
$webURL = “http://MyWeb.com”
$web = Get-SPWeb $webURL
[Microsoft.SharePoint.Publishing.PublishingWeb]$pubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web);
2.     Get the default value for AllowUnsafeUpdates property to change it at the end and now set it to true
$allowunsafeupdates = $web.AllowUnsafeUpdates
$web.AllowUnsafeUpdates = $true

3.     Get the Pages library and get the page from where we want to delete the web part
$list = $web.Lists[$pagesLibrary]
if($list){
$page = $web.GetFile(”My Page URL from where I want to delete the web part”)

}

4.     If page is not checked out to other user, then checkout the page, get the webpartmanager for the page and get all webparts available on the page
$page.CheckOut()
$webpartmanager = $web.GetLimitedWebPartManager($page.URL, [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
$WebPartCollection = $webpartmanager.WebParts

5.     Go through all the web part collection, compare with our webpart name, ZoneId and Order.
$webPartsCount = $WebPartCollection.Count

for($i=0;$i -lt $WebPartCollection.Count; $i++){
#Here we are checking the RepresentedWebPartType.Name – for details on this please refer http://prashamsabadra.blogspot.in/2012/03/representedwebparttype-or-errorwebpart.html

if($webpartmanager.Webparts[$i].RepresentedWebPartType.Name -eq $webPartName -or $webpartmanager.Webparts[$i].GetType().Name -eq        $MyCustomWP){
                                                                                    if($webpartmanager.Webparts[$i].ZoneId -eq 1){
                                                                                                if($webpartmanager.Webparts[$i].PartOrder -eq 1){
            $SPWebPart = $web.GetWebPartCollection($page.url,[Microsoft.SharePoint.WebPartPages.Storage]::Shared)
            $webPartTobeDeleted = $webpartmanager.Webparts[$i]                                                                    $SPWebPart.Delete($webPartTobeDeleted.StorageKey)
            Write-Output "Deleted" $webPartTobeDeleted.GetType().Name
            $web.Update()
            break
            }#if part order
            }#if webpart zone
            }#if webpart type
            }#foor loop - $i

6.     Finally check in the page and close all the instances
    #Check to ensure the page is checked out by you, and if so, check it in
    if ($page.CheckedOutBy.UserLogin -eq $web.CurrentUser.UserLogin)
    {
        $page.CheckIn("Page checked in automatically by PowerShell script")
        Write-Output $page.Title"("$page.Name") has been checked in"
    }
#Approve the page
$page.Approve("Page approved automatically by PowerShell script")


$web.AllowUnsafeUpdates = $allowunsafeupdates
$pubWeb.Close()
$web.Dispose()

Thanks!

Your suggestions / Feedback / Comments always welcome !

Enjoy SharePoint J

Sunday, 11 November 2012

Adding Web part on pages using PowerShell script

One of the requirements in our project is to replace the existing webpart from our production site which was causing lots of problem with performance.  This web part was available on multiple content pages. So one of the option available to us is write PowerShell script to add new web part on multiple content pages.
So here I will discuss adding webpart on one SharePoint page using PowerShell script.
  1. To add the web part we will require web part definition file should be available on file system so that we can add it in webpart gallery, import and add it using WebPartManager class
  2. Now, consider we need to add the webpart on MyWPPage.aspx page from the page library of web MyWeb
  3. We need to get publishing web instance from web instance and allow unsafe updates to true as follows:
  4. Get the pages library and find the your list item as follows
  5. Get the file from listitem, check that if this page is checked out to other user or same user, in case same user then publish and then check out the page
  6. Now from local file system, get the file stream and import it using webpart manager as follows
  7. Finally, Check in the page and clean up the instances



$webURL = “http://MyWeb.com”
$web = Get-SPWeb $webURL
#Get the publishing web instance and set allow unsafe update property to true
[Microsoft.SharePoint.Publishing.PublishingWeb]$pubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web);
$allowunsafeupdates = $web.AllowUnsafeUpdates
$web.AllowUnsafeUpdates = $true
$list = $web.Lists[$pagesLibrary]
foreach($listItem in $list.Items){
if($listitem.URL.Contains("MyWPPage.aspx ") {
            $myListItem = $listItem
            break; 
}

$page = $web.GetFile($listitem.URL)
if ($page.CheckOutStatus -ne "None")           {
#Check to ensure the page is checked out by same user, and if so, check it in
    if ($page.CheckedOutBy.UserLogin -eq $web.CurrentUser.UserLogin)
    {
        $page.CheckIn("Page checked in automatically by PowerShell script")
        Write-Output $page.Title"("$page.Name") has been checked in"
    }
}
if ($page.CheckOutStatus -eq "None"){
$page.CheckOut()
#Get the webpart manager
$webpartmanager = $web.GetLimitedWebPartManager($page.URL, [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
}
$saveFolder = "C:\webpart\"
$webpartfile = “MyWebPart.webpart”
$fileDWP = $saveFolder + $webpartfile
write-output "DWP File"  $fileDWP

#Getting the webpart gallery
[Microsoft.SharePoint.SPList]$wpList = $web.Site.GetCatalog([Microsoft.SharePoint.SPListTemplateType]::WebPartCatalog)
$fileStream = ([System.IO.FileInfo](Get-Item $fileDWP)).OpenRead()
[Microsoft.SharePoint.SPFile]$wpFile = $wpFolder.Files.Add($webpartfile, $fileStream, $true)
Write-host $wpFile
 [System.Xml.XmlReader]$xmlReader = [System.Xml.XmlReader]::Create($wpFile.OpenBinaryStream())
#Import the webpart
$myCustomWP = $webpartmanager.ImportWebPart($xmlReader,[ref]$errorMsg)
Write-Output "My custom WebPart" $myCustomWP.title
#If this webpart is not available on page then add it
if(! $webpartmanager.WebParts.Contains($myCustomWP)){
$webpartmanager.AddWebPart($myCustomWP, $wpZoneId, $wpOrder)
}

$page.CheckIn("Page checked in automatically by PowerShell script")
$page.Publish("Page published,new webpart added")
$web.AllowUnsafeUpdates = $allowunsafeupdates
$xmlReader.Close()
$pubWeb.Close()
$web.Dispose()
Thanks!
Your feedback / comments are most welcome
Enjoy SharePoint :)