
So I am trying to create my own logic for moving a Quote Annotation to a SharePoint location. After multiple trial-and-errors I am now at a point which I cannot seem to solve.
The objective of the custom Workflow is simple;
For step 3 I created a Custom Workflow plugin with the following tutorials as references:
vikramxrm.blogspot.nl/.../copy-ms-crm-2011-attached-documents-in.html
https://github.com/jlattimer/CRM-Note-Workflow-Utilities
The code I have so far is:
public class MoveQuoteToSharepoint : CodeActivity
{
[Input("SourceQuote")]
[ReferenceTarget("quote")]
public InArgument<EntityReference> SourceQuote { get; set; }
private String _fileName;
protected override void Execute(CodeActivityContext executionContext)
{
//Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
// Get the target entity from the context
Entity regQuote = (Entity)service.Retrieve("quote", context.PrimaryEntityId, new ColumnSet(new string[] { "name", "ownerid" }));
string quoteName = (string)regQuote.Attributes["name"];
//Get the notes from the Quote (context)
QueryExpression _quoteAttachmentQuery = new QueryExpression
{
EntityName = "annotation",
ColumnSet = new ColumnSet
(
"subject",
"filename",
"documentbody"
),
Criteria = new FilterExpression
{
Conditions =
{
new ConditionExpression
{
AttributeName = "objectid",
Operator = ConditionOperator.Equal,
Values = { context.PrimaryEntityId }
},
new ConditionExpression
{
AttributeName = "isdocument",
Operator = ConditionOperator.Equal,
Values = {true}
}
}
}
};
EntityCollection results = service.RetrieveMultiple(_quoteAttachmentQuery);
//Annotation found
if (results.Entities.Count > 0)
{
//Fetch first annotation
Entity retrievedAnnotation = results.Entities.First();
_fileName = retrievedAnnotation.GetAttributeValue<string>("filename");
using (FileStream fileStream = new FileStream(_fileName, FileMode.OpenOrCreate))
{
byte[] fileContent = Convert.FromBase64String(retrievedAnnotation.GetAttributeValue<string>("documentbody"));
//fileStream.Write(fileContent, 0, fileContent.Length);
CopyToSharePoint2013(retrievedAnnotation.Id, service, quoteName, fileContent, _fileName); }
}
else
{
throw new Exception("There are no annotations found for this Quote.");
}
}
public static void CopyToSharePoint2013(Guid _CaseId, IOrganizationService _service, string _FolderName, byte[] fileContent, string filename)
{
try
{
string _SharePointServer = @"mydomain.sharepoint.com/.../xxx";
using (ClientContext _clientContext = new ClientContext(_SharePointServer))
{
SecureString passWord = new SecureString();
foreach (char c in "xxxx".ToCharArray()) passWord.AppendChar(c);
_clientContext.Credentials = new SharePointOnlineCredentials("me@loginemail.com", passWord);
//create web object
Web web = _clientContext.Web;
List oList = web.Lists.GetByTitle("Quote");
if (oList != null)
{
//Create Folder
var folders = oList.RootFolder.Folders;
_clientContext.Load(folders);
_clientContext.ExecuteQuery();
var newFolder = folders.Add(_FolderName);
_clientContext.ExecuteQuery();
//Copy file into created folder
FileCreationInformation oFileCreationInformation = new FileCreationInformation();
oFileCreationInformation.Content = fileContent;
oFileCreationInformation.Url = @_SharePointServer + "/quote/" + _FolderName + "/" + filename;
oFileCreationInformation.Overwrite = true;
oList.RootFolder.Files.Add(oFileCreationInformation);
_clientContext.Load(oList);
_clientContext.ExecuteQuery();
//Create SharePoint Location record
if (!AlreadyExistDocumentLocationRecord(_CaseId, _service))
{
CreateDocumentLocationRecord(_service, _FolderName, oFileCreationInformation.Url, _CaseId);
}
}
}
}
catch (Exception Ex)
{
Console.Write(Ex.Message);
if (Ex.InnerException != null)
{
Console.WriteLine(Ex.InnerException.Message);
Console.ReadLine();
}
}
}
private static void CreateDocumentLocationRecord(IOrganizationService service, string _locationName, string _locationURL, Guid _regarding)
{
try
{
// Instantiate an account object.
Entity DocumentLocation = new Entity("sharepointdocumentlocation");
//set the fields values
DocumentLocation["name"] = _locationName;
DocumentLocation["regardingobjectid"] = new EntityReference("quote", _regarding);
DocumentLocation["relativeurl"] = _locationName;
if ((GetParentSiteUrl(service)) != Guid.Empty)
{
DocumentLocation["parentsiteorlocation"] = new EntityReference("sharepointdocumentlocation", GetParentSiteUrl(service));
}
//create the record
Guid DocumentLocationid = service.Create(DocumentLocation);
}
catch (Exception Ex)
{
Console.Write(Ex.Message);
if (Ex.InnerException != null)
{
Console.WriteLine(Ex.InnerException.Message);
Console.ReadLine();
}
}
}
private static Guid GetParentSiteUrl(IOrganizationService service)
{
Guid _Id = Guid.Empty;
try
{
QueryExpression _Query = new QueryExpression
{
EntityName = "sharepointdocumentlocation",
ColumnSet = new ColumnSet("relativeurl"),
Criteria = new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression
{
AttributeName = "relativeurl",
Operator = ConditionOperator.Equal,
Values = { "quote" }
},
}
}
};
EntityCollection _EntityLocation = service.RetrieveMultiple(_Query);
if (_EntityLocation.Entities.Count > 0)
{
_Id = _EntityLocation.Entities[0].Id;
}
}
catch (Exception Ex)
{
Console.Write(Ex.Message);
if (Ex.InnerException != null)
{
Console.WriteLine(Ex.InnerException.Message);
Console.ReadLine();
}
}
return _Id;
}
private static bool AlreadyExistDocumentLocationRecord(Guid CaseId, IOrganizationService _service)
{
QueryExpression _Query = new QueryExpression
{
EntityName = "sharepointdocumentlocation",
ColumnSet = new ColumnSet("regardingobjectid"),
Criteria = new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression
{
AttributeName = "regardingobjectid",
Operator = ConditionOperator.Equal,
Values = { CaseId }
},
}
}
};
EntityCollection _EntityLocation = _service.RetrieveMultiple(_Query);
if (_EntityLocation.Entities.Count > 0)
return true;
else
return false;
}
}
After some testing I am getting the following error:
![]() |
Unexpected exception from plug-in (Execute): MyNameSpace.MoveQuoteToSharepoint: System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed. |
I guess it is being caused by the following bit of code, but I am not sure:
using (FileStream fileStream = new FileStream(_fileName, FileMode.OpenOrCreate))
{
byte[] fileContent = Convert.FromBase64String(retrievedAnnotation.GetAttributeValue<string>("documentbody"));
//fileStream.Write(fileContent, 0, fileContent.Length);
CopyToSharePoint2013(retrievedAnnotation.Id, service, quoteName, fileContent, _fileName); }
Anyone have a clue how to fix this? I am also not sure if the SharePoint bits of code will work, not even got there because of the previous error. Does anyone think I should program it differently?
Thank you in advance!
*This post is locked for comments
I have the same question (0)You're right in what line of code is causing the problem. It looks like your plugin is running in the sandbox, which blocks FileIO access. You've 3 main options: