CollabNet claims that CollabNet SourceForge® Enterprise Edition is the number one platform for distributed teams. Implemented as a web application, it enables distributed teams to share the same source code repositories, issue tracking system and collaborate. It enables external systems, such as CruiseControl, to interact with the system through one of its many web services. However, consuming those services via .NET is a challenge because some WSDL do not validate, nor are there any examples of how to consume services from .NET. Hopefully CollabNet will sort things out in the next release.
Create a directory where you want to generate service references. For this examples, lets use C:SFEE. In c:sfee, execute the svcutil command line. This will generate a file called SourceForge.cs.
svcutil
http://sfee-demo/sf-soap43/services/DiscussionApp?wsdl
http://sfee-demo/sf-soap43/services/DocumentApp?wsdl
http://sfee-demo/sf-soap43/services/FrsApp?wsdl
http://sfee-demo/sf-soap43/services/IntegrationDataApp?wsdl
http://sfee-demo/sf-soap43/services/NewsApp?wsdl
http://sfee-demo/sf-soap43/services/RbacApp?wsdl
http://sfee-demo/sf-soap43/services/ScmApp?wsdl
http://sfee-demo/sf-soap43/services/SourceForge?wsdl
http://sfee-demo/sf-soap43/services/TaskApp?wsdl
http://sfee-demo/sf-soap43/services/TrackerApp?wsdl
http://sfee-demo/sf-soap43/services/WikiApp?wsdl
/out:SourceForge.cs /n:*,Sfee
At this time, references cannot be generated for FileStorageApp or SimpleFileStorageApp because the schema for namespace "http://xml.apache.org/xml-soap" doesn't exist. Once you have generated service references, you are ready to call the SFEE project.
Before you can really do anything with the SFEE web services, you need to login. You can do this by calling the SourceForge web service. The login method returns a session id (or token) that you will pass to other methods. Here is an example showing how to list the projects of admin.
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
ProjectSoapList projects = client.getProjectList(session);
foreach (ProjectSoapRow row in projects.dataRows)
{
Console.WriteLine(row.title);
}
client.logoff("admin", session);
client.Close();
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
// this is interesting.
ProjectSoapList projects = client.getProjectList(session);
foreach (ProjectSoapRow row in projects.dataRows)
{
Console.WriteLine("=== {0} ===", row.title);
Console.WriteLine(row.id);
Console.WriteLine(row.path);
Console.WriteLine(row.description);
Console.WriteLine(row.dateCreated);
}
client.logoff("admin", session);
client.Close();
In this example, we get the project data for a project with the id "proj1039" and print its details.
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
ProjectSoapDO project = client.getProjectData(session, "proj1039");
Console.WriteLine(@"=== {0} ===", project.title);
Console.WriteLine(project.id);
Console.WriteLine(project.path);
Console.WriteLine(project.description);
Console.WriteLine(project.createdDate);
Console.WriteLine(project.createdBy);
Console.WriteLine(project.lastModifiedBy);
Console.WriteLine(project.lastModifiedDate);
Console.WriteLine(project.version);
client.logoff("admin", session);
client.Close();
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
WikiAppSoapClient wiki = new WikiAppSoapClient();
WikiPageSoapDO page = wiki.getWikiPageDataByName(session, "proj1019", "HomePage");
Console.WriteLine(page.wikiText);
client.logoff("admin", session);
client.Close();
This snippet gets the page with a specific id and prints it to the console.
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
WikiAppSoapClient wiki = new WikiAppSoapClient();
WikiPageSoapDO page = wiki.getWikiPageData(session, "wiki1026");
Console.WriteLine(page.wikiText);
client.logoff("admin", session);
client.Close();
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
WikiAppSoapClient wiki = new WikiAppSoapClient();
wiki.createWikiPage(session,
"proj1019",
"TestResults",
"This is the result of tests we wrote",
"Some Comment");
client.logoff("admin", session);
client.Close();
This snippet gets the text from the home page and prepends a bullet after the "List" heading.
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
WikiAppSoapClient wiki = new WikiAppSoapClient();
WikiPageSoapDO page = wiki.getWikiPageDataByName(session, "proj1019", "HomePage");
string text = page.wikiText;
const string title = "!!List";
if(string.IsNullOrEmpty(text))
{
text = string.Format("!!!Headingnn{0}", title);
}
int index = text.LastIndexOf(title);
index += title.Length;
text = text.Insert(index, "n* Bullet ");
page.wikiText = text;
wiki.setWikiPageData(session, page);
client.logoff("admin", session);
client.Close();
First, you need to save the results of the XUnit.net script to an xml file. Lets assume you save it to C:test.xml.
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
WikiAppSoapClient wiki = new WikiAppSoapClient();
// Update a specific page
WikiPageSoapDO page = wiki.getWikiPageData(session, "wiki1026");
StringWriter writer = new StringWriter();
// transform the XML to a wiki page
XPathDocument doc = new XPathDocument(@"c:test.xml");
XslTransform transform = new XslTransform() ;
transform.Load("xunit.xslt");
transform.Transform(doc, null, writer);
// update the wiki
page.wikiText = writer.ToString();
wiki.setWikiPageData(session, page);
client.logoff("admin", session);
client.Close();
The XUnit.XSLT may look as follows. The SourceForge Wiki syntax is very sensitive to spaces, so its recommended that you change the XSLT to format correctly. For example, you have to ensure that no newlines are generated in the data of a bullet point.
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="<a href="http://www.w3.org/1999/XSL/Transform" class="external free" title="http://www.w3.org/1999/XSL/Transform" rel="nofollow">http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
!!!Functional Test Results
!!Summary
* Tests run: <xsl:value-of select="sum(//assembly/@total)"/>
* Tests run: <xsl:value-of select="sum(//assembly/@total)"/>
* Failures: <xsl:value-of select="sum(//assembly/@failed)"/>
* Skipped: <xsl:value-of select="sum(//assembly/@skipped)"/>
* Run time: <xsl:value-of select="sum(//assembly/@time)"/>
!!Tests
<xsl:if test="//assembly/class/test[@result='Fail']">
!Failed Tests
<xsl:apply-templates select="//assembly/class/test[@result='Fail']">
<xsl:sort select="@name"/>
</xsl:apply-templates>
</xsl:if><xsl:if test="//assembly/class/test[@result='Skip']">
!Skipped Tests
<xsl:apply-templates select="//assembly/class/test[@result='Skip']">
<xsl:sort select="@name"/>
</xsl:apply-templates>
</xsl:if><xsl:if test="//assembly/class/test[@result='Pass']">
!Passed Tests
<xsl:apply-templates select="//assembly/class/test[@result='Pass']">
<xsl:sort select="@name"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
<xsl:template match="test">
*(<xsl:apply-templates select="traits/trait[@name='Category']">
<xsl:sort select="@name"/>
</xsl:apply-templates>) <xsl:value-of select="@name"/>
</xsl:template>
<xsl:template match="trait">
<xsl:value-of select="@value"/>
</xsl:template>
</xsl:stylesheet>
The following snippet gets a list of packages for project with id "proj1019".
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
const string projectId = "proj1019";
FrsAppSoapClient frs = new FrsAppSoapClient();
PackageSoapList packageList = frs.getPackageList(session, projectId);
foreach (PackageSoapRow row in packageList.dataRows)
{
PackageSoapDO package = frs.getPackageData(session, row.id);
Console.WriteLine(package.title);
Console.WriteLine(package.description);
Console.WriteLine(package.version);
Console.WriteLine(package.lastModifiedBy);
Console.WriteLine(package.lastModifiedDate);
Console.WriteLine(package.parentFolderId);
Console.WriteLine(package.path);
Console.WriteLine();
}
client.logoff("admin", session);
client.Close();
The following snippet gets a list of releases in package "pkg1088". This may be particular useful if you want to have some automated process to download and do something with the latest release.
SourceForgeSoapClient client = new SourceForgeSoapClient();
string session = client.login("admin", "admin");
FrsAppSoapClient frs = new FrsAppSoapClient();
const string packageId = "pkg1088";
ReleaseSoapList releases = frs.getReleaseList(session, packageId);
foreach (ReleaseSoapRow row in releases.dataRows)
{
ReleaseSoapDO release = frs.getReleaseData(session, row.id);
Console.WriteLine("{0} ({1})", release.title, release.createdDate);
}
client.logoff("admin", session);
client.Close();
Comments