12.07.2015 Views

Introduction to the WDK Datagrid - EMC Community Network

Introduction to the WDK Datagrid - EMC Community Network

Introduction to the WDK Datagrid - EMC Community Network

SHOW MORE
SHOW LESS
  • No tags were found...

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Documentum DFS, UCF and ASP .NET – Practical GuideBy Mirza Fazlic, August 2009 – mirza.fazlic@gmail.comThis article is a practical guide <strong>to</strong> <strong>the</strong> use of UCF as a content transfer mechanism in a DFS basedapplication. For <strong>the</strong>ory behind UCF, please consult <strong>the</strong> DFS documentation. The example DFSapplication demonstrated in this article will be built using a cus<strong>to</strong>m UCF Applet integrated with anASP .NET application. Core services for view, upload, checkout and check in will be covered. Youshould be familiar with <strong>the</strong> basic DFS concepts. This article was written using DFS 6.5 SP1.INTRODUCTION .....................................................................................................................................2APPLICATION OVERVIEW ....................................................................................................................2ENVIRONMENT OVERVIEW ..................................................................................................................3UCF APPLET ..........................................................................................................................................3Including <strong>the</strong> applet in <strong>the</strong> ASP .NET page .......................................................................................................................3Applet security requirements .............................................................................................................................................4Creating a keys<strong>to</strong>re ...........................................................................................................................................................4Signing <strong>the</strong> applet jar file ...................................................................................................................................................4Applet Code .........................................................................................................................................................................5Building <strong>the</strong> applet .............................................................................................................................................................6UCF Client Installer Process ...............................................................................................................................................7ASP .NET APPLICATION .....................................................................................................................10Document Listing Component .........................................................................................................................................10Page PostBack and Browser Refresh Problem ..............................................................................................................14Frame Approach ................................................................................................................................................................15Cookie Approach ...............................................................................................................................................................16Separate Window Approach .............................................................................................................................................18View Document Example ..................................................................................................................................................18Checkout Document Example ..........................................................................................................................................20Checkin Document Example ............................................................................................................................................21Import Document Example ...............................................................................................................................................22Conclusion .........................................................................................................................................................................23


