-->

21/11/2012

Uploading Documents Programatically to a Content Organizer Enabled Site

We have covered Content Organizer / Metadata Routing in SP2010 in earlier post.
We have created all the required infrastructure for meta data routing or Content organizing. So only task remining is uploading the documents.
Well ! we cannot ask the users to navigate to Drop Off library and upload their documents. Right?
So i have created a simple Webpart for uploading the documents for the specific content type.
 Now we need to upload the selected files programatically to Drop Off Library.
Below is the code written by me for uplaoding the file to DropOff Library of the respective site.
 
private void UploadFromFileControl(FileUpload fuFile,string description)
        {
            using (SPWeb objWeb = SPContext.Current.Site.OpenWeb())
            {
                objWeb.AllowUnsafeUpdates = true;
                
                SPFolder myLibrary = objWeb.Folders["DropOffLibrary"];
                Boolean replaceExistingFiles = true;
                String fileName = System.IO.Path.GetFileName(fuFile.PostedFile.FileName);
                Int32 fileLen = fuFile.PostedFile.ContentLength;
                Byte[] Input = new Byte[fileLen];
                Stream fileStream = fuFile.FileContent;
                fileStream.Read(Input, 0, fileLen);
                SPFile spFile = myLibrary.Files.Add(Path.GetFileName(fuFile.PostedFile.FileName), fileStream, replaceExistingFiles);

                SPListItem spListItem = spFile.ListItemAllFields;
                spListItem["ContentType"] = objWeb.ContentTypes["CntUploadedDocs"];
                spListItem["CandidateId"] = CandidateId;
                spListItem["Relationship"] = ddlRelation.Items[ddlRelation.SelectedIndex].Value.ToString();
                spListItem["DocumentType"] = ddlDocumentType.Items[ddlDocumentType.SelectedIndex].Value.ToString();
                spListItem["Description"] = description;
                spListItem.Update();
                spFile.Update();
            }
        }
Result: Code executed perfectly, and the Document is uploaded to DropOff Library. I opened the DropOff  library and the record is successfully added. Task Acomplished?

No! Our task is not to add the document to DropOff library. Automatically it has to be moved from DropOff library to destination Library by Content organizer. But why it is still waiting there. Then i came across a stunning fact that . . .
Content Organizer Rules will not be triggered for Documents added to DropOff Library Programatically
Now i went to Content Organizer settings and copied the webservice Url at the bottom.
Usually it ends with "/vti_bin/OfficialFile.asmx".
Reffered the web service in my visual studio solution with name "FileUploadSvc".
Obviously you will end up writing code using "SPFile", "SPListItem" and "FileUploadSvcSoapClient".
It is a tedious process of doing so, but later i realized that reffering OfficialFile.asmx will create a Circualr refrence issue.
Reason being, the web service url has to be used for configuring  "SendTo" connections in Central Admin for access from other sites. Not for refering in your own website.

Now, i end up with a big question . .

How to Upload Documents to Content Organizer Enabled Site Programtically and make the Content Oragnizer rule trigger automatically?
Here is the answer . . . Microsoft.Office.Policy.dll 
Add this dll to your solution, and use "Microsoft.Office.RecordsManagement.RecordsRepository.dll" in your class file.

Doing so, you can access a class called "OfficialFileCore"  which will reffer the OfficialFile.asmx webservice by default. Try browsing the webservice and see what are the methods available.

Look at th last method, "SubmitFile". That is the method we need to use and MSDN has lot of information to offer about syntax and other stuff.
Microsoft link talking about Syntax.
Now i changed the code of my usercontrol to :
        
private void UploadFromFileControl(FileUpload fuFile,string description)
        {
            using (SPWeb objWeb = SPContext.Current.Site.OpenWeb())
            {               
                try
                {
                    string destination = null;
                    String fileName = System.IO.Path.GetFileName(fuFile.PostedFile.FileName);
                    Int32 fileLen = fuFile.PostedFile.ContentLength;
                    Byte[] Input = new Byte[fileLen];
                    Stream fileStream = fuFile.FileContent;
                    fileStream.Read(Input, 0, fileLen);

                    List properties = new List();
    properties.Add(new Microsoft.SharePoint.RecordsRepositoryProperty() 
              { Name = "Name", Type = "Text", Value = fileName });
    properties.Add(new Microsoft.SharePoint.RecordsRepositoryProperty() 
              { Name = "CandidateId", Type = "Text", Value = CandidateId });
    properties.Add(new Microsoft.SharePoint.RecordsRepositoryProperty() 
              { Name = "Relationship", Type = "Text", Value = ddlRelation.Items[ddlRelation.SelectedIndex].Value.ToString() });
    properties.Add(new Microsoft.SharePoint.RecordsRepositoryProperty() 
              { Name = "DocumentType", Type = "Text", Value = ddlDocumentType.Items[ddlDocumentType.SelectedIndex].Value.ToString() });
   properties.Add(new Microsoft.SharePoint.RecordsRepositoryProperty() 
              { Name = "Description", Type = "Text", Value = description });
   properties.Add(new Microsoft.SharePoint.RecordsRepositoryProperty() 
              { Name = "ContentType", Type = "Text", Value = "CntUploadedDocs" });
   var result = OfficialFileCore.SubmitFile(objWeb, Input, properties.ToArray(), "CntUploadedDocs", fuFile.PostedFile.FileName, @"domain\pratap", false, out destination);

                }
                catch (Exception ex)
                {
                }
                
            }
        }

Before deploying the code, there is another step to perform to have a smooth execution.
Go to Site Actions > Site Permissions > Add the Current or Configured user  to this group.

If you havent done above action, you will not be able to add the records to any library and the SubmitFile method will return "NotFound" response back as a result of execution.

Deployed the solution and added the record again.
DropOff Library:
Destination Document Library:

Task Acomplished. We are able to Add / Upload document programatically to a Content Organizer enabled site.
Is it helpful for you? Kindly let me know your comments / Questions.

2 comments:

  1. is it available for client object model?

    ReplyDelete
  2. Thanks for the code.

    OfficialFileCore.SubmitFile() seems to be working fine and the file is getting copied to the destination library but the content organizer rule is not creating folders at the destination as defined in content organizer rules. I have enabled the option to "Automatically Create a folder for each unique value of a property" in the content organizer rules. Out of box, it is working as expected i.e. it is creating folders at destination and moving files inside the folder but it is not working programmatically.

    Can you suggest what could be going wrong?

    ReplyDelete