<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Content on Content Management &#187; C#</title>
	<atom:link href="http://contentoncontentmanagement.com/category/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://contentoncontentmanagement.com</link>
	<description></description>
	<lastBuildDate>Tue, 03 Aug 2010 12:57:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<atom:link rel="next" href="http://contentoncontentmanagement.com/category/c/feed/?page=2" />

		<item>
		<title>.NET API for Oracle UCM Version 2.0</title>
		<link>http://contentoncontentmanagement.com/2008/05/net-api-version-20/</link>
		<comments>http://contentoncontentmanagement.com/2008/05/net-api-version-20/#comments</comments>
		<pubDate>Mon, 26 May 2008 23:41:53 +0000</pubDate>
		<dc:creator>David Roe</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Content Management]]></category>

		<guid isPermaLink="false">http://ContentOnContentManagement.com/?p=81</guid>
		<description><![CDATA[The past few weeks I&#8217;ve been revisiting one of my old projects, the .NET API for Oracle UCM, which I&#8217;ve always felt was powerful but also missing some functionality.  The original project was a pretty simple API modeled after Oracle&#8217;s &#8230; <a href="http://contentoncontentmanagement.com/2008/05/net-api-version-20/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The past few weeks I&#8217;ve been revisiting one of my old projects, the .NET API for Oracle UCM, which I&#8217;ve always felt was powerful but also missing some functionality.  The original project was a pretty simple API modeled after Oracle&#8217;s own idcserver package usually used in Site Studio JSP development.  I&#8217;ve always liked the simplicity of the idcserver API as you can basically make any content server service call using just a couple of simple objects.  Implementing the same design in .NET(and later Flex) turned out to be a pretty successful(I think) model as well.  The original API is one of the most popular downloads and I&#8217;ve received quite a bit of positive feedback about it.</p>
<h3>What&#8217;s new with Version 2.0</h3>
<p>The improvements to version 2.0 center around a couple different areas:</p>
<h4>Direct communication with the content server</h4>
<p>This was probably my biggest motivator towards developing a new version of the API as the web filter to content server communication is somewhat of an undocumented mystery.  I&#8217;ve written a couple custom filters to integrate UCM with some third part security/SSO providers, but never have really picked apart the actual protocol that&#8217;s going back and forth.  Turns out it&#8217;s basically just passing HTTP through, but there are a couple values you can add to set authentication.</p>
<p>If you&#8217;re ever curious about what happens after your request is made to the web server, you can actually connect to the content server on its listener port(usually 4444) with a telnet terminal.  If you turnon  the CGI_SEND_DUMP on from the filter administration page it will log all calls made to the content server from the web server plugin.  Those logged requests can then be copied out of the log, modified and then pasted in to the telnet window.  Make sure that if you&#8217;re using telnet or even this API that the server you are executing from is included in the host or IP filter for the content server, else you won&#8217;t be able to connect.</p>
<h4>Asynchronous, Multithreaded Execution</h4>
<p>I started out planning for just asynchronous execution and then broke a bit more off with the threading(threads are addictive).  What I was looking for was the capability to make a content server request and then for the result to be passed back via an event.  The previous version&#8217;s process consisted of an executeService call, waiting inline until the request is completed and then retrieving results from the ServerBean.  The entire process usually takes less than a second, but a more elegant method might be for the executeService call to be made and then for an event handler to process the results when they arrive.  This new version supports the old method and the new event handler.</p>
<p>In addition to the events, the API is also multi threaded so when running in asynchronous mode each content server request runs in it&#8217;s own in it&#8217;s own thread.  Calling executeService will queue up a content server request and also create and activate a new execution object for your next call.</p>
<p>The API has a setting for the maximum number of threads which can run concurrently.   So if you make 1000 requests the content server will not receive 1000 requests all on top of each other.  Rather it will queue up all 1000 requests, keeping only the max number of threads active during processing.</p>
<p><strong>The Object Model</strong></p>
<p>In copying the idcserver package, I originally figured copying the idcserver object model would make things easier to pick up and learn, but unfortunately I think it was also a little trickier to extend and customize.  The API was flexible and powerful, but if you wanted to build a more robust API, say one specific to your application or organization, things were a bit trickier to extend.</p>
<p>In this new version I&#8217;ve set up a more flexible object model(<strong>as well as breaking backwards compatibility..sorry about that</strong>).  Every object used in the API is referenced by interface, but also encapsulates all functionality in abstract classes.  The only class that this does not apply to is the ExecutionManagerFactory, which is basically a static class used only to create a new ExecutionManager object (the new server bean).</p>
<h3>Some Examples</h3>
<p>Looking at some code examples with the new API, you&#8217;ll find that for the most part they aren&#8217;t too different than the old version.  Most of the methods are still named the same only the object types have changed.</p>
<h4>Check In New</h4>
<p>This example is a synchronous inline operation which checks in a file.  If you compare it to code used with version 1 the similaritites should pop right out.<br />
<code><br />
static void CheckInAFile()<br />
{<br />
  //create a new execution manager object<br />
  ICSExecutionManager em = ExecutionManagerFactory.CreateExecutionManager();<br />
  //set the connection mode.  We're going direct to the content server<br />
  em.ConnectionDetails.ConnectionMode = ConnectionMode.ContentServer;<br />
  //set the host<br />
  em.ConnectionDetails.ContentServerHost = "localhost";<br />
  //set the relative web root<br />
  em.ConnectionDetails.ContentServerRelativeWebRoot = "stellent";<br />
  //set the user to run the operation under<br />
  em.ContentServerUser = "sysadmin";<br />
  //set the service and other metadata<br />
  em.putLocal("IdcService", "CHECKIN_NEW");<br />
  em.putLocal("dDocTitle", "Picture of Me");<br />
  em.putLocal("dDocType", "Image");<br />
  em.putLocal("dSecurityGroup", "Public");<br />
  em.putLocal("dDocAuthor", "sysadmin");<br />
   //set the file<br />
   em.putLocal("primaryFile", new FileInfo(@"C:\file.jpg));<br />
   //execute the service<br />
   em.executeService();<br />
   //check the response<br />
   Console.WriteLine(em.getLocal("StatusMessage"));<br />
 }<br />
</code></p>
<p>This example demonstrates how the asyncronous, multi-threaded execution is utilized.  The code will execute three search calls as three different users on the content server.  Each execution will occur in it&#8217;s own thread, with the results being handled by the same event.</p>
<p><code><br />
static void AsyncSearchByUser(){<br />
    //create a new execution manager object<br />
    ICSExecutionManager em = ExecutionManagerFactory.CreateExecutionManager();<br />
    //set the connection to the content server<br />
    em.ConnectionDetails.ConnectionMode = ConnectionMode.ContentServer;<br />
    //set the host<br />
    em.ConnectionDetails.ContentServerHost = "localhost";<br />
    //set the relative web root<br />
    em.ConnectionDetails.ContentServerRelativeWebRoot = "stellent";<br />
    //this will be Asynchronous execution<br />
    em.ProcessMode = ProcessMode.Asynchronous;<br />
    //attach a complete event<br />
    em.OnExecutionComplete += new OUCSNET.events.ExecutionCompleteHandler(SearchOnExecutionComplete);</code></p>
<p><code>//first call will be as the user droe<br />
    em.ContentServerUser = "droe";<br />
    //set the search crtiera, we want a count of everything<br />
    em.putLocal("IdcService", "GET_SEARCH_RESULTS");<br />
    em.putLocal("QueryText", "");<br />
    //execute the server.<br />
    //Since this is Asynchronous, exection will continue right on<br />
    //with this search result request running in it's own thread<br />
    em.executeService();</p>
<p>//Once executeService is called a new Execution object is created<br />
    //and made active in the execution manager<br />
    //even though its the same em interface this is a new execution<br />
    //object</p>
<p>//this one will run as sysadmin<br />
    em.ContentServerUser = "sysadmin";<br />
    em.putLocal("IdcService", "GET_SEARCH_RESULTS");<br />
    em.putLocal("QueryText", "");<br />
    em.executeService();  //execute and move on</p>
<p>//repeat running as user<br />
    em.ContentServerUser = "user";<br />
    em.putLocal("IdcService", "GET_SEARCH_RESULTS");<br />
    em.putLocal("QueryText", "");<br />
    em.executeService();</p>
<p>//Since we are running asynchronously<br />
    //this should be the first line in the std out.<br />
    Console.WriteLine("All Executions Called");<br />
}</p>
<p></code></p>
<p><code>//The event handler for the exection object<br />
static void SearchOnExecutionComplete(object sender, EventArgs e)<br />
{<br />
    //convert the sender object to an ICSExecution object<br />
    ICSExecution execution = (ICSExecution)sender;<br />
    //output some results<br />
    Console.WriteLine(execution.ContentServerUser<br />
 + " can access "<br />
 + execution.getLocal("TotalRows")<br />
 + " content items");<br />
    //disposing the execution object will remove it<br />
    //from the internal list of execution objects<br />
    execution.Dispose();<br />
}<br />
</code></p>
<h3>Probably More Work To Do</h3>
<p>There is an outstanding issue with the API, with regards to NTLM authentication.  The previous version utilized the .NET WebRequest object for content server communication which supported NTLM authentication.  This version, because it needs to connect to both the web server and the content server directly is using the TCPClient object which is basically one step up from a raw socket connection.  Any protocols(beyond TCP) need to be implemented manually, and NTLM has been a bit tricky to configure, basic authentication however seems to work just fine.</p>
<p>This version of the API obviously has quite a bit more functionality in it and I fully expect there to be some bugs that appear(though I hope they don&#8217;t).  At the very least I think there will probably be some suggestions for better behavior by API, and so if have some or if you find an issue, please let me know by posting them to the forums.</p>
<h3>Not The Last Version</h3>
<p>This will not be the last version of the API, so if you have any ideas I&#8217;d love to hear them.  Eventually I&#8217;m hoping this project will develop in to something close to par with Oracle&#8217;s own Content Integration Suite.  So far I am loosely planning on developing some web examples using the API with ASP.NET as well as some examples for .NET 3.5.</p>
<p>The new version of the API can be downloaded here:</p>
<p><a href="http://contentoncontentmanagement.com/2008/05/26/net-api-version-20/net-api-for-oracle-ucm-v2/">.NET API for Oracle UCM Version 2.0</a></p>
]]></content:encoded>
			<wfw:commentRss>http://contentoncontentmanagement.com/2008/05/net-api-version-20/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>.NET API For Stellent / Oracle Content Server</title>
		<link>http://contentoncontentmanagement.com/2007/09/net-api-for-stellent-oracle-content-server/</link>
		<comments>http://contentoncontentmanagement.com/2007/09/net-api-for-stellent-oracle-content-server/#comments</comments>
		<pubDate>Mon, 01 Oct 2007 03:37:21 +0000</pubDate>
		<dc:creator>David Roe</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Stellent]]></category>
		<category><![CDATA[Web Service]]></category>

		<guid isPermaLink="false">http://ContentOnContentManagement.com/2007/09/30/net-api-for-stellent-oracle-content-server/</guid>
		<description><![CDATA[Stellent / Oracle Content Sever has a wonderful component which allows you wrap a WSDL around any of the app&#8217;s services.  It&#8217;s pretty easy to use and has made Visual Studio(at least for me), my preferred IDE for writing ad-hoc &#8230; <a href="http://contentoncontentmanagement.com/2007/09/net-api-for-stellent-oracle-content-server/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Stellent / Oracle Content Sever has a wonderful component which allows you wrap a WSDL around any of the app&#8217;s services.  It&#8217;s pretty easy to use and has made Visual Studio(at least for me), my preferred IDE for writing ad-hoc and batch applications.  In fact I have to confess that I&#8217;ve found it much simpler to write simple batchloading programs in .NET rather then using Stellent&#8217;s own batchloading tool.</p>
<p>Despite my personal fandom of the WSDL component, it does have a couple drawbacks:</p>
<p>1.  Each web service is in it&#8217;s own namespace.  This makes it a bit of a pain when working with multi-step operations, for instance if you&#8217;re calling the DocInfo service with a WSDL it will return all custom metadata in an array of IdcProperty objects.  If you&#8217;re then planning on updating that item or checking in another related item, you&#8217;ll have to copy all your original IdcProperty objects over to new IdcProperty objects specific to the Checkin/Update service&#8217;s namespace.</p>
<p>2.  Aside from the seven or so pre-defined services, you have to define any additional WSDLS you wish to consume.  Not the end of the world, but it does make the development a little tricker when you need ensure your WSDL exists on each instance you connect to and that it&#8217;s defined to your specs.</p>
<p>There is an alternative; rather then using the WSDLs, you could just add IsSoap=1 to the end of any service call, which will then return you request in SOAP format.  Of course there&#8217;s no friendly WSDL to create all your proxy classes, leaving the SOAP parsing up to you.  In addition uploading files can also be pretty tricky as you essentially need to replicate a multi-part/form upload.</p>
<p>To make my life(and potentially yours) a little easier, I&#8217;ve been experimenting and ultimately developed a simple .NET API for the Stellent / Oracle Content Server.  Modeled after the Stellent&#8217;s Java-based idcserver package, the API can make IsSoap service calls to retrieve information, or just straight HTTP calls when downloading files.  In addition since all calls are made as multipart-form/data posts, one to many files may be uploaded and checked in.</p>
<p><span id="more-13"></span>The API has two public classes, the ServerBean which is the primary interface to the API and the ServerResultSet class which acts and behaves like a Stellent Resultset.  If you think you&#8217;ve seen those class names before, it&#8217;s because you have.  I tried to replicate the functionality of the Content Server&#8217;s idcserver package in .NET.</p>
<p>Here&#8217;s an example of a search results call using the API:</p>
<p><code>//create the object<br />
ServerBean sb = new ServerBean();<br />
//set the url to the content server<br />
sb.ContentServerURL = "http://localhost/stellent/idcplg";<br />
//set our credentials<br />
sb.ContentServerCredentials = new System.Net.NetworkCredential("sysadmin", "idc");<br />
//set the service<br />
sb.putLocal("IdcService", "GET_SEARCH_RESULTS");<br />
//pass in our query<br />
sb.putLocal("QueryText", "dDocTitle &lt;substring&gt; <substring></substring>`Test`");<br />
//execute the service<br />
sb.executeService();<br />
//get our search results<br />
ServerResultSet SearchResults = sb.getResultSet("SearchResults");<br />
if (SearchResults != null)<br />
{<br />
  //loop through the search results<br />
  for(SearchResults.first();SearchResults.isRowPresent();SearchResults.next()){<br />
  //write the content id<br />
  System.Diagnostics.Debug.WriteLine(SearchResults.getStringValue("dDocName"));<br />
  }<br />
}</code> </p>
<p>As you can see the syntax is extremely similar to the Content Server&#8217;s idcserver package.  Anyone familier with JSP development in the content server, should find it very familiar.</p>
<p>Uploading files is also very easy.  I&#8217;ve overriden the &#8220;putLocal&#8221; method so that it can accept a string or a FileInfo object as a value argument.<br />
<code><br />
//create the object<br />
ServerBean sb = new ServerBean();<br />
//set our url<br />
sb.ContentServerURL = "http://localhost/stellent/idcplg";<br />
//set our credentials<br />
sb.ContentServerCredentials = new System.Net.NetworkCredential("sysadmin", "idc");<br />
//service is a check in new<br />
sb.putLocal("IdcService", "CHECKIN_NEW");<br />
//set the title and required arguments<br />
sb.putLocal("dDocTitle", "NET TEST CHECKIN");<br />
sb.putLocal("dDocType", "Document");<br />
sb.putLocal("dDocAuthor", "sysadmin");<br />
sb.putLocal("dSecurityGroup", "Public");<br />
//create to fileinfo objects based on some local files<br />
System.IO.FileInfo File1 = new System.IO.FileInfo(@"C:\Test Spreadsheet.xls");<br />
System.IO.FileInfo File2 = new System.IO.FileInfo(@"C:\Test Text File.txt");<br />
//add the files<br />
sb.putLocal("primaryFile", File1);<br />
sb.putLocal("alternateFile", File2);<br />
//execute the service<br />
sb.executeService();<br />
//check our status<br />
Console.WriteLine(sb.getLocal("StatusMessage"));<br />
</code></p>
<p>Since we also need to download files or retrieve raw results like a dynamic conversion, the underlying executeServiceEx method which is called by the executeService method and also returns a raw stream from the Content Server&#8217;s response is a public method.  Calling executeServiceEx directly will skip the lines of code realted to parsing the server&#8217;s response.</p>
<p>In this example, we perform a dynamic conversion and write the raw HTML to the console window</p>
<p><code>//Create the object<br />
ServerBean sb = new ServerBean();<br />
//set the url<br />
sb.ContentServerURL = "http://localhost/stellent/idcplg";<br />
//set our credentials<br />
sb.ContentServerCredentials = new System.Net.NetworkCredential("sysadmin", "idc");<br />
//set the dynamic conversion<br />
sb.putLocal("IdcService", "GET_DYNAMIC_CONVERSION");<br />
//set our required parameters<br />
sb.putLocal("dDocName", "[Content ID]");<br />
sb.putLocal("RevisionSelectionMethod", "LatestReleased");<br />
//call executeServiceEx, which returns the raw stream<br />
Stream resultStream = sb.executeServiceEx();<br />
//create a reader<br />
System.IO.StreamReader reader = new System.IO.StreamReader(resultStream);<br />
//read the stream<br />
String resultString = reader.ReadToEnd();<br />
//write it to the console<br />
Console.Write(resultString);</code></p>
<p><code></code>That&#8217;s the basic gist on how to work with the API, I will be following up this post with one going through the actual code.  Like any of my code examples, the API is provided without support or warrenty, but I plan keeping the API as sort of a a personal ongoing project so you can expect future versions and enhancements.  If you have any questions or ideas please let me know.  I&#8217;m really looking for some feedback on this one, so comment away.</p>
<p>I&#8217;ve bundled the source as well as an installer package together and posted them for download <a rel="attachment wp-att-14" href="http://ContentOnContentManagement.com/2007/09/30/net-api-for-stellent-oracle-content-server/net-api-for-stellent-oracle-content-server/" title=".NET API For Stellent / Oracle Content Server">here</a><a href="http://contentoncontentmanagement.com/wp-content/uploads/2007/09/simple-net-content-server-api.zip">.</a>  Once installed the API will appear in your Visual Studio add references dialog as OUCSNET.</p>
<p><a href="http://ContentOnContentManagement.com/2007/09/30/net-api-for-stellent-oracle-content-server/net-api-for-stellent-oracle-content-server/" rel="attachment wp-att-14">.NET API For Stellent / Oracle Content Server</a></p>
]]></content:encoded>
			<wfw:commentRss>http://contentoncontentmanagement.com/2007/09/net-api-for-stellent-oracle-content-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

