Introduction
This article gives one of the practical usages of the .NET reflection concept in SharePoint webparts. We can make use of this concept to change the properties of the SharePoint webparts during runtime in a bulk manner. I have used this for changing the URLs from old to new referred in the CorasWorks webparts and Image webparts.
Background
The CorasWorks suite is used for roll up of all the lists in a SharePoint system. The challenge here is when the portal and the sites are restored, the weparts in the new system will have the links pointed to old URL. The CorasWorks store the "SiteURL
" and "ListNames
" properties in the .dwp file of that webpart.
All SharePoint developers know that the webparts are associated with a .dwp file and the data associated with the webparts are not stored in the database. The webpart specific data are stored in the .dwp file and so this has to be changed to the new one. You might wonder what the big deal is, but suppose the system has thousands of wss sites and least one CorasWorks webpart is there. Hope you can recognize the criticality now.
I need to really appreciate the "Reflection" concept of .NET here.
- The webparts are iterated for all the webs using the
GetWebPartCollection
of the SPWeb
object and the webpart type is identified using GetType()
method. - Using the
GetMember()
method of the object, the Members[]
array is created. - A
PropertyInfo
object is created based on the Members
element. - Then the
GetValue()
and SetValue()
method of PropertyInfo
helps in getting the old value, replacing the new one and setting it back.
Once the value is set, the webpart values are saved using the SaveChanges
method of the SPWebPartCollection
object.
Note: This can be done only for the wss sites and not for portal areas due to permission restriction of saving the webpart values.
Using the code
The code shows looping through the virtual servers (the IIS websites linked to SharePoint) and all further sites. It looks for the type of the webpart.
SPGlobalAdmin global = new SPGlobalAdmin();
string webname = string.Empty;
#region looping Virtual servers
for(int count=1; count<=2; count++)
{
SPSiteCollection allSitesOnServer = global.VirtualServers[count].Sites;
int totalSites = allSitesOnServer.Count;
for(int sitesCount =0;sitesCount<totalSites;sitesCount++)
{
try
{
SPSite allSites = allSitesOnServer[sitesCount];
SPWebCollection allWebs = allSites.AllWebs;
#region looping web collection
foreach(SPWeb currentWeb in allWebs)
{
webname = currentWeb.Url ;
SPWebPartCollection webParts = currentWeb.GetWebPartCollection
("default.aspx",Storage.Shared);
for(int i=0; i<webParts.Count;i++)
{
WebPart currentWebPart = webParts[i];
object obj = null;
Type typeobj = currentWebPart.GetType();
if(currentWebPart.GetType().FullName.EndsWith
("ImageWebPart"))
{
Log("The Image webparts " +
currentWebPart.GetType().FullName);
Log("Info of " + currentWeb.Url + ":");
currentWebPart.AllowZoneChange = true;
WebPart newWebPart = ReadUpdatePropertyValues
(currentWebPart,typeobj,obj,oldUrl,newUrl);
webParts.SaveChanges(newWebPart.StorageKey);
}
}
}
#endregion
}
catch(Exception ex)
{
Log("Error in : " + webname + "--->" + ex.Message);
}
}
}
public static WebPart ReadUpdatePropertyValues
(WebPart wpart,Type wptype, object obj,string oldUrl,string newUrl)
{
try
{
string[] wpProps = new string[]{"ImageLink"};
#region looping through properties
foreach (string wpProp in wpProps)
{
MemberInfo[] members = wptype.GetMember(wpProp);
if(members.Length != 1)
{
Log(failed+": Not handled - No required property " +
wpart.Title );
failed++;
}
else
{
switch(members[0].MemberType)
{
case MemberTypes.Property :
{
PropertyInfo prop = (PropertyInfo)members[0];
obj = prop.GetValue(wpart, new object[0]);
string newurl = obj.ToString().Replace(oldUrl,newUrl);
if(newurl != obj.ToString())
{
object strVal = (object)newurl;
prop.SetValue(wpart, strVal ,new object[0]);
Log(changed + ": " + wpart.Title +
" : Changed property");
Log(changed + ": " + newurl +
" : Changed property");
changed++;
}
}
break;
case MemberTypes.Field :
{
FieldInfo field = (FieldInfo)members[0];
obj = field.GetValue(wpart);
string newurl = obj.ToString().Replace(oldUrl,newUrl);
object strVal = (object)newurl;
field.SetValue(wpart,strVal);
}
break;
default :
throw new Exception("Not found");
}
}
Log(success +": " +wpart.Title+" : Has property");
success++;
}
#endregion
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
return wpart;
}
Havin 6+years of IT experience and Working as a Technical Lead with Wipro Technologies, Bangalore specifically in Sharepoint and .Net. My hobbies are painting and photography.