示例#1
0
 static void Main(string[] args)
 {
     //clean up. Take out try catch here and put it in HandleSalesforceAttachment
     try
     {
         log4net.Config.XmlConfigurator.Configure();
         HandleSalesForceAttachmentAsync().Wait();
         Console.WriteLine("Process Complete");
     }
     catch (Exception ex)
     {
         SharedFunctionality.SendEmail("ERROR: Salesforce to Sharepoint process failed", ex.InnerException.Message);
         SharedFunctionality.Log(ex.ToString());
         Console.WriteLine("Error Occurred. Please check log for more details.");;
     }
 }
示例#2
0
 public MyClass2()
 {
     this.sharedFunctionality = new SharedFunctionality();
 }
示例#3
0
        private static async Task HandleSalesForceAttachmentAsync()
        {
            //log.Info("Starting Process");
            SharedFunctionality.Log("Starting Process");

            System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

            var authClient = await SharedFunctionality.CreateAuthClient();

            //build a KVP of RecordTypeId and Text description. Used to set metadata on uploaded file
            var contentArray = RecordTypeArray.Split('|');

            var contentTypeList = new List <KeyValuePair <string, string> >();

            var contactDocumentIdList = new List <string>();

            for (int x = 0; x < contentArray.Length; x++)
            {
                var array = contentArray[x].ToString().Split(',');
                contentTypeList.Add(new KeyValuePair <string, string>(array[0], array[1]));
            }

            using (var forceClient = SharedFunctionality.GetUserNamePasswordForceClientAsync(authClient))
            {
                //Get all ContentDocumentId's and put into a list for SOQL subquery as part of getting the ContectVersion
                var contactDocuments = await forceClient.QueryAsync <ContentDocumentLink>("SELECT ContentDocumentId, LinkedEntityId FROM ContentDocumentLink WHERE LinkedEntityId in (Select Id FROM Contact WHERE RecordTypeId in (" + SalesforceRecordTypeIdList + "))").ConfigureAwait(false);

                //Due to limitation of the Salesforce Query Language (SOQL) we cannot to a LIKE search on ParentId. We should only get Files for users
                //considered a CPS Contact, whose ID starts with 003
                var filteredDocList = contactDocuments.Records.FindAll(q => (q.LinkedEntityId.StartsWith("003")));

                //wrap ContentDocumentId's in single quotes, needed for subquery later on
                filteredDocList.ForEach(o => contactDocumentIdList.Add("'" + o.ContentDocumentId + "'"));

                SharedFunctionality.Log("total Contact Document IDs returned: " + filteredDocList.Count);

                //convert list to comma separated list
                var contactDocumentIdString = string.Join(",", contactDocumentIdList);

                var attachments = await forceClient.QueryAsync <SalesForce365Library.Models.Salesforce.Attachment>("SELECT id, Name, ParentId FROM Attachment WHERE ParentID in (Select Id FROM Contact WHERE RecordTypeId in (" + SalesforceRecordTypeIdList + ")) ORDER BY CreatedDate DESC LIMIT 1").ConfigureAwait(false);

                var files = await forceClient.QueryAsync <ContentVersion>("SELECT Id, VersionData, PathOnClient, ContentDocumentId FROM ContentVersion WHERE IsLatest = True AND ContentDocumentId IN (" + contactDocumentIdString + ")").ConfigureAwait(false);

                for (var x = 0; x < files.Records.Count; x++)
                {
                    var documentRecord = filteredDocList.Find(d => d.ContentDocumentId == files.Records[x].ContentDocumentId);

                    files.Records[x].ParentId = documentRecord.LinkedEntityId;
                }

                using (System.Net.WebClient wclient = new System.Net.WebClient())
                {
                    wclient.Headers.Add("Authorization: OAuth " + authClient.AccessToken);

                    try
                    {
                        //Create directory that we will download the files to. If it already exists, no action will be taken
                        Directory.CreateDirectory(DownloadedFilePath);
                    }
                    catch (Exception ex)
                    {
                        SharedFunctionality.Log("Error trying to create directory " + DownloadedFilePath);
                        SharedFunctionality.Log(ex.Message);
                        throw ex;
                    }

                    //Due to limitation of the Salesforce Query Language (SOQL) we cannot to a LIKE search on ParentId. We should only get attachments for users
                    //considered a CPS Contact, whose ID starts with 003
                    var filteredIdList = attachments.Records.FindAll(q => (q.ParentId.StartsWith("003")));

                    var mergedList = MergeFilesAttachments(filteredIdList, files, authClient);

                    SharedFunctionality.Log("Found " + mergedList.Count + " records.");

                    //Loop thru records to get body for each file. SF query limitation only returns one body at a time, so we need to make numerous http GET calls
                    for (int i = 0; i < mergedList.Count; i++)
                    {
                        try
                        {
                            SharedFunctionality.Log("Attachment for ID: " + mergedList[i].ParentId);

                            wclient.DownloadFile(mergedList[i].Uri, mergedList[i].FilePath);

                            using (ClientContext context = new ClientContext(SharepointUrl))
                            {
                                var securePwd = new SecureString();
                                foreach (char c in SharepointPassword.ToCharArray())
                                {
                                    securePwd.AppendChar(c);
                                }

                                context.Credentials = new SharePointOnlineCredentials(SharepointUser, securePwd);

                                //Get contact record to populate metadata
                                var contact = await forceClient.QueryAsync <Contact>("SELECT Birthdate,FirstName,LastName,RecordTypeId,Intake_Date__c FROM Contact WHERE Id = '" + mergedList[i].ParentId + "'");

                                //Program name = EOC/Talent Search/Upward Bound
                                var programName = contentTypeList.First(kvp => kvp.Key == contact.Records[0].RecordTypeId).Value;

                                var list = context.Web.Lists.GetByTitle(programName);

                                context.Load(list.RootFolder);
                                context.ExecuteQuery();

                                var folders = list.RootFolder.Folders;
                                context.Load(folders);
                                context.ExecuteQuery();
                                //only do this if the contact has an intake date
                                if (contact.Records[0].Intake_Date__c.Value != null)
                                {
                                    var intakeYearMonth = contact.Records[0].Intake_Date__c.Value.ToString("yyyyMM", System.Globalization.CultureInfo.GetCultureInfo("en-US"));

                                    var intakeDateFolderUrl = list.RootFolder.ServerRelativeUrl + "/" + intakeYearMonth;
                                    //Check to make sure date folder does not already exist. If it doesn't, error is thrown. Catch it, and create folder
                                    try
                                    {
                                        var checkFolder = context.Web.GetFolderByServerRelativeUrl(intakeDateFolderUrl);
                                        context.ExecuteQuery();
                                    }
                                    catch
                                    {
                                        //Create a parent folder in SP for file
                                        SharedFunctionality.CreateSharepointFolder(context, list, intakeYearMonth, list.RootFolder.ServerRelativeUrl);
                                    }

                                    //Url of root folder for contact ID subfolders
                                    var contactFolderParentUrl = list.RootFolder.ServerRelativeUrl + "/" + intakeYearMonth;
                                    //Url of contact ID subfolder
                                    var contactFolderUrl = list.RootFolder.ServerRelativeUrl + "/" + intakeYearMonth + "/" + mergedList[i].ParentId;

                                    //Check to make sure folder does not already exist. If it doesn't, error is thrown. Catch it, and create folder
                                    try
                                    {
                                        var checkFolder = context.Web.GetFolderByServerRelativeUrl(contactFolderUrl);
                                        context.ExecuteQuery();

                                        //if this folder exists, set the variable FolderRelativeUrl in the shared class
                                        SharedFunctionality.SetContactFolderUrl(contactFolderUrl);
                                    }
                                    catch
                                    {
                                        //Create a folder in SP for file
                                        SharedFunctionality.CreateContactSharepointFolder(context, list, contactFolderParentUrl, mergedList[i].ParentId);
                                    }

                                    //Check to make sure file does not already exist. If it doesn't, process upload to Sharepoint
                                    var checkFile = context.Web.GetFileByServerRelativeUrl(contactFolderUrl + "/" + mergedList[i].FileName);

                                    context.Load(checkFile, fe => fe.Exists);
                                    context.ExecuteQuery();

                                    if (!checkFile.Exists)
                                    {
                                        //upload file to Sharepoint
                                        var fileLink = SharepointUrl + programName + "/" + intakeYearMonth + "/" + mergedList[i].ParentId + "/" + mergedList[i].FileName;

                                        using (FileStream fs = new FileStream(mergedList[i].FilePath, FileMode.Open))
                                        {
                                            SharedFunctionality.UploadSalesforceFileToSharepoint(context, contact, fs, mergedList[i], list);

                                            //Add new Image object to Salesforce contact
                                            SharedFunctionality.AddLinkToSalesforce(forceClient, mergedList[i], fileLink);
                                        }

                                        if (DeleteSFAttachment != "false")
                                        {
                                            await DeleteSalesforceAttachmentAsync(forceClient, mergedList[i].Id);
                                        }
                                    }
                                    else
                                    {
                                        SharedFunctionality.Log("File " + contactFolderParentUrl + "/" + mergedList[i].FileName + " exists.");
                                    }
                                }
                            }
                        }

                        catch (Exception ex)
                        {
                            SharedFunctionality.Log("Error trying to upload " + mergedList[i].FileName);
                            SharedFunctionality.Log(ex.Message);
                            throw ex;
                        }
                    }
                }
            }

            try
            {
                //After looping thru records, delete the downloaded files from the DownloadedFilePath
                var di = new DirectoryInfo(DownloadedFilePath);
                SharedFunctionality.Log("Deleting files in " + DownloadedFilePath);
                foreach (FileInfo file in di.EnumerateFiles())
                {
                    SharedFunctionality.Log("Deleting " + file.FullName);
                    file.Delete();
                }
                SharedFunctionality.Log("All files deleted");
            }
            catch (Exception ex)
            {
                SharedFunctionality.Log("Error trying to delete all files in folder " + DownloadedFilePath);
                SharedFunctionality.Log(ex.Message);
                throw ex;
            }
        }