DawidPotgieter / Dynamics-CRM-Binary-Storage-Options

A Dynamics CRM plugin to transparently store attachment binaries outside CRM database. Azure Blob or File storage for instance.
GNU Affero General Public License v3.0
34 stars 15 forks source link

Attachments on an inactive e-mail #13

Closed meikelenboom closed 5 years ago

meikelenboom commented 6 years ago

I have an issue with e-mail attachements. These are stored in Azure Blob storage, but when I try to retreive them they give an error. Note attachements work fine.

Any ideas?

meikelenboom commented 6 years ago

I'm digging a little deeper and I find the following.

With activitymimeattachments the binary data is stored in CRM and in Azure Blob storage. The body field is not emptied / set to the new value.

Btw I'm working with v9.

DawidPotgieter commented 6 years ago

Hi there,

Can you give a little bit more information here? Is it any kind of email attachments, like if you create a new email and add an attachment, does this happen? I remember seeing you mention email queues, is it only happening there?

The email attachments plugin is attached to run async after creation (i.e. the workflow service executes this by moving the data and then clearing out the record's binary data), so if there's any errors, you will see it in the "System Jobs" tab. If you could check there and see if you find anything?

Cheers.

meikelenboom commented 6 years ago

Hi,

I've done very extensive testing and debugging and found that it happens on every e-mail (activitymimeattachments), not specifically related to queues.

It stores the data in blob storage, but the update to set the body field to the placeholder doesn't work. These line are the 'issue' in the Plugin.Create class:

entity.Attributes[GenericConstants.Constants[entity.LogicalName][GenericConstants.DocumentBodyAttributeKey]] = GenericConstants.EmptyBodyContent;
//If the plugin is running in async mode and is for attachment, we have to make a call to save the attachment.
if (context.Stage == CrmConstants.PostOperationStateNumber && entity.LogicalName == CrmConstants.AttachmentEntityName)
{
    service.Update(entity);
}

I've tested it with CRM online V8.2 and V9.0. And I've tested it with various options in async and synchronous mode.

meikelenboom commented 6 years ago

I forgot about the System Jobs and found this error:

Plugin Trace:

[BinaryStorageOptions: BinaryStorageOptions.Plugin]
[d2e89545-de31-e611-942d-0050569079a0: BinaryStorageOptions.Plugin: Create of activitymimeattachment]

Error Message:

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: System.ArgumentNullException: Value cannot be null.
Parameter name: s
   at System.IO.StringReader..ctor(String s)
   at System.Xml.Linq.XDocument.Parse(String text, LoadOptions options)
   at BinaryStorageOptions.Configuration.PluginStepConfigurationProvider..ctor(IOrganizationService organizationService, String configurationForEntityType, String unsecurePluginStepConfiguration, String securePluginStepConfiguration)
   at BinaryStorageOptions.Configuration.Factory.GetConfigurationProvider(IOrganizationService organizationService, String entityName, String unsecurePluginStepConfiguration, String securePluginStepConfiguration)
   at BinaryStorageOptions.Plugin.Create(IServiceProvider serviceProvider)Detail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ActivityId>013a6e68-f06c-46b1-80ec-ffa394f24dfb</ActivityId>
  <ErrorCode>-2147220891</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
    <KeyValuePairOfstringanyType>
      <d2p1:key>OperationStatus</d2p1:key>
      <d2p1:value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:int">3</d2p1:value>
    </KeyValuePairOfstringanyType>
    <KeyValuePairOfstringanyType>
      <d2p1:key>SubErrorCode</d2p1:key>
      <d2p1:value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:int">-2146233088</d2p1:value>
    </KeyValuePairOfstringanyType>
  </ErrorDetails>
  <Message>System.ArgumentNullException: Value cannot be null.
Parameter name: s
   at System.IO.StringReader..ctor(String s)
   at System.Xml.Linq.XDocument.Parse(String text, LoadOptions options)
   at BinaryStorageOptions.Configuration.PluginStepConfigurationProvider..ctor(IOrganizationService organizationService, String configurationForEntityType, String unsecurePluginStepConfiguration, String securePluginStepConfiguration)
   at BinaryStorageOptions.Configuration.Factory.GetConfigurationProvider(IOrganizationService organizationService, String entityName, String unsecurePluginStepConfiguration, String securePluginStepConfiguration)
   at BinaryStorageOptions.Plugin.Create(IServiceProvider serviceProvider)</Message>
  <Timestamp>2018-06-05T09:12:59.7866587Z</Timestamp>
  <ExceptionRetriable>false</ExceptionRetriable>
  <ExceptionSource>PluginExecution</ExceptionSource>
  <InnerFault i:nil="true" />
  <OriginalException>Microsoft.Xrm.Sdk.InvalidPluginExecutionException
   at BinaryStorageOptions.Plugin.Create(IServiceProvider serviceProvider)
   at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.&lt;&gt;c__DisplayClass14_3.&lt;Execute&gt;b__0()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IOrganizationServiceFactory organizationServiceFactory, Dictionary`2 sandboxServices, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, IPluginExecutionContext requestContext, Boolean enablePluginStackTrace, Boolean chaosFailAppDomain)
   at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IOrganizationServiceFactory organizationServiceFactory, Dictionary`2 sandboxServices, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, IPluginExecutionContext requestContext, Boolean enablePluginStackTrace, Boolean chaosFailAppDomain)
   at Microsoft.Crm.Sandbox.SandboxWorker.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, SandboxRequestCounter&amp; workerCounter, Boolean returnTraceInfo)</OriginalException>
  <TraceText>