<strong>Introduction</strong>UCF allows <strong>the</strong> content <strong>to</strong> be transferred directly between <strong>the</strong> client browser and <strong>the</strong> content server.To accomplish this, connection needs <strong>to</strong> be established between <strong>the</strong>se two points. The UCF clientcode will need <strong>to</strong> execute on <strong>the</strong> user browser machine. It will require solid access <strong>to</strong> <strong>the</strong> user’smachine (i.e. <strong>to</strong> read and write <strong>the</strong> files, modify registry settings etc). In order <strong>to</strong> do this, <strong>the</strong> clientcode needs <strong>to</strong> execute ei<strong>the</strong>r from within an applet or an Active X control. At <strong>the</strong> time of writing thisarticle, <strong>the</strong> ActiveX control for <strong>the</strong> UCF is still in <strong>the</strong> “early access” (seehttps://community.emc.com/docs/DOC-3501 for more details); <strong>the</strong>refore, in this article, we are going <strong>to</strong> focuson <strong>the</strong> applet. To make things interesting, however, we will integrate it with an ASP .NET application.While <strong>the</strong> code examples are in C# ASP .NET, <strong>the</strong> discussions regarding <strong>the</strong> use of applet shouldapply <strong>to</strong> people integrating UCF and DFS using o<strong>the</strong>r Java-based frameworks.Application OverviewThe example application will retrieve a list of documents and display <strong>the</strong>m in a simple data grid. Theuser will be able <strong>to</strong> select a row in <strong>the</strong> data grid and view, check-out or check-in <strong>the</strong> selecteddocument. In addition, user will be able <strong>to</strong> upload a new file from his local hard drive. We areinterested in content only, so no metadata discussion.The following diagram shows our simple user interface:UCF APPLETEDIT CHECKOUT CHECKINGRIDVIEW CONTROLFILE INPUT CONTROLHIDDEN FIELDS CONTROLSExcept <strong>the</strong> UCF applet, all o<strong>the</strong>r controls are standard ASP .NET controls. Grid view control will beused <strong>to</strong> display a list of documents and process row selection. View, Checkout and Checkin but<strong>to</strong>nswill be used <strong>to</strong> execute <strong>the</strong> corresponding action on <strong>the</strong> document. File input control will be used <strong>to</strong> let<strong>the</strong> user import a file. Hidden field controls will be used <strong>to</strong> s<strong>to</strong>re some values required <strong>to</strong> properlyinitialize <strong>the</strong> content transfer in <strong>the</strong> back-end code.Our client browser will be IE 6 with Sun Java Version 6 Update 14.


Now that our applet can successfully initialize, it is time <strong>to</strong> enhance <strong>the</strong> .NET application. Let us add<strong>the</strong> necessary controls and integrate with DFS. We will be using <strong>the</strong> productivity layer.ASP .NET ApplicationDocument Listing ComponentFirst we will add code <strong>to</strong> display a list of documents in <strong>the</strong> Gridview control. The updated .aspx pagewill look like this:UCF and DFS Integration//called from <strong>the</strong> applet <strong>to</strong> set <strong>the</strong> valuesfunction initUcf(ucfId,jsessionId){alert('in ucf init, ucId is: ' + ucfId + ', jsessionid is: ' + jsessionId);}The code behind page will bind <strong>the</strong> Gridview <strong>to</strong> <strong>the</strong> list of DocumentInfo objects:


public partial class _Default : System.Web.UI.Page{public string SelectedObjectId{get { return ViewState["selectedObjectId"] != null ?(string)ViewState["selectedObjectId"] : null; }set { ViewState["selectedObjectId"] = value; }}protected void Page_Load(object sender, EventArgs e){if (!IsPostBack){DocumentHelper helper = new DocumentHelper();List docs = helper.GetDocuments();DocumentsGridView.DataSource = docs;DocumentsGridView.DataBind();}}}protected void DocumentsGridView_SelectedIndexChanged(object sender, EventArgs e){String objectId = DocumentsGridView.SelectedRow.Cells[0].Text;SelectedObjectId = objectId;}The SelectedIndexChanged method keeps track of <strong>the</strong> currently selected row and s<strong>to</strong>res <strong>the</strong> object idin <strong>the</strong> ViewState cache. We will need this object id later during view / checkout functionality.DocumentInfo is a simple data model class:public class DocumentInfo{public string ObjectId { get; set;}public string DocumentName { get; set; }public string LockOwner { get; set; }}public DocumentInfo(){}Finally, <strong>the</strong> DocumentHelper is a utility class that integrates with <strong>the</strong> DFS query service:public List GetDocuments(){List documents = new List();IServiceContext context = ConfigUtil.GetDfsServiceContext();IQueryService querySvc =ServiceFac<strong>to</strong>ry.Instance.GetRemoteService(context, "core",ConfigUtil.DfsServerUri);PassthroughQuery query = new PassthroughQuery();


query.QueryString = "select r_object_id, object_name, r_lock_owner from dm_documentwhere object_name like '%Template%'";query.AddReposi<strong>to</strong>ry(ConfigUtil.DefaultReposi<strong>to</strong>ry);QueryExecution queryEx = new QueryExecution();queryEx.CacheStrategyType = CacheStrategyType.DEFAULT_CACHE_STRATEGY;OperationOptions operationOptions = null;QueryResult queryResult = querySvc.Execute(query, queryEx,operationOptions);DataPackage resultDp = queryResult.DataPackage;List dataObjects = resultDp.DataObjects;foreach (DataObject dObj in dataObjects){PropertySet docProperties = dObj.Properties;String objectId = dObj.Identity.GetValueAsString();String name = docProperties.Get("object_name").GetValueAsString();String lockedBy = null;Property lockOwner = docProperties.Get("r_lock_owner");if (lockOwner != null){lockedBy = lockOwner.GetValueAsString();}}DocumentInfo a1 = new DocumentInfo();a1.ObjectId = objectId;a1.DocumentName = name;a1.LockOwner = lockedBy;documents.Add(a1);}return documents;The ConfigUtil is a class with some utility methods / properties:public class ConfigUtil{public ConfigUtil(){}public static string DfsServerUri{get{string dfsServerUri = System.Configuration.ConfigurationManager.AppSettings["dfsServerUri"];return dfsServerUri;}}public static string DefaultReposi<strong>to</strong>ry{get{string repo = System.Configuration.ConfigurationManager.AppSettings["defaultReposi<strong>to</strong>ry"];return repo;}}public static string TestUser{


get{string user = System.Configuration.ConfigurationManager.AppSettings["testUser"];return user;}}public static string TestUserPassword{get{string password = System.Configuration.ConfigurationManager.AppSettings["testUserPassword"];return password;}}public static IServiceContext GetDfsServiceContext(){IServiceContext context = ContextFac<strong>to</strong>ry.Instance.NewContext();context.AddIdentity(new Reposi<strong>to</strong>ryIdentity(DefaultReposi<strong>to</strong>ry, TestUser, TestUserPassword, ""));return context;}}The application’s web.config file contains <strong>the</strong> following cus<strong>to</strong>m entries:TIP: There are additional required configuration settings <strong>to</strong> configure DFS services. Please take alook at <strong>the</strong> full web.config provided as part of <strong>the</strong> Visual Studio Solution sample code and/or consult<strong>the</strong> DFS Development Guide.TIP: The query will try <strong>to</strong> read contents of <strong>the</strong> /Templates cabinet. Make sure <strong>the</strong> test user you areusing has proper access permissions on that cabinet.The final display should look something like this:


Page PostBack and Browser Refresh ProblemThis is where things start <strong>to</strong> get interesting. Try <strong>to</strong> select one or two documents and moni<strong>to</strong>r <strong>the</strong> JavaConsole. You will get an error like this:Exception in thread "Thread-1" com.documentum.ucf.common.transport.TransportError:com.documentum.ucf.common.transport.TransportStreamException: Unrecoverable stream error: HTTP session is notproperly initializedat com.documentum.ucf.client.transport.impl.ClientSession.run(ClientSession.java:420)Caused by: com.documentum.ucf.common.transport.TransportStreamException: Unrecoverable stream error: HTTPsession is not properly initializedat com.documentum.ucf.client.transport.impl.ClientReceiver.getRequests(ClientReceiver.java:53)at com.documentum.ucf.client.transport.impl.ClientSession.handshake(ClientSession.java:621)at com.documentum.ucf.client.transport.impl.ClientSession.handshake(ClientSession.java:600)at com.documentum.ucf.client.transport.impl.ClientSession.run(ClientSession.java:214)-1; Handshake failed…What happened? Clicking “Select” will cause <strong>the</strong> ASP .NET <strong>to</strong> post <strong>the</strong> page back <strong>to</strong> <strong>the</strong> server. Afterserver processing is complete, <strong>the</strong> page will be rendered again. Second time it renders, <strong>the</strong> applet willtry <strong>to</strong> reinitialize again. The init() method will be called and <strong>the</strong> applet will try <strong>to</strong> start ano<strong>the</strong>r


UcfConnection. However, because this is <strong>the</strong> same HttpSession initialized previously, <strong>the</strong> code willfail.You can observer <strong>the</strong> same behavior just by clicking F5 (Refreshing <strong>the</strong> browser page).After <strong>the</strong> above exception is thrown, <strong>the</strong> process is broken (in addition, <strong>the</strong> code itself is veryinefficient - we do not want <strong>to</strong> start new UcfConnections on every postback). Depending on yourrequirements, <strong>the</strong>re are few things you can do here.Frame ApproachOne way <strong>to</strong> fix this is <strong>to</strong> move <strong>the</strong> applet <strong>to</strong> a separate outer frame and include <strong>the</strong> .NET page insidea separate frame. This way, <strong>the</strong> applet will stay loaded and .NET postbacks will resubmit only <strong>the</strong>inner frame. The UcfConnection will be established only once and <strong>the</strong> process will be very efficient.The outer frame will look like this:DFS and UCF Integration//called from <strong>the</strong> applet <strong>to</strong> set <strong>the</strong> valuesfunction initUcf(ucfId,jsessionId){alert('in ucf init, ucId is: ' + ucfId + ', jsessionid is: ' + jsessionId);}The Deafult.aspx page stays <strong>the</strong> same as before just without <strong>the</strong> applet.TIP: Frame approach with a combination of cookies (more on this later) is <strong>the</strong> approach we arecurrently using. One problem we encountered was that our application had <strong>to</strong> be invoked withcertain URL parameters passed <strong>to</strong> it. This meant that <strong>the</strong> outer frame page had <strong>to</strong> propagate <strong>the</strong>sedown <strong>to</strong> <strong>the</strong> Default.aspx page. You can accomplish this using <strong>the</strong> asp literal control.


For example, instead of iframe tag in <strong>the</strong> outer .aspx page, you would have something like this:……Then in <strong>the</strong> code behind class do something like this:public partial class Outter : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){string url = Request.Url.ToString();int paramStart = url.IndexOf("?");string newPrams = url.Substring(paramStart);LiteralFrame.Text = "";}}While <strong>the</strong> frame approach fixes <strong>the</strong> postback problem, <strong>the</strong> issue of <strong>the</strong> browser refresh still remains.The browser refresh will cause both frames <strong>to</strong> reload and <strong>the</strong> UcfConnection would fail <strong>to</strong> initialize.To make things worse, if <strong>the</strong> user navigates away <strong>to</strong> a different page (one without <strong>the</strong> applet) and<strong>the</strong>n revisits <strong>the</strong> applet page, same exception will happen.Using cookies and “rebinding” UcfConnection can help us solve this issue.Cookie ApproachIf you look at <strong>the</strong> construc<strong>to</strong>rs of <strong>the</strong> UcfConnection class, notice <strong>the</strong>re are two – one takes just <strong>the</strong>DFS server URL as a parameter, while <strong>the</strong> o<strong>the</strong>r one takes in jsessionId and deploymentId as well.For example, if we know <strong>the</strong> jsessionId, we can open a new UcfConnection as follows:UcfConnection conn = new UcfConnection(new URL("http://soulshaker:7777/"),jsessionId, deploymentId);If <strong>the</strong> connection is established this way, <strong>the</strong> exception will not be thrown. So, we will modify <strong>the</strong>behavior of our applet – initially it will establish a regular UcfConnection using just <strong>the</strong> URL in <strong>the</strong>construc<strong>to</strong>r. We will <strong>the</strong>n obtain <strong>the</strong> jsessionId and s<strong>to</strong>re it as a cookie. Any possible subsequent calls<strong>to</strong> initialize <strong>the</strong> applet will first check if <strong>the</strong> cookie exist, and if so, rebind <strong>the</strong> UcfConnection <strong>to</strong> <strong>the</strong>same HttpSession (identified by <strong>the</strong> jsessionId). Here is <strong>the</strong> modified applet init method code:public void init() {System.out.println("Cookie applet init()...");jsessionId = getCookie();System.out.println("read cookie jsession id as: " + jsessionId);if (jsessionId == null) {System.out.println("NO JSESSIONID COOKIE FOUND, starting NEW CONNECTION");


try {conn = new UcfConnection(new URL("http://soulshaker:7777/"));jsessionId = conn.getJsessionId();ucfId = conn.getUid();deploymentId = conn.getTargetDeploymentId();System.out.println("jsessionId=" + jsessionId + ", uid="+ ucfId);addCookie(jsessionId);System.out.println("added cookie");} catch (Exception e) {e.printStackTrace();}} else {System.out.println("FOUND jsession ID in cookie as: " + jsessionId);System.out.println("trying <strong>to</strong> reuse <strong>the</strong> connection with <strong>the</strong> old jsession id");try {conn = new UcfConnection(new URL("http://soulshaker:7777/"),jsessionId, deploymentId);}} catch (MalformedURLException e) {e.printStackTrace();} catch (UcfException e) {e.printStackTrace();}}// finally, pass <strong>the</strong> values <strong>to</strong> <strong>the</strong> asp .net pageJSObject win = JSObject.getWindow(this);win.call("initUcf", new Object[] { ucfId, jsessionId });The getCookie() and addCookie() are simple helper methods that use JavaPlugin <strong>to</strong> add/read cookiesfrom within <strong>the</strong> applet. Here is <strong>the</strong> example code:public void addCookie(String cookieValue) {JSObject myBrowser = JSObject.getWindow(this);JSObject myDocument = (JSObject) myBrowser.getMember("document");myDocument.setMember("cookie", cookieValue);}public String getCookie() {try {JSObject myBrowser = (JSObject) JSObject.getWindow(this);JSObject myDocument = (JSObject) myBrowser.getMember("document");String myCookie = (String) myDocument.getMember("cookie");if (myCookie != null && myCookie.length() > 0)return myCookie;} catch (Exception e) {e.printStackTrace();}return null;}IMPORTANT: It is important <strong>to</strong> realize that recreating and rebinding <strong>the</strong> UcfConnection this way stillspawns ano<strong>the</strong>r javaw.exe process on <strong>the</strong> client machine. If you keep refreshing <strong>the</strong> page whilemoni<strong>to</strong>ring <strong>the</strong> running processes on <strong>the</strong> client machine, you will notice this. The connectionseventually do time out and <strong>the</strong> processes terminate. In our case, this behavior was acceptable as


