dinsdag 4 september 2012

Change ContentType and Metadata of your Documents uploaded in a Sharepoint Library


This part for updating a sharepoint contentType for a uploaded Document in a SharePoint Library.
So Once you have uploaded a File into a SharePoint Library, you needs it's ID for changing the
metadata or contentType of a Document.
So first of all call my function below for getting the ID.

    //Call to the function to get the ID
    string sID = sGetID(sSiteUrl, sSiteList, sFileName);
    private string sGetID(string sURL, string sListName, string sFileName) 
    {
        string sID = "";
        SPListsService.Lists list = new SPListsService.Lists();
        list.Url = sSiteUrl + "/_vti_bin/lists.asmx";
  // I have a common Boolean field for determing if I use the current logged on user or to use a Technical User. 
  // attention !!!! The user must have access to your Sharepoint environment.
        if (bDefaultLogon)
            list.Credentials = System.Net.CredentialCache.DefaultCredentials;
        else
        {
            list.PreAuthenticate = true;
            list.Credentials = new System.Net.NetworkCredential(sTechnicalUser, sTechnicalPw, sTechnicalDomain);
        }
        try
        {
   string rowLimit = "99999";
            XmlDocument xmlDoc = new System.Xml.XmlDocument();
            XmlNode listQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
            listQuery.InnerXml = "" + sFileName + "";
            listQuery.InnerXml = listQuery.InnerXml + "\"";
            XmlNode listViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
            listViewFields.InnerXml = "" +
                                      "";
            XmlNode listQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");
            listQueryOptions.InnerXml = "";
            XmlNode ndListItems = null;
            Guid g = GetWebID(sSiteUrl); // Function to get the ID of your Web
            ndListItems = list.GetListItems(sSiteList, null, listQuery, listViewFields, rowLimit, listQueryOptions, g.ToString());
            sID = ndListItems.ChildNodes[1].ChildNodes[1].Attributes["ows_ID"].Value;
        }
        catch { }
        finally {
           list.Dispose();
        }
        return sID;
    }    
    /* -- Get the Guid of your List  -- */
    private Guid GetWebID(string webPath)
    {
        SPSiteDataService.SiteData siteDataWS = new SPSiteDataService.SiteData();
        if (bDefaultLogon)
            siteDataWS.Credentials = System.Net.CredentialCache.DefaultCredentials;
        else
        {
            siteDataWS.PreAuthenticate = true;
            siteDataWS.Credentials = new System.Net.NetworkCredential(sTechnicalUser, sTechnicalPw, sDomain);
        }
        SPSiteDataService._sWebMetadata webMetaData;
        SPSiteDataService._sWebWithTime[] arrWebWithTime;
        SPSiteDataService._sListWithTime[] arrListWithTime;
        SPSiteDataService._sFPUrl[] arrUrls;
        string roles; string[] roleUsers; string[] roleGroups;
        siteDataWS.Url = webPath + "/_vti_bin/sitedata.asmx";
        uint i = siteDataWS.GetWeb(out webMetaData, out arrWebWithTime, out arrListWithTime, out arrUrls, out roles, out roleUsers, out roleGroups);
        Guid g = new Guid(webMetaData.WebID);
        return g;
    }
 
 


My Code below will change the ContentType of your Document and also some extra Metadata. 
Now it is posible that you would not want to change the ContentType,
 so if not, put the call in comment.
