Dynamics 365 Доступность поискового ресурса - PullRequest
1 голос
/ 10 марта 2020

Я пытаюсь реализовать возможность поиска ресурсов, как описано здесь: https://cloudblogs.microsoft.com/dynamics365/it/2019/05/21/retrieve-resource-availability-with-universal-resource-scheduling-api/

Здесь приведен пример того, как реализовать его через JavaScript (хотя JavaScript библиотеки, вероятно, устарели или не поддерживаются), на которые я ссылался здесь: https://cloudblogs.microsoft.com/dynamics365/it/2019/07/15/how-to-use-resource-schedulings-search-resource-availability-api/

Я написал. NET Базовая библиотека классов, которая использует службу OData Dynamics 365 для POST к действию msdyn_SearchResourceAvailability.

Я видел несколько примеров для inte rnet, но все они используют SDK Dynamics 365, а не веб-API Dynamics 365.

Я получаю ошибку и поэтому извлекли JSON, который отправляется, и попробовал тот же вызов в Почтальоне, где я получаю ту же ошибку:

{
"error": {
    "code": "0x0",
    "message": "An error occurred while validating input parameters: Microsoft.OData.ODataException: Does not support untyped value in non-open type.\r\n   at System.Web.OData.Formatter.Deserialization.DeserializationHelpers.ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, Object resource, ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)\r\n   at System.Web.OData.Formatter.Deserialization.ODataResourceDeserializer.ApplyStructuralProperties(Object resource, ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n   at Microsoft.Crm.Extensibility.CrmODataEntityDeserializer.ApplyStructuralProperties(Object resource, ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n   at System.Web.OData.Formatter.Deserialization.ODataResourceDeserializer.ReadResource(ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n   at Microsoft.Crm.Extensibility.ODataV4.CrmODataActionPayloadDeserializer.ReadEntry(ODataDeserializerContext readContext, ODataParameterReader reader, IEdmOperationParameter parameter)\r\n   at Microsoft.Crm.Extensibility.ODataV4.CrmODataActionPayloadDeserializer.Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)\r\n   at System.Web.OData.Formatter.ODataMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)",
    "innererror": {
        "message": "An error occurred while validating input parameters: Microsoft.OData.ODataException: Does not support untyped value in non-open type.\r\n   at System.Web.OData.Formatter.Deserialization.DeserializationHelpers.ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, Object resource, ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)\r\n   at System.Web.OData.Formatter.Deserialization.ODataResourceDeserializer.ApplyStructuralProperties(Object resource, ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n   at Microsoft.Crm.Extensibility.CrmODataEntityDeserializer.ApplyStructuralProperties(Object resource, ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n   at System.Web.OData.Formatter.Deserialization.ODataResourceDeserializer.ReadResource(ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n   at Microsoft.Crm.Extensibility.ODataV4.CrmODataActionPayloadDeserializer.ReadEntry(ODataDeserializerContext readContext, ODataParameterReader reader, IEdmOperationParameter parameter)\r\n   at Microsoft.Crm.Extensibility.ODataV4.CrmODataActionPayloadDeserializer.Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)\r\n   at System.Web.OData.Formatter.ODataMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)",
        "type": "Microsoft.Crm.CrmHttpException",
        "stacktrace": "   at Microsoft.Crm.Extensibility.OData.CrmODataUtilities.ValidateInputParameters(ModelStateDictionary controllerModelState)\r\n   at Microsoft.Crm.Extensibility.OData.ActionController.<>c__DisplayClass9_0.<PostUnboundAction>b__0()\r\n   at Microsoft.PowerApps.CoreFramework.ActivityLoggerExtensions.Execute[TResult](ILogger logger, EventId eventId, ActivityType activityType, Func`1 func, IEnumerable`1 additionalCustomProperties)\r\n   at Microsoft.Xrm.Telemetry.XrmTelemetryExtensions.Execute[TResult](ILogger logger, XrmTelemetryActivityType activityType, Func`1 func)\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
    }
}
}