[BinaryStorageOptions: BinaryStorageOptions.Plugin]
[d2e89545-de31-e611-942d-0050569079a0: BinaryStorageOptions.Plugin: Create of activitymimeattachment]

</TraceText>
</OrganizationServiceFault>

However, I don't understand this error. I'm debugging with the profiler in the plugin registration tool and it doesn't give the same error. And I have some doubt if this error is actually related to the issue, as I can't reproduce it a the moment.

DawidPotgieter commented 6 years ago

Hi there,

The error listed below seems to indicate that you have not set the xml configuration on the create step, either the unsecure or the secure config.

Can you check that and make sure it is set correctly?

Sent from my Windows 10 phone


From: meikelenboom notifications@github.com Sent: Tuesday, June 12, 2018 6:42:47 PM To: DawidPotgieter/Dynamics-CRM-Binary-Storage-Options Cc: Dawid Potgieter; Comment Subject: Re: [DawidPotgieter/Dynamics-CRM-Binary-Storage-Options] Attachments on an inactive e-mail (#13)

I forgot about the System Jobs and found this error:

Plugin Trace:

[BinaryStorageOptions: BinaryStorageOptions.Plugin] [d2e89545-de31-e611-942d-0050569079a0: BinaryStorageOptions.Plugin: Create of activitymimeattachment]

Error Message:

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: System.ArgumentNullException: Value cannot be null. Parameter name: s at System.IO.StringReader..ctor(String s) at System.Xml.Linq.XDocument.Parse(String text, LoadOptions options) at BinaryStorageOptions.Configuration.PluginStepConfigurationProvider..ctor(IOrganizationService organizationService, String configurationForEntityType, String unsecurePluginStepConfiguration, String securePluginStepConfiguration) at BinaryStorageOptions.Configuration.Factory.GetConfigurationProvider(IOrganizationService organizationService, String entityName, String unsecurePluginStepConfiguration, String securePluginStepConfiguration) at BinaryStorageOptions.Plugin.Create(IServiceProvider serviceProvider)Detail:

013a6e68-f06c-46b1-80ec-ffa394f24dfb -2147220891 OperationStatus 3 SubErrorCode -2146233088 System.ArgumentNullException: Value cannot be null. Parameter name: s at System.IO.StringReader..ctor(String s) at System.Xml.Linq.XDocument.Parse(String text, LoadOptions options) at BinaryStorageOptions.Configuration.PluginStepConfigurationProvider..ctor(IOrganizationService organizationService, String configurationForEntityType, String unsecurePluginStepConfiguration, String securePluginStepConfiguration) at BinaryStorageOptions.Configuration.Factory.GetConfigurationProvider(IOrganizationService organizationService, String entityName, String unsecurePluginStepConfiguration, String securePluginStepConfiguration) at BinaryStorageOptions.Plugin.Create(IServiceProvider serviceProvider) 2018-06-05T09:12:59.7866587Z false PluginExecution Microsoft.Xrm.Sdk.InvalidPluginExecutionException at BinaryStorageOptions.Plugin.Create(IServiceProvider serviceProvider) at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.<>c__DisplayClass14_3.<Execute>b__0() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IOrganizationServiceFactory organizationServiceFactory, Dictionary`2 sandboxServices, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, IPluginExecutionContext requestContext, Boolean enablePluginStackTrace, Boolean chaosFailAppDomain) at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IOrganizationServiceFactory organizationServiceFactory, Dictionary`2 sandboxServices, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, IPluginExecutionContext requestContext, Boolean enablePluginStackTrace, Boolean chaosFailAppDomain) at Microsoft.Crm.Sandbox.SandboxWorker.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, SandboxRequestCounter& workerCounter, Boolean returnTraceInfo) [BinaryStorageOptions: BinaryStorageOptions.Plugin] [d2e89545-de31-e611-942d-0050569079a0: BinaryStorageOptions.Plugin: Create of activitymimeattachment]

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FDawidPotgieter%2FDynamics-CRM-Binary-Storage-Options%2Fissues%2F13%23issuecomment-396482561&data=02%7C01%7C%7C146ce613135348176af308d5d02fb697%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636643825693726110&sdata=FKwypIAsvif7IzxHSfM3lToY%2BVDlFMQrxDJmKTXARNM%3D&reserved=0, or mute the threadhttps://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FATktwKIdI7uXUmMr-ZnqNDu2Ebf4UBCLks5t72LngaJpZM4Ucq6m&data=02%7C01%7C%7C146ce613135348176af308d5d02fb697%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636643825693726110&sdata=JovzCm0i9JeH3OKPCAo7gm6EIHQOYjMuiP6Zk6Cvc6E%3D&reserved=0.