The reason why you need the change of your ContentType and 
the rest of your Metadata in a different XML update block
is because by changing the ContentType, other Columns/MetaData becomes at your position, 
as examle your colums that you have created in your ContentType 
are not at your position before you have changed your ContentType. 
Only the default Columns are available.


    // Call to the function for update file metadate
 bool ret = UpdateFileDataViaBatch(sID, sSiteUrl, sSiteList, Array_FileMetaData);   

 /* --  Update File columns in Sharepoint List-- */
    private Boolean UpdateFileDataViaBatch(string sId, string sSiteUrl, string sSiteList, DataTable ExtraFileMetaData)
    {
        Boolean retcode = true;
        XmlDocument xmlDoc = new XmlDocument();
        XmlElement elBatch = xmlDoc.CreateElement("Batch");
        elBatch.SetAttribute("OnError", "Continue");
        elBatch.SetAttribute("ViewName", GetViewId(sSiteUrl, sSiteList, ""));
        try
        {
            string strBatch = "";
            int id = 0;
            if (ExtraFileMetaData.Rows.Count > 0)
            {
                DataRow drFileInfo = ExtraFileMetaData.Rows[0];
    // call for creating your xml-element for changing the contentType... If you don't need to change it, put it in comment
                strBatch = changeContentType(id,drFileInfo,  sId);
    // call for creating you xml-element for updating your document with extra info.
                strBatch = strBatch + createXmlUpdateBatch(++id, drFileInfo, sId);
            }
            elBatch.InnerXml = strBatch;
            Boolean retcodeUpdSPList = UpdateSPList(sSiteUrl, sSiteList, elBatch);
        }
        catch { }
        return retcode;
    }

    private string changeContentType(int id, DataRow drFileInfo, string sID)
    {
        String strBatch = "";
        strBatch = strBatch + "";
        strBatch = strBatch + "" + sID + "";
        strBatch = strBatch + "" + replaceSpecialChars(drFileInfo["ContentType"].ToString()) + "";
        strBatch = strBatch + "";
        return strBatch;
    }
    private string createXmlUpdateBatch(int id,  DataRow drFileInfo, string sID)
    {
        String strBatch = "";
        strBatch = strBatch + "";
        strBatch = strBatch + "" + sID + "";
        strBatch = strBatch + "" + replaceSpecialChars(drFileInfo["ExtraFileMetaData1"].ToString()) + "";
        strBatch = strBatch + "" + replaceSpecialChars(drFileInfo["ExtraFileMetaData2"].ToString()) + "";
        strBatch = strBatch + "";
        return strBatch;
    }

    private string replaceSpecialChars(string mystring)
    {
        mystring = mystring.Replace("&", "&");
        mystring = mystring.Replace("<", "<");
        mystring = mystring.Replace(">", ">");
        mystring = mystring.Replace("\"", """);
        mystring = mystring.Replace("'", "'");
        return mystring;
    }

 
 

At least you also need the function for the real update... 
otherwise you have your batch XML document, 
but your data isn't updated yet.
So you also need my function below for executing your 
Batch Element by using the Lists.asmx webservice.


 /* -- Update SharePoint List -- */
    private Boolean UpdateSPList(string sSiteUrl, string sSiteList, XmlElement elBatch)
    {
        Boolean retcode = true;
        SPListsService.Lists list = new SPListsService.Lists();
        list.Url = sSiteUrl + "/_vti_bin/lists.asmx";
        if (bDefaultLogon)
            list.Credentials = System.Net.CredentialCache.DefaultCredentials;
        else
        {
            list.PreAuthenticate = true;
            list.Credentials = new System.Net.NetworkCredential(sTechnicalUser, sTechnicalPw, sDomain);
        }
        try
        {
            XmlNode ndReturn = list.UpdateListItems(sSiteList, elBatch);
            // Instantiate a new XML document object to hold the return value(s) 
            XmlDocument xmlResult = new XmlDocument();
            xmlResult.LoadXml(ndReturn.OuterXml);
            // SharePoint XML always uses a fixed namespace; you'll need your own NamespaceManager object to parse the return values 
            XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlResult.NameTable);
            nsMgr.AddNamespace("sp", ndReturn.NamespaceURI);
            XmlNode ndRoot = xmlResult.SelectSingleNode("sp:Results", nsMgr);
            // Find the ErrorCode node, which exists for all operations regardless of status. 
            XmlNodeList nlResults = ndRoot.SelectNodes("//sp:Result/sp:ErrorCode", nsMgr);
            // Loop through the node collection and find each ErrorCode entry 
            foreach (XmlNode ndResult in nlResults)
            {
                // Check the value of the node to determine its status 
                if (ndResult.InnerText != "0x00000000")
                {
                    XmlNode ndError = ndResult.NextSibling;
                    string sError = ndError.InnerText;
                    // Set the value of string variable to hold the error code 
                    // If you want to trip the Try…Catch, throw and exception of whatever type suits you 
                }
                else
                {
                    // put your code on success... whatever you want 
                }
            }
        }
        catch (Exception e)
        {
            retcode = false;
        }
        finally
        {
            list.Dispose();
        }
        return retcode;
    }
 
 
 

If you have questions, don't hesitate to contact me... 
I only use the webservices to be undependent of the environment
to run the code on... So it hasn't to be on a sharepoint Environment !
If there are problems with my code, please let me know... 

Geen opmerkingen:

Een reactie posten