Dynamics crm 使用实体元数据早期绑定调用Dynamics Web API

Dynamics crm 使用实体元数据早期绑定调用Dynamics Web API,dynamics-crm,microsoft-dynamics,dynamics-365,Dynamics Crm,Microsoft Dynamics,Dynamics 365,我希望使用我的oData端点,但使用早期绑定的类。然而,有很多早期绑定的工具,我想知道哪一个提供了最好的开发人员体验/最少的阻力 例如,有一个: 等等。是否存在开发人员首选项/方法?早期绑定类用于作为SOAP服务的组织服务。生成这些类的常规方法是使用 OData可以用于组织数据服务或Web API中,但它们没有早期绑定的类 进一步阅读:与标准SOAP早期绑定类一起使用并非不可能。我们必须要有创意。如果我们只处理基本属性(字段,而不是关系,ecc),这似乎是可能的。例如对于创建和更新,ODat

我希望使用我的oData端点,但使用早期绑定的类。然而,有很多早期绑定的工具,我想知道哪一个提供了最好的开发人员体验/最少的阻力

例如,有一个:


等等。是否存在开发人员首选项/方法?

早期绑定类用于作为SOAP服务的组织服务。生成这些类的常规方法是使用

OData可以用于组织数据服务或Web API中,但它们没有早期绑定的类


进一步阅读:

与标准SOAP早期绑定类一起使用并非不可能。我们必须要有创意。如果我们只处理基本属性(字段,而不是关系,ecc),这似乎是可能的。例如对于创建和更新,OData将不接受整个早期绑定类,只传递attibutes:

    class Program
{
    static void Main(string[] args)
    {
        string token = System.Threading.Tasks.Task.Run(() => GetToken()).Result;
        CRMWebAPI dynamicsWebAPI = new CRMWebAPI("https:/ORG.api.crm4.dynamics.com/api/data/v9.1/",
                token);


        CRMGetListOptions listOptions = new CRMGetListOptions
        {
            Select = new string[] { "EntitySetName" },
            Filter = "LogicalName eq 'contact'"
        };

        dynamic entityDefinitions = dynamicsWebAPI.GetList<ExpandoObject>("EntityDefinitions", listOptions).Result;

        Contact contact = new Contact
        {
            FirstName = "Felipe",
            LastName = "Test",
            MobilePhone = "38421254"
        };

        dynamic ret = System.Threading.Tasks.Task.Run(async () => await dynamicsWebAPI.Create(entityDefinitions.List[0].EntitySetName, KeyPairValueToObject(contact.Attributes))).Result;



}

    public static async Task<string> GetToken()
    {
        string api = "https://ORG.api.crm4.dynamics.com/";

        ClientCredential credential = new ClientCredential("CLIENT_ID", "CLIENT_SECRET");

        AuthenticationContext authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/commom/oauth2/authorize");
        return authenticationContext.AcquireTokenAsync(api, credential).Result.AccessToken;

    }

    public static object KeyPairValueToObject(AttributeCollection keyValuePairs)
    {
        dynamic expando = new ExpandoObject();
        var obj = expando as IDictionary<string, object>;
        foreach (var keyValuePair in keyValuePairs)
            obj.Add(keyValuePair.Key,  keyValuePair.Value);
        return obj;

    }
}
所以,它是模式名,而不是字段名。如果在设置字段名时使用CamelCase,则在何处出现问题。我们可以用(那个可爱的)代码来解决这个问题

