Sunday, December 7, 2008

Preserving/Updating CreatedBy and ModifiedBy

You might have a scenario where by you want to migrate the list data from one site another site list manually instead of .STP file
Or you use Run With Elevated Privileges ( with delegate()) to insert a record into library where by normal user don't have contribute rights but only READ access Or you need to update one or more fields in a library and you want to preserve Created By and Modified By data.

Here is the Pseudocode:
If Current User is Super user OR Preserver user details is false
Normal Insert
Else
Run the Code With Elevated Privileges to Insert
Then Restore User Details
End If

Code for Restore User Details (C#):

private void RestoreUserDetails(string sitename, string libname, int itemId, int sharePointUserID, string UserLoginName)
{
using (SPSite siteColl = new SPSite(sitename))
{
using (SPWeb web = siteColl.OpenWeb())
{
SPList Legal = web.Lists[libname];
SPListItem LegalItem = Legal.GetItemById(itemId);

//SPFieldUserValue oUser = new SPFieldUserValue(web, web.CurrentUser.ID, web.CurrentUser.LoginName);
SPFieldUserValue oUser = new SPFieldUserValue(web, sharePointUserID, UserLoginName);

LegalItem["Author"] = oUser.User.ID;
LegalItem["Editor"] = oUser.User.ID;
LegalItem.Update();

}
}
}

Tuesday, December 2, 2008

Deactivating the Multiple Documents Option for Upload

We had a business requirement to block the "Upload Multiple Documents" Option for the document library. So add "Content Editor Web Part" check the "Hide" under layouts section.
Then add below code under Source Editor and you are done!.

<script type="text/javascript">
function GetElementByText(tagName, title)
{
var a = document.getElementsByTagName(tagName);

for (var i=0; i < a.length; i++)
{
if (a[i].text)
{
if (a[i].text === title)
{
return a[i];
}
}
}
return null;
}

if (window.onload)
{
var oLoad = window.onload;
window.onload = function bodyLoad()
{
oLoad();
var oMenu = GetElementByText("ie:menuitem","Upload Multiple Documents");
if (oMenu )
{
oMenu .disabled = true;
}
}
}

</script>

Note: If you want to deactivate the Upload Document change the var oMenu ;
var oMenu = GetElementByText("ie:menuitem","Upload Documents");

Monday, November 24, 2008

Web Service (Data) Connection & Elevated Permissions

Let's Talk about Dynamically changing the web service's URL before executing and running with Elevated Permissions.

As we know very well by now, grabbing the settings from webconfig allows us seamlessly push code from Dev-QA-Staging-Production, Here I am showing sample code to change the Uri for the webservice as well as running the code with Elevated Privileges. Which allows to executes the specified method with Full Control rights even if the user does not have Full Control.

private void GetUserProfileByNameByChangingURI()
{
WebServiceConnection ws = (WebServiceConnection)this.DataConnections["GetUserProfileByName"];
Uri url = new Uri(ConfigurationManager.AppSettings["UserProfileWS"].ToString());
ws.ServiceUrl = url;
string accountName = "us9\\raja";
XPathNavigator nav = CreateNavigator();
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//Create the Data Source.
XPathNavigator navDataSource = DataSources["GetUserProfileByName"].CreateNavigator();
//Set or Pass The Query Parameter.
navDataSource.SelectSingleNode("/dfs:myFields/dfs:queryFields/s0:GetUserProfileByName/s0:AccountName", NamespaceManager).SetValue(accountName);
//All Set For Execution.
ws.Execute();
nav = navDataSource;
});

//Grab the Results from the Result Set.
XPathNavigator navFirstName = nav.SelectSingleNode("/dfs:myFields/dfs:dataFields/s0:GetUserProfileByNameResponse/s0:GetUserProfileByNameResult/s0:PropertyData[s0:Name='FirstName']/s0:Values/s0:ValueData[1]/s0:Value", NamespaceManager);
string FirstName = navFirstName.Value;
}
catch { }
}

Note:
a. Add the using System.Configuration Name Space to your solution so that you can read the webconfig.
b. Add fallowing key under in web.config file:
<add key="UserProfileWS" value="http://<site>/<_vti_bin/userprofileservice.asmx>/" />

Dynamically Updating Data Connections:

Wondering how to change Data connections dynamically in InfoPath Forms so that you can deploy the solution seamlessly from DEV-QA-Staging-Production.

Here is Sample Code for MainSubmit()

private void MainSubmit(SubmitEventArgs e)
{
bool bSuccessful = false;
try
{
FileSubmitConnection fc = (FileSubmitConnection)this.DataConnections["MainSubmit"];
Uri url = new Uri(ConfigurationManager.AppSettings["Submit"].ToString());
fc.FolderUrl = url.AbsoluteUri;
fc.Execute();
bSuccessful = true;
}
catch
{
System.Diagnostics.EventLog.WriteEntry("MainSubmit", "MainSubmit: Failed to Submit();");
}
// If the submit operation is successful, set
// e.CancelableArgs.Cancel = false;
e.CancelableArgs.Cancel = !bSuccessful;
}

Note:
a. Add the using System.Configuration Name Space to your solution so that you can read the webconfig.
b. Add fallowing key under in web.config file:
<add key="Submit" value="http://<url>/<LibraryName>/" />

Sunday, July 20, 2008

Custom Activity For Windows Workflow

As you know Activity is a unit of work which could be simple or complex. Workflows use all these activities to finish its job, so we can say that Workflow is a collection of activities. In the design mode you see Base Activity Library in tool box those are all core collection of activities that come built in.

Why you need a Custom Activity!? As simple as you want to build once and reuse again and again the object or the way you process the data/flow. Simple Example Writing the status notifications back to DB over and over as the Workflow process moves/jumps the state. Or moving the files around workflow.


