Вызов WebAPI от Dynamics CRM - PullRequest
       11

Вызов WebAPI от Dynamics CRM

0 голосов
/ 27 апреля 2018

Возникает проблема, когда я получаю свой асинхронный вызов get, но только при вызове в CRM. Я использовал URL, который я создал в коде на конечной точке Swagger, он работает. Я использовал его в консольном приложении, оно работает, но теперь оно не работает в CRM, и мне действительно нужно Ask-A-Friend или poll the audience здесь, в зависимости от того, какое из них работает.

Я использовал ILMerge, чтобы разрешить использование библиотеки Newtonsoft.JSON. Пожалуйста, дайте мне знать, если есть какая-либо другая информация, которая может вам помочь.

Вот исключение из журнала трассировки подключаемого модуля:

  Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk,Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: One or more errors occurred.Detail: 
    <OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-   instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
    <ActivityId>05794e3d-578e-4c1b-b768-dca8c175628d</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">0</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>One or more errors occurred.</Message>
     <Timestamp>2018-04-27T13:57:23.586758Z</Timestamp>
     <ExceptionRetriable>false</ExceptionRetriable>
     <ExceptionSource>PluginExecution</ExceptionSource>
     <InnerFault i:nil="true" />
 <OriginalException>Microsoft.Xrm.Sdk.InvalidPluginExecutionException
 at System.Activities.WorkflowApplication.Invoke(Activity activity, IDictionary`2 inputs, WorkflowInstanceExtensionManager extensions, TimeSpan timeout)
 at System.Activities.WorkflowInvoker.Invoke(Activity workflow, IDictionary`2 inputs, TimeSpan timeout, WorkflowInstanceExtensionManager extensions)
 at System.Threading.Tasks.Task`1.InnerInvoke()
 at System.Threading.Tasks.Task.Execute()
--- 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, String customActivityTypeName, IExecutionContext requestContext, Dictionary`2 sandboxServices, Boolean useDrawbridgeEnabled, Boolean chaosFailAppDomain)
 at Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IOrganizationServiceFactory organizationServiceFactory, String customActivityTypeName, IExecutionContext requestContext, Dictionary`2 sandboxServices, Boolean useDrawbridgeEnabled, Boolean chaosFailAppDomain)
 at Microsoft.Crm.Sandbox.SandboxWorker.ExecuteCustomWorkflowActivity(SandboxCallInfo callInfo, SandboxCustomActivityExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, SandboxRequestCounter&amp; workerCounter, Boolean returnTraceInfo)</OriginalException>

 <TraceText>
https://l1wsdev.cdc.gov/MisoCustomerSurvey/v1.0/Report/GetDetails/878/2018-04-26/2019-04-27
In method
security protocol set
Handler is handling
credentials credentialing
inside of using statement
set BaseAddress
added headers
Got Survey Details
</TraceText>

Server stack trace: 
 at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
 at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
 at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
 at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
 at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
 at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
 at Microsoft.Crm.Sandbox.ISandboxHost.ExecuteCustomWorkflowActivityAndReturnTraceInfo(SandboxCallInfo callInfo, SandboxCustomActivityExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String assemblyContents, Boolean returnTraceInfo)
 at Microsoft.Crm.Sandbox.SandboxCustomActivity.Execute(SandboxClient client, SandboxCallTracker callTracker, IExecutionContext requestContext, String assemblyContents, Boolean returnTraceInfo)
 at Microsoft.Crm.Sandbox.SandboxCodeUnit.Execute(IExecutionContext context)

И вот мой код

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using System;
using System.Activities;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace CETS_Utility_Workflows
{
    public class GetSurveyDetails : CodeActivity
    {
    [Input("Start of Date Range")] 
    public InArgument<DateTime> StartDate { get; set; }
    [Input("End of Date Range")] 
    public InArgument<DateTime> EndDate { get; set; }
    [Input("Project Name")] 
    public InArgument<string> ProjectName { get; set; }
    [Output("Answer1")]
    //[AttributeTarget("bah_survey", "bah_qualityofwork")]
    public OutArgument<string> Answer1 { get; set; }//quality
    [Output("Answer2")]
    //[AttributeTarget("bah_survey", "bah_communicationlines")]
    public OutArgument<string> Answer2 { get; set; }//communication
    [Output("Answer3")]
    //[AttributeTarget("bah_survey", "bah_recievedincorporatedfeedback")]
    public OutArgument<string> Answer3 { get; set; }//feedback
    [Output("Answer4")]
    //[AttributeTarget("bah_survey", "bah_metbusinessneed")]
    public OutArgument<string> Answer4 { get; set; }//biz need
    [Output("Answer5")]
    //[AttributeTarget("bah_survey", "bah_feltinformedaboutprojectprogress")]
    public OutArgument<string> Answer5 { get; set; }//informed
    [Output("Answer6")]
    //[AttributeTarget("bah_survey", "bah_enduserexperience")]
    public OutArgument<string> Answer6 { get; set; }//pleased with project
    [Output("Answer7")]
    //[AttributeTarget("bah_survey", "bah_comfortablewithfutureprojects")]
    public InOutArgument<string> Answer7 { get; set; }//future proj
    [Output("Answer8")] public OutArgument<string> Answer8 { get; set; }//comments
    protected override void Execute(CodeActivityContext executionContext)
    {
        ITracingService tracer =          executionContext.GetExtension<ITracingService>();
        IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
        IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

        try
        {
            Entity entity = (Entity) context.InputParameters["Target"];

            //TODO: Do stuff
            var projectName = ProjectName.Get(executionContext);
            var detailsUrl = "https://l1wsdev.cdc.gov/MisoCustomerSurvey/v1.0/Report/GetDetails/";
            var surveyId = "878";
            //need to convert to this Date Format (YYYY-MM-DD)
            var startDate = StartDate.Get(executionContext).ToString("s");
            var endDate = EndDate.Get(executionContext).ToString("s");
            startDate = startDate.Split('T')[0]; //format should be correct here.
            endDate = endDate.Split('T')[0];

            //url is built, now go make the call
            var url = $"{detailsUrl}" + $"{surveyId}/" + $"{startDate}/" + $"{endDate}";
            tracer.Trace(url);

            var surveyDetailsJson = GetSurveyDetailsAsync(url, tracer);
            tracer.Trace("Got Survey Details");
            surveyDetailsJson.Wait();
            tracer.Trace("waited");
            var resultJson = surveyDetailsJson.Result;
            tracer.Trace(resultJson);
            var objArr = new object[resultJson.Length];
            var index = 0;
            List<RootObject> listJson = JsonConvert.DeserializeObject<List<RootObject>>(resultJson);
            foreach (var answer in listJson)
            {
                tracer.Trace($"index = {index}");
                tracer.Trace(answer.ParameterValues.ProjectName);
                index++;
            }

            var queryList = listJson.AsQueryable();

            var valueList = queryList.Where(a => a.ParameterValues.ProjectName == projectName).ToList();
            var valuesArray = new string[valueList.Count];
            var indexer = 0;
            foreach (var value in valueList)
            {
                valuesArray[indexer] = value.Value;
                tracer.Trace(value.Text);
                tracer.Trace(value.Value);
                tracer.Trace($"index = {indexer}");
                indexer++;
            }            

            Answer1.Set(executionContext, valuesArray[0]);
            Answer2.Set(executionContext, valuesArray[1]);
            Answer3.Set(executionContext, valuesArray[2]);
            Answer4.Set(executionContext, valuesArray[3]);
            Answer5.Set(executionContext, valuesArray[4]);
            Answer6.Set(executionContext, valuesArray[5]);
            Answer7.Set(executionContext, valuesArray[6]);
            Answer8.Set(executionContext, valuesArray[7]);

        }
        catch (Exception e)
        {
            throw new InvalidPluginExecutionException(e.Message);
        }
    }

    static public async Task<string> GetSurveyDetailsAsync(string url, ITracingService tracer)
    {
        tracer.Trace("In method");
        System.Net.ServicePointManager.SecurityProtocol =
            SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 |
            SecurityProtocolType.Tls;
        tracer.Trace("security protocol set");
        var handler = new HttpClientHandler();
        tracer.Trace("Handler is handling");
        handler.UseDefaultCredentials = true;
        tracer.Trace("credentials credentialing");
        using (var client = new HttpClient(handler))
        {
            tracer.Trace("inside of using statement");
            client.BaseAddress = new Uri(url);
            tracer.Trace("set BaseAddress");
            client.DefaultRequestHeaders.Accept.Add(
                new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
            tracer.Trace("added headers");
            var response = await client.GetAsync(url);
            tracer.Trace("got response");
            var content = await response.Content.ReadAsStringAsync();
            tracer.Trace(content);

            if (response.IsSuccessStatusCode)
            {
                tracer.Trace("returning content");
                return content;
            }

            else
            {
                tracer.Trace("failed");
                return "Fail";
            }

        }
    }


}
public class ParameterValues
{
    public int UserSurveyAnswerId { get; set; }
    public string ProjectName { get; set; }
}

public class RootObject
{
    public int UserAnswerId { get; set; }
    public int SurveyId { get; set; }
    public object Name { get; set; }
    public string Text { get; set; }
    public DateTime QuestionCreateDate { get; set; }
    public object QuestionDeleteDate { get; set; }
    public object ReferenceCode { get; set; }
    public int UserAnswerCreateByPersonId { get; set; }
    public DateTime UserAnswerCreateDate { get; set; }
    public string Value { get; set; }
    public bool IsActive { get; set; }
    public object AnsweredBy { get; set; }
    public ParameterValues ParameterValues { get; set; }
}
}

1 Ответ

0 голосов
/ 12 декабря 2018

Решил проблему. В режиме песочницы встроенная защита не поддерживается. Поэтому, когда я установил для учетных данных по умолчанию значение «true», CRM взорвал мой вызов GET. Вы должны использовать служебную учетную запись и ввести в коде имя пользователя и пароль. Мы предпримем шаги для шифрования пользователя / прохода в верхних средах, но приятно иметь возможность использовать веб-API и получать внешние результаты от CRM

[Ответ вставлен из комментария OP]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...