DawidPotgieter commented 6 years ago

Could you perhaps give me the line number causing an exception, as there are 3 lines of code there.

I’m guessing though, that if you’re getting an error there, that the plugin is not attached to the correct entity/event.

Would you mind expanding the events and attached plugins just for binarystorageoptions and post that?

Sent from my Windows 10 phone


From: meikelenboom notifications@github.com Sent: Tuesday, June 12, 2018 6:29:06 PM To: DawidPotgieter/Dynamics-CRM-Binary-Storage-Options Cc: Dawid Potgieter; Comment Subject: Re: [DawidPotgieter/Dynamics-CRM-Binary-Storage-Options] Attachments on an inactive e-mail (#13)

Hi,

I've done very extensive testing and debugging and found that it happens on every e-mail (activitymimeattachments), not specifically related to queues.

It stores the data in blob storage, but the update to set the body field to the placeholder doesn't work. These line are the 'issue' in the Plugin.Create class:

entity.Attributes[GenericConstants.Constants[entity.LogicalName][GenericConstants.DocumentBodyAttributeKey]] = GenericConstants.EmptyBodyContent; //If the plugin is running in async mode and is for attachment, we have to make a call to save the attachment. if (context.Stage == CrmConstants.PostOperationStateNumber && entity.LogicalName == CrmConstants.AttachmentEntityName) { service.Update(entity); }

I've tested it with CRM online V8.2 and V9.0. And I've tested it with various options in async and synchronous mode.

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://nam05.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FDawidPotgieter%2FDynamics-CRM-Binary-Storage-Options%2Fissues%2F13%23issuecomment-396479933&data=02%7C01%7C%7Ca9ba573f31d64ac0a14608d5d02dccda%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636643817479381324&sdata=riCMIXGBX%2Be%2BTivjUNaSG6Z3yah2zmMBss10tUQN0TA%3D&reserved=0, or mute the threadhttps://nam05.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FATktwMczrBhL5WN9IGBGT7zIYZkHnReQks5t71-ygaJpZM4Ucq6m&data=02%7C01%7C%7Ca9ba573f31d64ac0a14608d5d02dccda%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636643817479381324&sdata=BIU0YgjvHmW%2FZc0Yo3jKrMUYv4nBHcBiIsW8fFN3ffs%3D&reserved=0.

meikelenboom commented 6 years ago

It's set correctly. That's why I think it's not from the error. But from the initial deployment.

In the meantime, I'm testing with an older onpremises environment to make sure I can debug properly. It doesn't give any errors, but the body is not set to the constant value.

So attachements are stored in blob storage, but not deleted from the database. It's not the same issue I started the issue with, but looks related.

DawidPotgieter commented 6 years ago

So,

The code gets to service.Update(entity), executes it without raising an error, but if you look in the database/crm toolkit, you can see the bodycontent is not something like IA== ?

Sent from my Windows 10 phone


From: meikelenboom notifications@github.com Sent: Tuesday, June 12, 2018 7:40:28 PM To: DawidPotgieter/Dynamics-CRM-Binary-Storage-Options Cc: Dawid Potgieter; Comment Subject: Re: [DawidPotgieter/Dynamics-CRM-Binary-Storage-Options] Attachments on an inactive e-mail (#13)

It's set correctly. That's why I think it's not from the error. But from the initial deployment.

In the meantime, I'm testing with an older onpremises environment to make sure I can debug properly. It doesn't give any errors, but the body is not set to the constant value.

So attachements are stored in blob storage, but not deleted from the database. It's not the same issue I started the issue with, but looks related.

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FDawidPotgieter%2FDynamics-CRM-Binary-Storage-Options%2Fissues%2F13%23issuecomment-396496303&data=02%7C01%7C%7Cddb80f93940c448788ae08d5d037c5c6%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636643860306664022&sdata=xUs%2FTeoR2lzxdp8S8Lggw9LIU7zoq9DOforIwuIG8V8%3D&reserved=0, or mute the threadhttps://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FATktwBDLivxBTssfGQxMk5RR2F4RwLo9ks5t73BsgaJpZM4Ucq6m&data=02%7C01%7C%7Cddb80f93940c448788ae08d5d037c5c6%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636643860306664022&sdata=AE4%2B00fBzYcDOUemi9gO85ApVrm4gMUBQsDfTufWjh8%3D&reserved=0.

meikelenboom commented 6 years ago

Yes, that's exactly the case. I can now reproduce it in three environments v8.2 & v9 online en 2016 onpremises.

If you have any suggestions on what to try, I'm very willing to make changes and submit a pull request if I can get it to work.

DawidPotgieter commented 6 years ago

Now that you mention it, I can’t remember ever getting the activitymimeattachments create to work in the debugger. Just that one plugin.

Can you confirm that he plugin is set to post operation, async? That is the only way that specific plugin is able to work correctly…

Sent from my Windows 10 phone


From: meikelenboom notifications@github.com Sent: Tuesday, June 12, 2018 11:19:35 PM To: DawidPotgieter/Dynamics-CRM-Binary-Storage-Options Cc: Dawid Potgieter; Comment Subject: Re: [DawidPotgieter/Dynamics-CRM-Binary-Storage-Options] Attachments on an inactive e-mail (#13)

Yes, that's exactly the case. I can now reproduce it in three environments v8.2 & v9 online en 2016 onpremises.

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://eur02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FDawidPotgieter%2FDynamics-CRM-Binary-Storage-Options%2Fissues%2F13%23issuecomment-396554971&data=02%7C01%7C%7C3173b278fe9746636b7f08d5d0566143%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636643991764880826&sdata=UNOzTA3depf3S9SWIE05Bdv8wQ%2FIQUHIUPFdXRLamks%3D&reserved=0, or mute the threadhttps://eur02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FATktwJX2ZN1-KCrMU87Ng6GlPlvZ-SPaks5t76PHgaJpZM4Ucq6m&data=02%7C01%7C%7C3173b278fe9746636b7f08d5d0566143%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636643991764880826&sdata=VuRZ2XYp0meRsJ3DYfRnH01cnAuXGzLrLXd2mtt38H8%3D&reserved=0.

meikelenboom commented 6 years ago

I can confirm that I've tested it with post operation async (and other options as well)

meikelenboom commented 6 years ago

Just to be sure it's not CRM, I've tested this code and that works;


entity["body"] = "IA==";

 if (context.Stage == 40 && entity.LogicalName == "activitymimeattachment")
{
    service.Update(entity);
}
meikelenboom commented 6 years ago

I'm pretty lost. I've tried the code above, and that works. When I try the webapi to test the same, but from another api, it doesn't work.

It's all very inconsistent.

DawidPotgieter commented 6 years ago

Hi there, sorry for the late response.

First off, the fact that the hard coded strings seem to make the debugging work, where the constants don't, well, that's a bizarre one that I don't have any ideas on.

However, I've just done some tests with clean installs, and I don't seem to have any issues when running this (haven't had a chance to test the 365 version yet, but I've been told it works fine there too). So, I would suggest as a last resort to remove the solution, and redo the install and setup steps, check if you still get an issue.

As a bit of history, what you are experiencing in that specific plugin in debug mode is exactly what I had, and I could never get it do work in debug/profiler mode. However, when the CRM workflow service executes that line, it works just fine, so I went with that. It seems that activitymimeattachments are "special" in some way, it doesn't work as consistently as other entities.

Looking back at this thread, it seems to have started off with getting an error when trying to read email attachments. Is that still an issue? Then, onto the "not clearing out part", as I mentioned, that won't ever work in profiling/debug mode as far as I can remember. I can only think of a few more things to try :

  1. Re-install and try again without debugging
  2. Check to make sure that the user doing the work (plugin runs in user's context) has update permissions : Core Records/Activity/Write
  3. Hard code the constants as you have above. If that works, I don't see any issue using it like that, because the intent is exactly the same.

If none of those options fixes your problems, please let me know. I will then dig further and test it on dynamics 365 instance to see if I can help.

Cheers.