<strong>the</strong> browser refresh case (or <strong>the</strong> case where <strong>the</strong> user navigates away <strong>the</strong>n comes back <strong>to</strong> <strong>the</strong>applet page) are extremely rare. Your requirements might be different, so be careful.Finally, as will be discussed later, we will be setting <strong>the</strong> Au<strong>to</strong>CloseConnection parameter of <strong>the</strong>ActivityInfo object <strong>to</strong> false. This allows us <strong>to</strong> reuse <strong>the</strong> UcfConnection multiple times. Ideally, weshould be manually closing <strong>the</strong> connection. Applets have a s<strong>to</strong>p() method called right before JVMshuts down – this appeared like a perfect place for us <strong>to</strong> close <strong>the</strong> connection. Unfortunately, <strong>the</strong>following throws an IOException:public void s<strong>to</strong>p() {System.out.println("closing connection");conn.closeConnection();super.s<strong>to</strong>p();}This article will be updated if a proper way <strong>to</strong> manually close <strong>the</strong> connection is discovered.Please email <strong>the</strong> author if you have ideas regarding this issue.Separate Window ApproachWhile this approach is not discussed in this article, if your requirements allow it, you could alwaysopen an additional window that would hold <strong>the</strong> applet. You could add a statment like “Please do notclose or refresh this window while your session is in progress”.View Document ExampleAt this point, we should have a stable applet that retrieves <strong>the</strong> required jsessionId and ucfIdparameters and passes it <strong>to</strong> a JavaScript function initUcf, which will s<strong>to</strong>re <strong>the</strong>se values using hiddenfields.First, add <strong>the</strong> hidden field controls <strong>to</strong> your Default.aspx page (page containing <strong>the</strong> data grid):Next, update <strong>the</strong> initUcf function in <strong>the</strong> Outter.aspx. Remember, <strong>the</strong> applet is contained on <strong>the</strong> outerframe, so <strong>the</strong> JavaScript will have <strong>to</strong> access <strong>the</strong> fields from <strong>the</strong> Doclist.aspx inner frame ://called from <strong>the</strong> applet <strong>to</strong> set <strong>the</strong> valuesfunction initUcf(ucfId,jsessionId){alert('in ucf init, ucId is: ' + ucfId + ', jsessionid is: ' + jsessionId);//get <strong>the</strong> frame and <strong>the</strong> <strong>to</strong>p form in <strong>the</strong> framevar <strong>to</strong>pFrame = window.frames['mainFrame'];var <strong>to</strong>pFrameForm = <strong>to</strong>pFrame.document.getElementById("form1");//set <strong>the</strong> values of hidden fields on <strong>the</strong> included page<strong>to</strong>pFrameForm.UcfIdText.value = ucfId;<strong>to</strong>pFrameForm.JsessionIdText.value = jsessionId;}