How to Build a Custom Activity!? Derive from Base Activity, Override Execute Method and Use Properties if needed. You can also use Dependency Properties.

What is a Dependency Properties!? Unlike normal properties, it won’t take up memory in the instance. It’s more of Centralized storage, Declarative binding at design time and also integrated with Workflow.

Code Snippet for DependencyProperty (<Shortcut>propdp</Shortcut>):
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets
xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
<Title>Define a DependencyProperty</Title>
<Shortcut>propdp</Shortcut>
<Description>
Code snippet for a property using DependencyProperty as the backing store.
</Description>
<Author>Raja Dandu</Author>
</Header>
<Snippet>
<Declarations>
<Literal Editable="true">
<ID>type</ID>
<ToolTip>Property Type</ToolTip>
<Default>int</Default>
<Function>
</Function>
</Literal>
<Literal Editable="true">
<ID>property</ID>
<ToolTip>Property Name</ToolTip>
<Default>MyProperty</Default>
<Function>
</Function>
</Literal>
<Literal Editable="false">
<ID>ownerclass</ID>
<ToolTip>
The owning class of this Property. Typically the class that it is declared in.
</ToolTip>
<Default>ClassNamePlaceholder</Default>
<Function>ClassName()</Function>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[
public $type$ $property$
{
get { return ($type$)GetValue($property$Property); }
set { SetValue($property$Property, value); }
}

//Using a DependencyProperty as the backing store for MyProperty.
//This Enables Animation, Styling, Binding.
public static readonly DependencyProperty $property$Property =
DependencyProperty.Register("$property$", typeof($type$), typeof
($ownerclass$), new UIPropertyMetadata(default($type$)));


$end$]]>

</Code>

</Snippet>

</CodeSnippet>

</CodeSnippets>

Choose the Activity Template in Visual Studio which will give you Design Surface whereby you can drag N drop built in Activities to build Custom Activity or build purely using code which can be active by implementing the “Activity” Interface. Then create your properties if needed and then override the “Execute” Method.

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
try
{
WriteStatus(Source, Connection, Message, Priority);
return ActivityExecutionStatus.Closed;
}
catch (Exception)
{
return ActivityExecutionStatus.Canceling;
}
}
Use the Try catch bolck to trap any failure, If failed return cancel. If needed you can use “componsation” for compensating the halfdone Work/Process.

If successful:
return ActivityExecutionStatus.Closed;

Once you sucessfully build the project Activity calss, Your Custom Activity will apper in yout Main Workflow toolbox.





After creating multiple custom Activities, you can combine them into one single Activity based on your requirement. This Activity called as Composit Activity.

Wednesday, June 4, 2008

Creating PDF documents using Microsoft Office Add-in

Wondering how to programatically create PDF! Here is the C# code for you guys!


using Microsoft.Office;
using Microsoft.Office.Core;
using Microsoft.Office.Interop;

object sE = Type.Missing;
object sPDFFile = @"C:\sPDFFile.PDF";
object sDOCXFile = @"C:\1.docx";
object wdFormatPDF = 17; // 17 PDF format.
object WdDoNotSaveChanges = 0;
Microsoft.Office.Interop.Word.Application wdo = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Documents wdocs = wdo.Documents;

//Open the Document
Microsoft.Office.Interop.Word.Document wdoc = wdocs.Open(ref sDOCXFile, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE);

//Save the Document
wdoc.SaveAs(ref sPDFFile, ref wdFormatPDF, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE, ref sE);

//Little CleanUp
wdoc.Close(ref WdDoNotSaveChanges, ref sE, ref sE);
wdo.Quit(ref WdDoNotSaveChanges, ref sE, ref sE);

Requirements:
Download 2007 Microsoft Office Add-in: Microsoft Save as PDF and XPS from below link
http://download.microsoft.com/download/b/5/3/b5370004-d59d-493f-b005-2299ffca8596/SaveAsPDF.exe

Thursday, March 27, 2008

Working on Dev Machine And Not Installed with SharePoint (Workaround for Workstation Development!)

Copy few DLL's and register them and you all set for MOSS Workflow devlopment.
  1. Copy all the server DLL’s from this location “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI” to Dev Machine Maintain the same file structure.
  2. Then GAC these DLL’s (Drag N Drop into “C:\WINDOWS\assembly”)
    a. Microsoft.SharePoint.dll
    b. Microsoft.SharePoint.Security.dll
    c. Microsoft.Sharepoint.WorkflowActions.dll
    d. Microsoft.Office.Workflow.Tasks.dll
  3. Copy "microsoft.sharepoint.WorkflowActions.intl.dll" from Server by navigating through
    C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SharePoint.WorkflowActions.intl\12.0.0.0__71e9bce111e9429c
    COPY microsoft.sharepoint.WorkflowActions.intl.dll to Dev Machine
    3.a Now GAC the above DLL into your Dev Machine.
  4. Copy " microsoft.SharePoint.workflowactions.intl.resources.dll" from Server by navigating through C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SharePoint.WorkflowActions.intl.resources\12.0.0.0__71e9bce111e9429c
    COPY microsoft.SharePoint.workflowactions.intl.resources.dll to Dev Machine
    4.a Now GAC the above DLL into your Dev Machine
  5. Copy "microsoft.sharepoint.library.dll" from Server by navigating through C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SharePoint.Library\12.0.0.0__71e9bce111e9429c
    COPY microsoft.sharepoint.library.dll to Dev Machine
    5.a Now GAC the above DLL into your Dev Machine.
  6. Install Visual Studio 2005 Extensions for Windows Workflow Foundation (EN)
  7. If you wish you can also install “Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System_Setup"

Now you all set for developing SharePoint Workflows!