Search code examples
c#dynamics-crmworkflowmicrosoft-dynamicsdotnet-httpclient

Sending a POST request using httpClient in a custom workflow activity in Dynamics CRM throws an exception "ThreadAbortException"


I have a task to retrieve data created in an entity called "Denunciation" then do some structuring and send this data (in JSON string format) to an API, so I need to make a POST request, everything works fine but when I want to send the post request, it throws this exception

The exception details:

System.Threading.ThreadAbortException
  HResult=0x80131530
  Message=The thread has been abandoned.
  Source=System
  StackTrace:
   at System.Net.CookieModule.OnSendingHeaders(HttpWebRequest httpWebRequest)
   at System.Net.HttpWebRequest.UpdateHeaders()
   at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
   at System.Net.HttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state)
   at System.Net.Http.HttpClientHandler.StartGettingRequestStream(RequestState state)
   at System.Net.Http.HttpClientHandler.PrepareAndStartContentUpload(RequestState state)
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at HclsDeclareProspect.DeclareProspect.<Execute>d__28.MoveNext() in C:\Users\aimad.quouninich\Desktop\Projects\VDN\HclsDeclareProspect\DeclareProspect.cs:line 177

  This exception was originally thrown at this call stack:
    [External Code]
    HclsDeclareProspect.DeclareProspect.Execute(System.Activities.CodeActivityContext) in DeclareProspect.cs

My code in the execute method:

// Send POST request APIM
CanalItem endpoint = CanalProvider.Retrieve(service, endpointReference);
_trace += string.Format("Endpoint : {0} \r\n", endpoint.Name);
_trace += string.Format("Endpoint Url : {0} \r\n", endpoint.Url);
_trace += string.Format("Endpoint Login : {0} \r\n", endpoint.Login);
_trace += string.Format("Endpoint Login : {0} \r\n", endpoint.Password);

string url = $"{endpoint.Url}/denunciation";

var content = new StringContent(requestJSON.ToString(), Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

HttpClient client = new HttpClient();

client.DefaultRequestHeaders.Add("Apim-Subscription-Key", endpoint.Password);

try
{
    var result = await client.PostAsync(url, content);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

If I removed the try-catch block the custom workflow and pluginRegistrationTool will exit without any error message and the subsequent line codes will not execute.

I have tried many things like using httpWebRequest instead of httpClient but when I tried to write to stream it exist with this error:

System.Security.SecurityException
  HResult=0x8013150A
  Message=Type Authorization Request Failed 'System.Net.WebPermission, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
  Source=mscorlib
  StackTrace:
   at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
   at System.Security.CodeAccessPermission.Demand()
   at System.Net.HttpWebRequest.get_Proxy()
   at System.Net.WebRequest.GetRequestStreamAsync()
   at HclsDeclareProspect.DeclareProspect.<Execute>d__29.MoveNext() in C:\Users\aimad.quouninich\Desktop\Projects\VDN\HclsDeclareProspect\DeclareProspect.cs:line 186

  This exception was originally thrown at this call stack:
    [External Code]
    HclsDeclareProspect.DeclareProspect.Execute(System.Activities.CodeActivityContext) in DeclareProspect.cs

Using this code for the HttpWebrequest in place of httpClient:

string url = $"{endpoint.Url}/denunciation";

var content = new StringContent(requestJSON.ToString(), Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

var request = (HttpWebRequest)WebRequest.Create(new Uri(url));
request.ContentType = "application/json";
request.Method = "POST";
request.Timeout = 4000; //ms
var itemToSend = JsonConvert.SerializeObject(requestJSON);
using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
{
    streamWriter.Write(itemToSend);
    streamWriter.Flush();
    streamWriter.Dispose();
}

// Send the request to the server and wait for the response:  
using (var response = await request.GetResponseAsync())
{
    // Get a stream representation of the HTTP web response:  
    using (var stream = response.GetResponseStream())
    {
        var reader = new StreamReader(stream);
        var message = reader.ReadToEnd();
    }
}

I don't know what to do, please any help will be appreciated.


Solution

  • Solved,

    The problem was in Newtonsoft.json package. it looks like the CRM doesn't accept extern packages/assemblies and the tool Ilmerge (to merge multiple assemblies) is deprecated and no longer supported by the CRM.

    When running the debugger and the process was asynchronous I dind'nt notice the problem and was working fine, so I removed Newtonsoft.json and used the built-in solution wich is DataContractSerializer then using Trace log I was able to see that post works fine, but in debugging it is not working the program just exit, the solution to that is to put the breakpoint after the post request line of code to be able to see the results.

    I hope this will help others with the same problem.