公共静态对象EntityToObject(T实体),其中T:entity
{
动态expando=新的ExpandoObject();
var obj=扩展为IDictionary;
foreach(entity.Attributes中的var keyValuePair)
{
添加(GetFieldName(实体,keyValuePair),CastenityAttitButesValueOnDynamicObject(keyValuePair.Value));
}
返回obj;
}
公共静态对象CastEntityAttitsValueOnDynamicObject(对象属性值)
{
if(attributeValue.GetType().Name==“EntityReference”)
{
CRMGetListOptions列表选项=新的CRMGetListOptions
{
Select=新字符串[]{“EntitySetName”},
筛选器=$“LogicalName eq'{((EntityReference)attributeValue).LogicalName}'”
};
dynamic entitySetName=dynamicsWebAPI.GetList(“EntityDefinitions”,listOptions).Result.List[0];
返回$“/{entitySetName.entitySetName}({((EntityReference)attributeValue.Id})”;
}
else if(attributeValue.GetType().Name==“OptionSetValue”)
{
返回((OptionSetValue)attributeValue).Value;
}
else if(attributeValue.GetType().Name==“DateTime”)
{
return((DateTime)attributeValue).ToString(“yyyy-MM-dd”);
}
else if(attributeValue.GetType().Name==“Money”)
{
返回((货币)属性值);
}
else if(attributeValue.GetType().Name==“AliasedValue”)
{
返回CastEntityAttitsValueOnDynamicObject(((AliasedValue)attributeValue).Value);
}
其他的
{
返回属性值;
}
}
公共静态字符串GetFieldName(T实体,KeyValuePair KeyValuePair),其中T:entity
{
开关(keyValuePair.Value.GetType().Name)
{
案例“实体参考”:
var entityNameList=System.Threading.Tasks.Task.Run(异步()=>await dynamicsWebAPI.GetEntityDisplayNameList()).Result;
var firstEntity=entityNameList.Where(x=>x.LogicalName==entity.LogicalName).FirstOrDefault();
var attrNameList=System.Threading.Tasks.Task.Run(异步()=>await dynamicsWebAPI.GetAttributeDisplayNameList(firstEntity.MetadataId)).Result;
返回attrNameList.Where(x=>x.LogicalName==keyValuePair.Key).Single().SchemaName+“@odata.bind”;
案例“活动当事人”:
抛出新的NotImplementedException();//TODO
违约:
返回keyValuePair.Key;
}
}
请注意,无论如何,这种方法看起来并不快或好。最好将所有这些值都设置为静态,这样我们就可以保存一些回迁

[编辑2]

我刚刚在XRMToolBox上发现了一个名为“Web API早期绑定生成器”的插件,它似乎是最好的选择。如果你仍然对此感到好奇,也许你应该试一试。我想这是最好的办法。 最终代码如下:

        static void Main(string[] args)
    {
        string token = Task.Run(() => GetToken()).Result;
        dynamicsWebAPI = new CRMWebAPI("https://ORG.api.crm4.dynamics.com/api/data/v9.1/",
                token);

        Contact contact = new Contact
        {
            FirstName = "Felipe",
            LastName = "Test",
            MobilePhone = "38421254",
            new_Salutation = new EntityReference(new_salutation.EntitySetName, new Guid("{BFA27540-7BB9-E611-80EE-FC15B4281C8C}")),
            BirthDate = new DateTime(1993, 04, 14),
        };

        dynamic ret = Task.Run(async () => await dynamicsWebAPI.Create(Contact.EntitySetName, contact.ToExpandoObject())).Result;
        Contact createdContact = dynamicsWebAPI.Get<Contact>(Contact.EntitySetName, ret, new CRMGetListOptions
        {
            Select = new string[] { "*" }
        }).Result;
    }
static void Main(字符串[]args)
{
字符串标记=Task.Run(()=>GetToken()).Result;
dynamicsWebAPI=新的CRMWebAPI(“https://ORG.api.crm4.dynamics.com/api/data/v9.1/",
代币);
联系人=新联系人
{
FirstName=“Felipe”,
LastName=“测试”,
MobilePhone=“38421254”,
new_saltation=new EntityReference(new_saltation.EntitySetName,new Guid({BFA27540-7BB9-E611-80EE-FC15B4281C8C})),
生日=新的日期时间(1993年4月14日),
};
dynamic ret=Task.Run(异步()=>等待dynamicsWebAPI.Create(Contact.EntitySetName,Contact.toexpandooobject()).Result;
Contact createdContact=dynamicsWebAPI.Get(Contact.EntitySetName,ret,new-CRMGetListOptions
{
选择=新字符串[]{“*”}
}).结果;
}
您必须更改Entity.cs类(由插件生成)上的ToExpandooObject

public ExpandoObject to ExpandoObject()
{
动态expando=新的ExpandoObject();
var expandoObject=expando作为IDictionary;
foreach(属性中的var属性)
{
如果(attributes.Key==GetIdAttribute())
{
持续
}
var值=attributes.value;
var key=attributes.key;
if(值为EntityReference EntityReference)
{
值=$“/{entityReference.EntitySetName}({entityReference.EntityId})”;
}
其他的
{
key=key.ToLower();
如果(值为DateTime dateTimeValue)
{
var propertyForAttribute=GetPublicInstanc
        public static object EntityToObject<T>(T entity) where T : Entity
    {
        dynamic expando = new ExpandoObject();
        var obj = expando as IDictionary<string, object>;
        foreach (var keyValuePair in entity.Attributes)
        {
            obj.Add(GetFieldName(entity, keyValuePair), CastEntityAttibutesValueOnDynamicObject(keyValuePair.Value));
        }
        return obj;

    }

    public static object CastEntityAttibutesValueOnDynamicObject(object attributeValue)
    {
        if (attributeValue.GetType().Name == "EntityReference")
         {
            CRMGetListOptions listOptions = new CRMGetListOptions
            {
                Select = new string[] { "EntitySetName" },
                Filter = $"LogicalName eq '{((EntityReference)attributeValue).LogicalName}'"
            };

            dynamic entitySetName = dynamicsWebAPI.GetList<ExpandoObject>("EntityDefinitions", listOptions).Result.List[0];

            return $"/{entitySetName.EntitySetName}({((EntityReference)attributeValue).Id})";
        }
        else if (attributeValue.GetType().Name == "OptionSetValue")
        {
            return ((OptionSetValue)attributeValue).Value;
        }
        else if (attributeValue.GetType().Name == "DateTime")
        {
            return ((DateTime)attributeValue).ToString("yyyy-MM-dd");
        }
        else if (attributeValue.GetType().Name == "Money")
        {
            return ((Money)attributeValue).Value;
        }
        else if (attributeValue.GetType().Name == "AliasedValue")
        {
            return CastEntityAttibutesValueOnDynamicObject(((AliasedValue)attributeValue).Value);
        }
        else
        {
            return attributeValue;
        }
    }

    public static string GetFieldName<T>(T entity, KeyValuePair<string, object> keyValuePair) where T : Entity
    {
        switch (keyValuePair.Value.GetType().Name)
        {
            case "EntityReference":
                var entityNameList = System.Threading.Tasks.Task.Run(async () => await dynamicsWebAPI.GetEntityDisplayNameList()).Result;

                var firstEntity = entityNameList.Where(x => x.LogicalName == entity.LogicalName).FirstOrDefault();

                var attrNameList = System.Threading.Tasks.Task.Run(async () => await dynamicsWebAPI.GetAttributeDisplayNameList(firstEntity.MetadataId)).Result;

                return attrNameList.Where(x => x.LogicalName == keyValuePair.Key).Single().SchemaName + "@odata.bind";
            case "ActivityParty":
                throw new NotImplementedException(); //TODO
            default:
                return keyValuePair.Key;
        }
    }
        static void Main(string[] args)
    {
        string token = Task.Run(() => GetToken()).Result;
        dynamicsWebAPI = new CRMWebAPI("https://ORG.api.crm4.dynamics.com/api/data/v9.1/",
                token);

        Contact contact = new Contact
        {
            FirstName = "Felipe",
            LastName = "Test",
            MobilePhone = "38421254",
            new_Salutation = new EntityReference(new_salutation.EntitySetName, new Guid("{BFA27540-7BB9-E611-80EE-FC15B4281C8C}")),
            BirthDate = new DateTime(1993, 04, 14),
        };

        dynamic ret = Task.Run(async () => await dynamicsWebAPI.Create(Contact.EntitySetName, contact.ToExpandoObject())).Result;
        Contact createdContact = dynamicsWebAPI.Get<Contact>(Contact.EntitySetName, ret, new CRMGetListOptions
        {
            Select = new string[] { "*" }
        }).Result;
    }
        public ExpandoObject ToExpandoObject()
    {
        dynamic expando = new ExpandoObject();
        var expandoObject = expando as IDictionary<string, object>;
        foreach (var attributes in Attributes)
        {
            if (attributes.Key == GetIdAttribute())
            {
                continue;
            }

            var value = attributes.Value;
            var key = attributes.Key;

            if (value is EntityReference entityReference)
            {
                value = $"/{entityReference.EntitySetName}({entityReference.EntityId})";
            }
            else
            {
                key = key.ToLower();

                if (value is DateTime dateTimeValue)
                {
                    var propertyForAttribute = GetPublicInstanceProperties().FirstOrDefault(x =>
                        x.Name.Equals(key, StringComparison.InvariantCultureIgnoreCase));

                    if (propertyForAttribute != null)
                    {
                        var onlyDateAttr = propertyForAttribute.GetCustomAttribute<OnlyDateAttribute>();

                        if (onlyDateAttr != null)
                        {
                            value = dateTimeValue.ToString(OnlyDateAttribute.Format);
                        }
                    }
                }
            }

            expandoObject.Add(key, value);
        }

        return (ExpandoObject)expandoObject;
    }