Так вот мой сценарий. Я должен вызывать функцию Azure через код плагина Dynamics CRM (C #) асинхронно, это нормально. Но Я не хочу, чтобы код ожидал ответа функции Azure . Я просто хочу завершить выполнение кода и выйти.
Функция Azure позаботится об обновлениях обратно в CRM, если это необходимо.
Причина, по которой я не хочу ждать, состоит в том, что для запуска плагина в CRM Online существует ограничение в 2 минуты. Однако функция Azure может занять несколько минут для завершения процесса.
Вот мой код класса плагина, который выполняет синхронный вызов функции Azure. (я могу преобразовать вызов в асинхронный после этого документа, но после этого подхода мой код все еще будет ждать ответа).
public class CallAzureFunc : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Extract the tracing service for use in debugging sandboxed plug-ins.
ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext));
// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parameters.
Entity entity = (Entity)context.InputParameters["Target"];
// Verify that the target entity represents an entity type you are expecting.
if (entity.LogicalName != "account")
return;
// Obtain the organization service reference which you will need web service calls.
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
// Plug-in business logic goes here.
Data data = new Data
{
name = entity.Attributes["name"].ToString()
};
string result = CallFunction(tracer, data);
tracer.Trace($@"result: {result}");
}
catch (FaultException<OrganizationServiceFault> ex)
{
throw new InvalidPluginExecutionException("An error occurred in MyPlug-in.", ex);
}
catch (Exception ex)
{
tracer.Trace("MyPlugin: {0}", ex.ToString());
throw;
}
}
}
private string CallFunction(ITracingService tracer, Data data)
{
string json = JsonConvert.SerializeObject(data);
string apiUrl = "https://<AzureFunctionName>.azurewebsites.net/api/";
string token = "<token>";
string content = null;
string apiMethod = "CreateContactFromLead";
string inputJson = json;
string result = ApiHelper.ExecuteApiRequest(apiUrl, token, content, apiMethod, inputJson, tracer);
return result;
}
}
А вот вспомогательные методы для вызова API.
internal static string ExecuteApiRequest(string apiUrl, string token, string content, string apiMethod, string inputJson, ITracingService tracer)
{
try
{
var data = Encoding.ASCII.GetBytes(inputJson);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format(apiUrl + apiMethod));
request.Method = "POST";
request.ContentLength = inputJson.Length;
request.ContentType = "application/json";
request.ContentLength = data.Length;
request.Headers.Add("x-functions-key", token);
request.Accept = "application/json";
// Send the data
Stream newStream = request.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
// Get the resposne
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response != null)
{
tracer.Trace("ApiHelper > ExecuteApiRequest > response.StatusCode: " + response.StatusCode);
tracer.Trace("ApiHelper > ExecuteApiRequest > response.StatusDescription: " + response.StatusDescription);
}
if (response.StatusCode == HttpStatusCode.OK || response.StatusDescription == "OK" || response.StatusDescription == "200")
{
content = ReadStream(response, tracer);
}
else if (response.StatusCode == HttpStatusCode.NoContent || response.StatusDescription == "No Content" || response.StatusDescription == "204")
{
content = null;
}
else
{
if (response != null)
{
throw new Exception(String.Format("Status Code: {0}, Status Description: {1}",
response.StatusCode,
response.StatusDescription));
}
}
return content;
}
catch (Exception ex)
{
tracer.Trace("ApiHelper > ExecuteApiRequest > error: " + ex.Message);
throw;
}
}
private static string ReadStream(HttpWebResponse response, ITracingService tracer)
{
try
{
var responseJson = string.Empty;
if (response != null)
{
Stream dataStream = response.GetResponseStream();
if (dataStream != null)
{
using (StreamReader reader = new StreamReader(dataStream))
{
while (!reader.EndOfStream)
{
responseJson = reader.ReadToEnd();
}
}
}
}
return responseJson;
}
catch (Exception ex)
{
tracer.Trace("ApiHelper > ReadStream > error: " + ex.Message);
throw ex;
}
}