Friday, April 02, 2010

Extract Data from MOSS 2007 (Sharepoint)

The following classes shows how easy it can be to extract data from MOSS 2007 (Sharepoint) and fill the values into properties. The class also checks if there are attachments if so, then it will download attached files to a local path.

the sample below assumes that you have created a Web References to your sharepoint list web service: https://your.sharepoint.com/_vti_bin/lists.asmx

please notice that i have copy and pasted methods from various classes into one class without running it, so don't be surprised if you get any compilation error.

the main aim behind it is to extract data from a bug tracker list and import it over the tfs api 2010 into team foundation server.

public class Sharepoint2007Wrapper
{
public string Title { get; set; }
public string Date { get; set; }
public string CreatedBy { get; set; }

[System.Diagnostics.DebuggerStepThrough]
private ICredentials GetCredentials()
{
return new NetworkCredential("username", "password", "domain");
}

private DataRowCollection LoadSharepointData(string viewFields, string listName)
{
sharepoint.Lists sp = new MigrationToolExportImport.sharepoint.Lists();
sp.Url = "http://url.ToYourSiteCollection.com/_vti_bin/Lists.asmx";
sp.Credentials = this.GetCredentials();

// this part is needed to receive the link to document attachments and all specified fields
XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");

// receive links to the attachments
ndQueryOptions.InnerXml = "<IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls>";
ndViewFields.InnerXml = viewFields;
ndQuery.InnerXml = ""; // <Query />

XmlNode allLists = sp.GetListCollection();
// ensure the number is big enough because without this value sharepoint returns configured amount which is 100 per view!
// listsgetlistitems method lists only 100
XmlNode lists = sp.GetListItems(listName, "", ndQuery, ndViewFields, "10000", ndQueryOptions, "");

XmlNodeReader r = new XmlNodeReader(lists);
DataSet ds = new DataSet();
ds.ReadXml(r, XmlReadMode.Auto);

return ds.Tables[1].Rows;
}

public void Extract(string listname)
{
if(string.IsNullOrEmpty(listname))
listname = "Your Sharepoint 2007 List Name";
// if nothing is provided then it returns all rows otherwise
// uese fieldRef tags to retrieve only requested columns
// <FieldRef Name="LinkTitle" /> <FieldRef Name="Title" />
string viewFields = "";
DataRowCollection rows = LoadSharepointData(viewFields, listname);

int i = 0;
foreach (DataRow row in rows)
{
try
{
if ((++i % 10) == 0)
Console.Write('.');
this.ParseAndExtractRow(row, GetCredentials());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}

private List<string> Attachments { get; set; }

private void ParseAndExtractRow(System.Data.DataRow data, ICredentials credentials)
{
// this helps to identify which text we need to retrieve the column value
this.PrintColNames(data);

this.Title = this.GetRowValue(data, "ows_Title");
this.Date = this.GetRowValue(data, "ows_Date");
this.CreatedBy = this.GetRowValue(data, "ows_CreatedBy");
}

private void DownloadAttachments(string urls, ICredentials credentials)
{
this.Attachments = new List<string>();
string[] fileUrls = urls.Split('#');
if (fileUrls != null && fileUrls.Length > 0)
{
foreach (string file in fileUrls)
{
string uri = file.Replace(";", "");
if (!string.IsNullOrEmpty(uri) && uri.Length > 1)
this.Attachments.Add(uri);
}
}

List<string> filepaths = new List<string>();

if (this.Attachments.Count > 0)
{
foreach (string url in this.Attachments)
{
try
{
string file = System.IO.Path.GetFileName(url);
string filepath = new Attchments().DownloadSharepointAttachment(url, file, credentials);
if (System.IO.File.Exists(filepath))
filepaths.Add(filepath);
else
Console.WriteLine("File does not exists!!");
}
catch (Exception ex)
{
Console.WriteLine("Error upon file download: " + ex.Message);
}
}
this.Attachments.Clear();
this.Attachments.AddRange(filepaths);
}
}

private void PrintColNames(System.Data.DataRow data)
{
for (int i = 0; i < data.Table.Columns.Count; ++i)
{
Console.WriteLine(data.Table.Columns[i].ToString());
}
}

private string GetRowValue(System.Data.DataRow data, string columnName)
{
try
{
if (data[columnName] != null)
return data[columnName].ToString();
else
return string.Empty;
}
catch (Exception ex)
{
return string.Empty;
}
}

private class Attchments
{
private static CookieContainer _cookieContainer;
public static CookieContainer CookieContainer
{
get
{
if (_cookieContainer == null)
{
_cookieContainer = new CookieContainer();
}
return _cookieContainer;
}
}

public class CookieAwareWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = AttchmentHandler.CookieContainer;
(request as HttpWebRequest).KeepAlive = false;
}
return request;
}
}

public string DownloadSharepointAttachment(string url, string filename, ICredentials credentials)
{
string localFolder = @"Z:\\YourRequestedLocationOnYourHardDrive\\";
// ensure we do not overwrite files with the same name.
string uniqueGuid = Guid.NewGuid().ToString();

//now the code that will download the file
try
{
using (WebClient client = new CookieAwareWebClient())
{
client.Credentials = credentials;
// client.DownloadFile("http://address.com/abc.pdf", @"c:\\temp\abc_local.pdf");
client.DownloadFile(url, localFolder + uniqueGuid + "_-_" + filename);
client.Dispose();
}
return localFolder + uniqueGuid + "_-_" + filename;
}
catch (Exception ex)
{
Console.WriteLine("Download Sharepoint Attachment Error: " + ex.Message);
return string.Empty;
}
}
}
}