JSON, который публикуется, выглядит следующим образом:

{
"Version": "1",
"Requirement": {
    "msdyn_duration": 180,
    "msdyn_effort": 1,
    "msdyn_fromdate": "2020-03-10T00:00:00+00:00",
    "msdyn_latitude": 55.784129,
    "msdyn_longitude": -3.982742,
    "msdyn_name": "Super Heroes Resource Requirement",
    "msdyn_remainingduration": 180,
    "msdyn_todate": "2020-03-12T00:00:00+00:00",
    "msdyn_worklocation": 690970002
},
"Settings": {
    "ConsiderSlotsWithLessThanRequiredCapacity": false,
    "ConsiderSlotsWithLessThanRequiredDuration": false,
    "ConsiderTravelTime": false,
    "ConsiderSlotsWithOverlappingBooking": false,
    "ConsiderSlotsWithProposedBookings": false,
    "MovePastStartDateToCurrentDate": false,
    "UseRealTimeResourceLocation": false,
    "MaxResourceTravelRadius": {
        "Value": 10,
        "Unit": 192350000
    },
    "SortOrder": {
        "value": [
            {
                "Name": "bookableresource",
                "SortOrder": 0
            }
        ]
    }
},
"ResourceSpecification": {
    "ResourceTypes": {
        "value": [
            2,
            3,
            5
        ]
    },
    "PreferredResources": {
        "value": [
            {
                "bookableresourceid": "d7315245-b162-ea11-a811-000d3a0bad7c"
            },
            {
                "bookableresourceid": "b54bc744-b162-ea11-a811-000d3a0ba110"
            }
        ]
    },
    "RestrictedResources": {
        "value": [
            {
                "bookableresourceid": "ba6d4a4b-b162-ea11-a811-000d3a0bad7c"
            },
            {
                "bookableresourceid": "ca6d4a4b-b162-ea11-a811-000d3a0bad7c"
            }
        ]
    },
    "Constraints": {
        "Characteristics": {
            "value": [
                {
                    "characteristicid": "a02db73e-b162-ea11-a811-000d3a0ba110"
                }
            ]
        },
        "Roles": {
            "value": [
                {
                    "bookableresourcecategoryid": "d56d4a4b-b162-ea11-a811-000d3a0bad7c"
                }
            ]
        },
        "Territories": {
            "value": [
                {
                    "territoryid": "7c2db73e-b162-ea11-a811-000d3a0ba110"
                }
            ]
        },
        "UnspecifiedTerritory": false,
        "OrganizationalUnits": {
            "value": [
                {
                    "msdyn_organizationalunitid": "822db73e-b162-ea11-a811-000d3a0ba110"
                }
            ]
        },
        "BusinessUnits": {
            "value": [
                {
                    "businessunitid": "fba6cf4b-f24a-ea11-a813-00224801cd21"
                }
            ]
        }
    }
}
}

Может ли кто-нибудь сообщить, где я иду не так?

Ответы [ 2 ]

0 голосов
/ 12 марта 2020

Часть проблемы заключается в том, что образцы C# используют SDK, который, в свою очередь, использует устаревшую службу WCF 2011 года, а не текущую службу OData. Похоже, что служба OData является более строгой с точки зрения @ odata.type, который вы указываете, в том смысле, что она проверяет, что атрибуты, которые вы предоставляете, являются реальными атрибутами / полями этой сущности. Проблема с настройками и ResourceSpecification заключается в том, что в Action тип сущности не указан.

0 голосов
/ 10 марта 2020

Мне удалось перейти на полевую службу v8.8.x с v8.7.x и протестировать действие CRM msdyn_SearchResourceAvailability с помощью веб-API со следующей полезной нагрузкой. Кажется, у меня не все настройки и настройки данных, но веб-интерфейс дает хороший ответ (отличный от 400 = неправильный запрос .. lol)

