Tags

    CollabNet SourceForge Enterprise Edition and .NET

    Comments

    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.

    Generating Service References

    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.

    Consuming the services

    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();
    

    Working with Projects

    List projects of logged in user
    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();
    
    Getting the project when you have an project id

    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();
    
    

    Working with the Wiki

    Getting text of the homepage wiki page
    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();
    
    Getting text of a specific wiki page

    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();
    
    Creating a new page
    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();
    
    Updating an existing page

    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();
    
    Uploading XUnit.net test results to a wiki page

    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>
    

    Working with the File Releases

    Getting a list of packages

    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();
    
    Getting a list of releases for a package

    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();