TFS API: Creating recursive TFS areas

The following code has been founded at Shai Raiten's blog:

TFS API Part 9: Get Area/Iteration Programmatically

TFS API Part 11: Get Area/Iteration Security Settings Using IAuthorizationService

He created a fantastic serie how to work with the API!!!
Thanks Shai



Simple Call:
NodeInfo nodeInfo = this.GetAddNode("\\new area name1", "YourProject", StructureType.Area);
NodeInfo nodeInfo = this.GetAddNode("\\new area name2", "YourProject", StructureType.Area);

Recursive Calls:
NodeInfo nodeInfo = this.GetAddNode("\\new area name\\area 1", "YourProject", StructureType.Area);
NodeInfo nodeInfo = this.GetAddNode("\\new area name\\area 2", "YourProject", StructureType.Area);





public enum StructureType
{
Iteration = 0,
Area = 1
}

private NodeInfo GetAddNode(string ElementPath, string projectName, StructureType nodeType)
{
NodeInfo retVal;
string rootNodePath = "\\" + projectName + "\\" + nodeType.ToString();

//Check if this path already exsist
string newPath = rootNodePath + ElementPath;
try
{
retVal = css.GetNodeFromPath(newPath);
if (retVal != null)
{
// return existing node
return retVal;
}
}
catch (Exception ex)
{
if (ex.Message.Contains("The following node does not exist"))
{
//just means that this path is not exist and we can continue.
}
else
{
throw ex;
}
}

int BackSlashIndex = ElementPath.LastIndexOf("\\");
string Newpathname = ElementPath.Substring(BackSlashIndex + 1);
string NewPath = (BackSlashIndex == 0 ? string.Empty : ElementPath.Substring(0, BackSlashIndex));
string PathRoot = rootNodePath + NewPath;
NodeInfo previousPath = null;
try
{
previousPath = css.GetNodeFromPath(PathRoot);
}
catch (Exception ex)
{
// had to update the string from shai's original code
if (ex.Message.Contains("TF200014: The following node does not exist:"))
{
//just means that this path is not exist and we can continue.
previousPath = null;
}
else
{
throw ex;
}
}
if (previousPath == null)
{
//call this method to create the parent paths.
previousPath = GetAddNode(NewPath, projectName, nodeType);
}

string newPathUri = css.CreateNode(Newpathname, previousPath.Uri);
NodeInfo ni = css.GetNode(newPathUri);

Console.WriteLine("Creating Area: " + ni.Path.ToString());
return ni;
}

TFS API: Get Team Project

The following method retrieves the TeamProject over TFS API:

    private TeamProject GetTeamProject()
{
VersionControlServer versionControl = (VersionControlServer)server.GetService(typeof(VersionControlServer));
TeamProject teamProject = versionControl.GetTeamProject("ProjectName");
return teamProject;
}

TFS API: List all TFS Users

The following code lists all TFS users over the API.

[System.Diagnostics.DebuggerStepThrough]
private ICredentials GetCredentials()
{
return new NetworkCredential("user", "pwd", "domain");
}


    public TfsWrapper()
{
server = new TeamFoundationServer("https://your.tfs.com/tfs/store", GetCredentials());
server.Authenticate();
css = (ICommonStructureService)server.GetService(typeof(ICommonStructureService));
gss = (IGroupSecurityService)server.GetService(typeof(IGroupSecurityService));
tfsIdentities = new List<Identity>();
}


public void ReadTfsUsers()
{
TeamProject tp = this.GetTeamProject();
Identity[] appGroups = gss.ListApplicationGroups(tp.ArtifactUri.AbsoluteUri);

foreach (Identity group in appGroups)
{
Identity[] groupMembers = gss.ReadIdentities(SearchFactor.Sid, new string[] { group.Sid }, QueryMembership.Expanded);
foreach (Identity member in groupMembers)
{
Console.WriteLine(member.DisplayName);
if (member.Members != null)
{
foreach (string memberSid in member.Members)
{
Identity memberInfo = gss.ReadIdentity(SearchFactor.Sid, memberSid, QueryMembership.None);

if (memberInfo.Type == IdentityType.WindowsUser)
{
if (!this.tfsIdentities.Contains(memberInfo))
this.tfsIdentities.Add(memberInfo);

// Console.WriteLine(" {0}", memberInfo.DisplayName);
//Console.WriteLine("AccountName :" + memberInfo.AccountName);
//Console.WriteLine("Deleted :" + memberInfo.Deleted);
//Console.WriteLine("Description :" + memberInfo.Description);
//Console.WriteLine("DisplayName :" + memberInfo.DisplayName);
//Console.WriteLine("DistinguishedName :" + memberInfo.DistinguishedName);
//Console.WriteLine("Domain :" + memberInfo.Domain);
//Console.WriteLine("MailAddress :" + memberInfo.MailAddress);
//Console.WriteLine("Sid :" + memberInfo.Sid);
//Console.WriteLine("Type :" + memberInfo.Type.ToString());
//Console.WriteLine("*********************************");
}
}
}
}
}
}

Thursday, April 01, 2010

Shared Cache - .Net Caching made easy

All information about Shared Cache is available here: http://www.sharedcache.com/. Its free and easy to use, we provide all sources at codeplex.

Facebook Badge