var parameters = {};
parameters.Version = "2";
var requirement = {};
requirement.msdyn_resourcerequirementid = "B9E6F413-0063-EA11-A811-000D3A5A1CAC"; //Delete if creating new record 
requirement["@odata.type"] = "Microsoft.Dynamics.CRM.msdyn_resourcerequirement";
parameters.Requirement = requirement;
var settings = {};
settings.systemuserid = "26ADDD07-D9F4-E711-8138-E0071B715B11"; //Delete if creating new record 
settings["@odata.type"] = "Microsoft.Dynamics.CRM.systemuser";
parameters.Settings = settings;

var req = new XMLHttpRequest();
req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/msdyn_SearchResourceAvailability", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function() {
    if (this.readyState === 4) {
        req.onreadystatechange = null;
        if (this.status === 200) {
            var results = JSON.parse(this.response);
            alert(this.response)
        } else {
            alert(this.status);
        }
    }
};
req.send(JSON.stringify(parameters));

Ответ:

{
  "@odata.context": "https://crmdev.crm.dynamics.com/api/data/v9.1/$metadata#Microsoft.Dynamics.CRM.msdyn_SearchResourceAvailabilityResponse",
  "TimeSlots": [
    {
      "@odata.type": "#Microsoft.Dynamics.CRM.organization"
    },
    {
      "@odata.type": "#Microsoft.Dynamics.CRM.organization"
    },
    {
      "@odata.type": "#Microsoft.Dynamics.CRM.organization"
    },
    {
      "@odata.type": "#Microsoft.Dynamics.CRM.organization"
    },
    {
      "@odata.type": "#Microsoft.Dynamics.CRM.organization"
    }
  ],
  "Resources": [
    {
      "@odata.type": "#Microsoft.Dynamics.CRM.organization"
    }
  ],
  "Related": {
    "@odata.type": "#Microsoft.Dynamics.CRM.organization"
  },
  "Exceptions": {
    "@odata.type": "#Microsoft.Dynamics.CRM.organization"
  }
}

Обновление:

  1. Для этого вызова требуются только версия, требование и настройки, поэтому начните с минимального ввода кода и улучшите его

  2. При устранении неисправности сообщения об ошибке Microsoft.OData.ODataException: Does not support untyped value in non-open type действуйте в этом направлении - опечатка в имени некоторой схемы может быть причиной

  3. Не уверен, что это msdyn_SearchResourceAvailability сообщение действия еще доступно в веб-интерфейсе API, но опробован только OrganizationRequest SDK Ссылка


Это пример запроса вместе с необходимой полезной нагрузкой :

var parameters = {};
var workorder = {};
workorder.msdyn_workorderid = "ADE6F413-0063-EA11-A811-000D3A5A1CAC"; //Delete if creating new record 
workorder["@odata.type"] = "Microsoft.Dynamics.CRM.msdyn_workorder";
parameters.WorkOrder = workorder;
parameters.RealTimeMode = true;
parameters.Duration = 30;
parameters.IgnoreDuration = true;
parameters.IgnoreTravelTime = true;
parameters.AllowOverlapping = true;
parameters.Radius = 0;
parameters.StartTime = new Date("3/10/2020").toISOString();
parameters.EndTime = new Date("3/10/2020").toISOString();
var resources1 = {};
resources1.systemuserid = "3BD2ADED-20B2-E911-A98E-000D3A374B53"; //Delete if creating new record 
resources1["@odata.type"] = "Microsoft.Dynamics.CRM.systemuser";
parameters.Resources = [resources1];

var req = new XMLHttpRequest();
req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/msdyn_RetrieveResourceAvailability", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function() {
    if (this.readyState === 4) {
        req.onreadystatechange = null;
        if (this.status === 200) {
            var results = JSON.parse(this.response);
            alert("response: "+this.response)
        } else {
            alert(this.status);
        }
    }
};
req.send(JSON.stringify(parameters));

Я только что сгенерировал это в своей песочнице без каких-либо данных, но вы можете попробовать построитель CRM REST для построения запроса.

...