The utility methods of <strong>the</strong> ConfigUtil used in <strong>the</strong> above code are implemented as follows:public static ContentTransferProfile GetUcfContentTransferProfile(string jsessionId, string ucfId){ActivityInfo activityInfo = GetActivityInfo(jsessionId, ucfId);ContentTransferProfile ctProfile = new ContentTransferProfile();ctProfile.TransferMode = ContentTransferMode.UCF;ctProfile.AllowCachedContentTransfer = true;ctProfile.transferModeSpecified = true;ctProfile.ActivityInfo = activityInfo;return ctProfile;}Notice that we set <strong>the</strong> Au<strong>to</strong>CloseConnection parameter of <strong>the</strong> ActivityInfo object <strong>to</strong> false in order <strong>to</strong> beable <strong>to</strong> reuse <strong>the</strong> UcfConnections in <strong>the</strong> applet.public static ActivityInfo GetActivityInfo(string jsessionId, string ucfId){ActivityInfo activityInfo = new ActivityInfo();activityInfo.ActivityId = ucfId;activityInfo.SessionId = jsessionId;activityInfo.Au<strong>to</strong>CloseConnection = false;return activityInfo;}public static ObjectIdentitySet GetObjectIdentitySet(String objectId){return new ObjectIdentitySet(GetObjectIdentity(objectId));}public static ObjectIdentity GetObjectIdentity(String objectId){return new ObjectIdentity(new ObjectId(objectId), DefaultReposi<strong>to</strong>ry);}Checkout Document ExampleCheckout is implemented in a similar way. Here is <strong>the</strong> implementation in <strong>the</strong> DocumentHelper:public void CheckoutDocument(string objectId, string jsessionId, string ucfId){//sanity check for <strong>the</strong> argumentsif (string.IsNullOrEmpty(objectId))throw new Exception("viewdocument, objectId is null");if (string.IsNullOrEmpty(jsessionId))throw new Exception("viewdocument, jsessionId is null");if (string.IsNullOrEmpty(ucfId))throw new Exception("viewdocument, ucfId is null");IServiceContext context = ConfigUtil.GetDfsServiceContext();IVersionControlService versionService =ServiceFac<strong>to</strong>ry.Instance.GetRemoteService(context, "core", ConfigUtil.DfsServerUri);ContentTransferProfile ctProfile = ConfigUtil.GetUcfContentTransferProfile(jsessionId, ucfId);//set <strong>the</strong> content transfer profile on <strong>the</strong> operationOperationOptions operationOptions = new OperationOptions();operationOptions.ContentTransferProfile = ctProfile;//set <strong>the</strong> content transfer profile on <strong>the</strong> contextcontext.SetProfile(ctProfile);


set <strong>the</strong> dfs content profile <strong>to</strong> editContentProfile contentProfile = new ContentProfile();contentProfile.FormatFilter = FormatFilter.ANY;contentProfile.PostTransferAction = "dfs:edit";operationOptions.ContentProfile = contentProfile;}versionService.Checkout(ConfigUtil.GetObjectIdentitySet(objectId), operationOptions);Checkin Document ExampleCheckin is also very similar. Notice how we do NOT specify <strong>the</strong> location of <strong>the</strong> actual content itself,only <strong>the</strong> object id. The DFS and UCF integration is smart enough <strong>to</strong> properly resolve this based on<strong>the</strong> object id (i.e. it will check <strong>the</strong> registry and obtain <strong>the</strong> exact location where <strong>the</strong> document waspreviously checked out). This will work properly even in <strong>the</strong> cases where <strong>the</strong> document was renamedwith a suffix (i.e. testdoc_01.doc) – this happens if a resource with a same name is already checkedout.public void CheckingDocument(string objectId, string jsessionId, string ucfId){//sanity check for <strong>the</strong> argumentsif (string.IsNullOrEmpty(objectId))throw new Exception("viewdocument, objectId is null");if (string.IsNullOrEmpty(jsessionId))throw new Exception("viewdocument, jsessionId is null");if (string.IsNullOrEmpty(ucfId))throw new Exception("viewdocument, ucfId is null");IServiceContext context = ConfigUtil.GetDfsServiceContext();IVersionControlService versionService =ServiceFac<strong>to</strong>ry.Instance.GetRemoteService(context, "core", ConfigUtil.DfsServerUri);//set <strong>the</strong> UCF content transfer profile on contextContentTransferProfile ctProfile = ConfigUtil.GetUcfContentTransferProfile(jsessionId, ucfId);context.SetProfile(ctProfile);//set <strong>the</strong> UCF content transfer profile on <strong>the</strong> opsOperationOptions operationOptions = new OperationOptions();operationOptions.ContentTransferProfile = ctProfile;CheckinProfile checkinProfile = new CheckinProfile();checkinProfile.DeleteLocalFileHint = true;checkinProfile.MakeCurrent = true;operationOptions.CheckinProfile = checkinProfile;//set <strong>the</strong> dfs content profile <strong>to</strong> generic (i.e. no post view / post edit action)ContentProfile contentProfile = new ContentProfile();contentProfile.FormatFilter = FormatFilter.ANY;operationOptions.ContentProfile = contentProfile;DataObject dataObject = new DataObject(ConfigUtil.GetObjectIdentity(objectId));DataPackage dataPackage = new DataPackage(dataObject);}versionService.Checkin(dataPackage, VersionStrategy.SAME_VERSION, false, null, operationOptions);


Import Document ExampleTo allow document import, first add <strong>the</strong> file input control and a new upload file but<strong>to</strong>n controls <strong>to</strong> yourASP .NET page:Implemented <strong>the</strong> method handler for <strong>the</strong> upload but<strong>to</strong>n:protected void UploadDocument_Click(object sender, EventArgs e){//this assumes <strong>the</strong> user selected a row in <strong>the</strong> data grid first//get <strong>the</strong> values of <strong>the</strong> hidden fieldsstring jsessionId = JsessionIdText.Value;string ucfId = UcfIdText.Value;string filePath = FileToUpload.PostedFile.FileName;}DocumentHelper docHelper = new DocumentHelper();docHelper.UploadDocument(filePath, jsessionId, ucfId);And finally, here is <strong>the</strong> actual UploadDocument method on <strong>the</strong> handler. Notice that <strong>the</strong> code is a bitsimplified – it will always create <strong>the</strong> document and name it “DFS and UCF Imported Document” as aPDF document.public void UploadDocument(string filePath, string jsessionId, string ucfId){//sanity check for <strong>the</strong> argumentsif (string.IsNullOrEmpty(filePath))throw new Exception("viewdocument, objectId is null");if (string.IsNullOrEmpty(jsessionId))throw new Exception("viewdocument, jsessionId is null");if (string.IsNullOrEmpty(ucfId))throw new Exception("viewdocument, ucfId is null");IServiceContext context = ConfigUtil.GetDfsServiceContext();ContentTransferProfile ctProfile = ConfigUtil.GetUcfContentTransferProfile(jsessionId, ucfId);context.SetProfile(ctProfile);ServiceFac<strong>to</strong>ry serviceFac<strong>to</strong>ry = ServiceFac<strong>to</strong>ry.Instance;IObjectService objectService = serviceFac<strong>to</strong>ry.GetRemoteService(context, "core",ConfigUtil.DfsServerUri);// DEFINE new documentObjectIdentity documentId = new ObjectIdentity(ConfigUtil.DefaultReposi<strong>to</strong>ry);DataObject documentObject = new DataObject(documentId, "dm_document");documentObject.Properties.Set("object_name", "DFS and UCF Imported Document");// ADD <strong>the</strong> folder ReferenceRelationship - we are saving in <strong>the</strong> Temp folderObjectPath objectPath = new ObjectPath("/Temp");ObjectIdentity folderIdentity = new ObjectIdentity(objectPath, ConfigUtil.DefaultReposi<strong>to</strong>ry);ReferenceRelationship folderRelationship = new ReferenceRelationship();folderRelationship.Name = Relationship.RELATIONSHIP_FOLDER;folderRelationship.Target = folderIdentity;folderRelationship.TargetRole = Relationship.ROLE_PARENT;


documentObject.Relationships.Add(folderRelationship);//only support pdf types. you will need <strong>to</strong> add some sort of format recognizer//configuration settings <strong>to</strong> determine <strong>the</strong> documentum content type depending//on <strong>the</strong> submited file (i.e. if file extension = doc, dctmcontent type = msw8 etc)String dctmContentType = "pdf";// ADD UCF content <strong>to</strong> documentUcfContent ucfContent = new UcfContent(filePath, dctmContentType);documentObject.Contents.Add(ucfContent);objectService.Create(new DataPackage(documentObject), new OperationOptions());}ConclusionHopefully this article shed some light on <strong>the</strong> required orchestration of events that need <strong>to</strong> happen for<strong>the</strong> DFS and UCF integration.Email <strong>the</strong> author at mirza.fazlic@gmail.com with any comments and suggestions.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!