simple-odata-client / Simple.OData.Client

MIT License
331 stars 197 forks source link

Dynamics CRM email activity parties #556

Open twastvedt opened 5 years ago

twastvedt commented 5 years ago

I'm trying to use Simple.OData.Client to create a draft email activity in Dynamics 365 CRM. Everything is working except for setting the "to" and "from", in Dynamics these are activitypartys. The email entity has a navigation property collection called email_activity_parties, but the activitypartys can't be created independently from an email entity. So when creating the email I need to also be able to send the nested activityparty objects, not just link to their IDs.

My POST request body should look something like this:

{
    "@odata.type": "#Microsoft.Dynamics.CRM.email",
    "subject": "Email subject",
    "description": "Email text",
    "regardingobjectid_opportunity@odata.bind": "https://endpoint/opportunities(<guid>)",
    "email_activity_parties": [
        {
            "partyid_systemuser@odata.bind" = "https://endpoint/systemuser(<guid>)",
            participationtypemask = 1
        },
        {
            "partyid_contact@odata.bind" = "https://endpoint/systemuser(<guid>)",
            participationtypemask = 2
        }
    ]
}

I'm not sure how to get Simple.OData.Client to create those parties though. I thought it should be this:

client.For<CRM.email>().Set(new
{
    subject = "Email subject",
    description = "Email description",
    regardingobjectid_opportunity = new { opportunityId },
    email_activity_parties = new List<dynamic>() {
        new CRM.activityparty
        {
            partyid_systemuser = new CRM.systemuser { ownerid },
            participationtypemask = 1
        },
        new CRM.activityparty
        {
            partyid_contact = new CRM.contact { contactid },
            participationtypemask = 2
        }}
};

(CRM.* are simple objects I created by hand to match the CRM api.)

But because activityparty is an entity type, Simple.OData.Client generates the following body from that:

{
    "@odata.type": "#Microsoft.Dynamics.CRM.email",
    "subject": "Email subject",
    "description": "Email text",
    "regardingobjectid_opportunity@odata.bind": "https://tenant.crm.dynamics.com/api/data/v9.0/opportunities(<guid>)",
    "email_activity_parties@odata.bind": [
        "https://tenant.crm.dynamics.com/api/data/v9.0/activityparties(00000000-0000-0000-0000-000000000000)",
        "https://tenant.crm.dynamics.com/api/data/v9.0/activityparties(00000000-0000-0000-0000-000000000000)"
    ]
}

I suspect this is related to #175, and so might not be possible. I'm very new to OData, but it seems to me that an activityparty is an entity type, but needs to be created as a complex type?

object commented 5 years ago

@twastvedt Can you paste extract from the service metadata that shows definitions for OData entities and types involved in your operations?

twastvedt commented 5 years ago

OK. I'm still pretty new to OData, so I'm not entirely sure what's relevant. Let me know if there's something I'm missing. All of the below are nested under the following:

<?xml version="1.0" encoding="UTF-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
    <script/>
    <edmx:Reference Uri="http://vocabularies.odata.org/OData.Community.Keys.V1.xml">
        <edmx:Include Namespace="OData.Community.Keys.V1" Alias="Keys"/>
        <edmx:IncludeAnnotations TermNamespace="OData.Community.Keys.V1"/>
    </edmx:Reference>
    <edmx:Reference Uri="http://vocabularies.odata.org/OData.Community.Display.V1.xml">
        <edmx:Include Namespace="OData.Community.Display.V1" Alias="Display"/>
        <edmx:IncludeAnnotations TermNamespace="OData.Community.Display.V1"/>
    </edmx:Reference>
    <edmx:DataServices>
        <Schema Namespace="Microsoft.Dynamics.CRM" Alias="mscrm" xmlns="http://docs.oasis-open.org/odata/ns/edm">

Here's the relevant part of the email entity:

<EntityType Name="email" BaseType="mscrm.activitypointer">
    <Key>
        <PropertyRef Name="activityid"/>
    </Key>
    ...
    <NavigationProperty Name="email_activity_parties" Type="Collection(mscrm.activityparty)" Partner="activityid_email"/>
    ...
</EntityType>

And here's the whole activityparty:

<EntityType Name="activityparty" BaseType="mscrm.crmbaseentity">
    <Key>
        <PropertyRef Name="activitypartyid"/>
    </Key>
    <Property Name="addressused" Type="Edm.String" Unicode="false"/>
    <Property Name="donotphone" Type="Edm.Boolean"/>
    <Property Name="donotpostalmail" Type="Edm.Boolean"/>
    <Property Name="scheduledstart" Type="Edm.DateTimeOffset"/>
    <Property Name="donotfax" Type="Edm.Boolean"/>
    <Property Name="ispartydeleted" Type="Edm.Boolean"/>
    <Property Name="_activityid_value" Type="Edm.Guid"/>
    <Property Name="participationtypemask" Type="Edm.Int32"/>
    <Property Name="scheduledend" Type="Edm.DateTimeOffset"/>
    <Property Name="instancetypecode" Type="Edm.Int32"/>
    <Property Name="versionnumber" Type="Edm.Int64"/>
    <Property Name="addressusedemailcolumnnumber" Type="Edm.Int32"/>
    <Property Name="_resourcespecid_value" Type="Edm.Guid"/>
    <Property Name="effort" Type="Edm.Double"/>
    <Property Name="_partyid_value" Type="Edm.Guid"/>
    <Property Name="exchangeentryid" Type="Edm.String" Unicode="false"/>
    <Property Name="activitypartyid" Type="Edm.Guid"/>
    <Property Name="donotemail" Type="Edm.Boolean"/>
    <Property Name="_ownerid_value" Type="Edm.Guid"/>
    <NavigationProperty Name="partyid_entitlement" Type="mscrm.entitlement" Nullable="false" Partner="entitlement_ActivityParties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="entitlementid"/>
    </NavigationProperty>
    <NavigationProperty Name="partyid_campaignactivity" Type="mscrm.campaignactivity" Nullable="false" Partner="campaignactivity_activityparties"/>
    <NavigationProperty Name="partyid_incident" Type="mscrm.incident" Nullable="false" Partner="incident_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="incidentid"/>
    </NavigationProperty>
    <NavigationProperty Name="activityid_serviceappointment" Type="mscrm.serviceappointment" Nullable="false" Partner="serviceappointment_activity_parties"/>
    <NavigationProperty Name="ActivityParty_SyncErrors" Type="Collection(mscrm.syncerror)" Partner="regardingobjectid_activityparty_syncerror"/>
    <NavigationProperty Name="activityid_recurringappointmentmaster" Type="mscrm.recurringappointmentmaster" Nullable="false" Partner="recurringappointmentmaster_activity_parties"/>
    <NavigationProperty Name="partyid_invoice" Type="mscrm.invoice" Nullable="false" Partner="invoice_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="invoiceid"/>
    </NavigationProperty>
    <NavigationProperty Name="partyid_contract" Type="mscrm.contract" Nullable="false" Partner="contract_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="contractid"/>
    </NavigationProperty>
    <NavigationProperty Name="activityid_campaignactivity" Type="mscrm.campaignactivity" Nullable="false" Partner="campaignactivity_activity_parties"/>
    <NavigationProperty Name="activityid_socialactivity" Type="mscrm.socialactivity" Nullable="false" Partner="socialactivity_activity_parties"/>
    <NavigationProperty Name="activityid_po_mailchimpactivity_activityparty" Type="mscrm.po_mailchimpactivity" Nullable="false" Partner="po_mailchimpactivity_activity_parties"/>
    <NavigationProperty Name="activityid_appointment" Type="mscrm.appointment" Nullable="false" Partner="appointment_activity_parties"/>
    <NavigationProperty Name="partyid_queue" Type="mscrm.queue" Nullable="false" Partner="queue_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="queueid"/>
    </NavigationProperty>
    <NavigationProperty Name="partyid_systemuser" Type="mscrm.systemuser" Nullable="false" Partner="system_user_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="systemuserid"/>
    </NavigationProperty>
    <NavigationProperty Name="activityid_fax" Type="mscrm.fax" Nullable="false" Partner="fax_activity_parties"/>
    <NavigationProperty Name="partyid_salesorder" Type="mscrm.salesorder" Nullable="false" Partner="salesorder_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="salesorderid"/>
    </NavigationProperty>
    <NavigationProperty Name="activityid_phonecall" Type="mscrm.phonecall" Nullable="false" Partner="phonecall_activity_parties"/>
    <NavigationProperty Name="activityid_task" Type="mscrm.task" Nullable="false" Partner="task_activity_parties"/>
    <NavigationProperty Name="activityid_campaignresponse" Type="mscrm.campaignresponse" Nullable="false" Partner="campaignresponse_activity_parties"/>
    <NavigationProperty Name="activityid_quoteclose" Type="mscrm.quoteclose" Nullable="false" Partner="quoteclose_activity_parties"/>
    <NavigationProperty Name="resourcespecid" Type="mscrm.resourcespec" Nullable="false" Partner="ActivityPartyResourceSpec">
        <ReferentialConstraint Property="_resourcespecid_value" ReferencedProperty="resourcespecid"/>
    </NavigationProperty>
    <NavigationProperty Name="activityid_letter" Type="mscrm.letter" Nullable="false" Partner="letter_activity_parties"/>
    <NavigationProperty Name="activityid_orderclose" Type="mscrm.orderclose" Nullable="false" Partner="orderclose_activity_parties"/>
    <NavigationProperty Name="partyid_bulkoperation" Type="mscrm.bulkoperation" Nullable="false" Partner="bulkoperation_activity_parties"/>
    <NavigationProperty Name="partyid_quote" Type="mscrm.quote" Nullable="false" Partner="quote_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="quoteid"/>
    </NavigationProperty>
    <NavigationProperty Name="activityid_email" Type="mscrm.email" Nullable="false" Partner="email_activity_parties"/>
    <NavigationProperty Name="partyid_knowledgearticle" Type="mscrm.knowledgearticle" Nullable="false" Partner="knowledgearticle_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="knowledgearticleid"/>
    </NavigationProperty>
    <NavigationProperty Name="partyid_lead" Type="mscrm.lead" Nullable="false" Partner="lead_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="leadid"/>
    </NavigationProperty>
    <NavigationProperty Name="activityid_opportunityclose" Type="mscrm.opportunityclose" Nullable="false" Partner="opportunityclose_activity_parties"/>
    <NavigationProperty Name="activityid_new_approval_activityparty" Type="mscrm.new_approval" Nullable="false" Partner="new_approval_activity_parties"/>
    <NavigationProperty Name="partyid_new_humanresources" Type="mscrm.new_humanresources" Nullable="false" Partner="new_humanresources_ActivityParties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="new_humanresourcesid"/>
    </NavigationProperty>
    <NavigationProperty Name="partyid_equipment" Type="mscrm.equipment" Nullable="false" Partner="equipment_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="equipmentid"/>
    </NavigationProperty>
    <NavigationProperty Name="partyid_opportunity" Type="mscrm.opportunity" Nullable="false" Partner="opportunity_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="opportunityid"/>
    </NavigationProperty>
    <NavigationProperty Name="partyid_campaign" Type="mscrm.campaign" Nullable="false" Partner="campaign_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="campaignid"/>
    </NavigationProperty>
    <NavigationProperty Name="partyid_account" Type="mscrm.account" Nullable="false" Partner="account_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="accountid"/>
    </NavigationProperty>
    <NavigationProperty Name="activityid_incidentresolution" Type="mscrm.incidentresolution" Nullable="false" Partner="incidentresolution_activity_parties"/>
    <NavigationProperty Name="activityid_activitypointer" Type="mscrm.activitypointer" Nullable="false" Partner="activitypointer_activity_parties">
        <ReferentialConstraint Property="_activityid_value" ReferencedProperty="activityid"/>
    </NavigationProperty>
    <NavigationProperty Name="partyid_contact" Type="mscrm.contact" Nullable="false" Partner="contact_activity_parties">
        <ReferentialConstraint Property="_partyid_value" ReferencedProperty="contactid"/>
    </NavigationProperty>
</EntityType>

There's also an activityparties entity set. Not sure if this gets involved.

<EntityContainer Name="System">
...
    <EntitySet Name="activityparties" EntityType="Microsoft.Dynamics.CRM.activityparty">
        <NavigationPropertyBinding Path="partyid_entitlement" Target="entitlements"/>
        <NavigationPropertyBinding Path="partyid_campaignactivity" Target="campaignactivities"/>
        <NavigationPropertyBinding Path="partyid_incident" Target="incidents"/>
        <NavigationPropertyBinding Path="activityid_serviceappointment" Target="serviceappointments"/>
        <NavigationPropertyBinding Path="ActivityParty_SyncErrors" Target="syncerrors"/>
        <NavigationPropertyBinding Path="activityid_recurringappointmentmaster" Target="recurringappointmentmasters"/>
        <NavigationPropertyBinding Path="partyid_invoice" Target="invoices"/>
        <NavigationPropertyBinding Path="partyid_contract" Target="contracts"/>
        <NavigationPropertyBinding Path="activityid_campaignactivity" Target="campaignactivities"/>
        <NavigationPropertyBinding Path="activityid_socialactivity" Target="socialactivities"/>
        <NavigationPropertyBinding Path="activityid_po_mailchimpactivity_activityparty" Target="po_mailchimpactivities"/>
        <NavigationPropertyBinding Path="activityid_appointment" Target="appointments"/>
        <NavigationPropertyBinding Path="partyid_queue" Target="queues"/>
        <NavigationPropertyBinding Path="partyid_systemuser" Target="systemusers"/>
        <NavigationPropertyBinding Path="activityid_fax" Target="faxes"/>
        <NavigationPropertyBinding Path="partyid_salesorder" Target="salesorders"/>
        <NavigationPropertyBinding Path="activityid_phonecall" Target="phonecalls"/>
        <NavigationPropertyBinding Path="activityid_task" Target="tasks"/>
        <NavigationPropertyBinding Path="activityid_campaignresponse" Target="campaignresponses"/>
        <NavigationPropertyBinding Path="activityid_quoteclose" Target="quotecloses"/>
        <NavigationPropertyBinding Path="resourcespecid" Target="resourcespecs"/>
        <NavigationPropertyBinding Path="activityid_letter" Target="letters"/>
        <NavigationPropertyBinding Path="activityid_orderclose" Target="ordercloses"/>
        <NavigationPropertyBinding Path="partyid_bulkoperation" Target="bulkoperations"/>
        <NavigationPropertyBinding Path="partyid_quote" Target="quotes"/>
        <NavigationPropertyBinding Path="activityid_email" Target="emails"/>
        <NavigationPropertyBinding Path="partyid_knowledgearticle" Target="knowledgearticles"/>
        <NavigationPropertyBinding Path="partyid_lead" Target="leads"/>
        <NavigationPropertyBinding Path="activityid_opportunityclose" Target="opportunitycloses"/>
        <NavigationPropertyBinding Path="activityid_new_approval_activityparty" Target="new_approvals"/>
        <NavigationPropertyBinding Path="partyid_new_humanresources" Target="new_humanresourceses"/>
        <NavigationPropertyBinding Path="partyid_equipment" Target="equipments"/>
        <NavigationPropertyBinding Path="partyid_opportunity" Target="opportunities"/>
        <NavigationPropertyBinding Path="partyid_campaign" Target="campaigns"/>
        <NavigationPropertyBinding Path="partyid_account" Target="accounts"/>
        <NavigationPropertyBinding Path="activityid_incidentresolution" Target="incidentresolutions"/>
        <NavigationPropertyBinding Path="activityid_activitypointer" Target="activitypointers"/>
        <NavigationPropertyBinding Path="partyid_contact" Target="contacts"/>
    </EntitySet>
dvidvi commented 4 years ago

@twastvedt I am a bit late to the party... but were you able to resolve the issue? I am facing similar problems myself.

twastvedt commented 4 years ago

oh boy. I don't think I ever got this working, but two years, a new job, and several projects later, I'm afraid I don't remember details of my attempts after this post. Sorry!

dvidvi commented 4 years ago

It was a long shot, but worth a try nonetheless. Thanks for getting back to me so promptly.

Yannick-DG commented 9 months ago

Hi @object ,

Sorry for tagging you, but this library is quite important for our project. We've noticed lately that this issue is still occurring to us. Is there a possible workaround or such to get this working? Otherwise we'll have to do a manual HTTP call, which defeats the purpose of this library. Is there a possibility that this could get fixed or is it too roughly made inside the code?

atsimourtos commented 3 weeks ago

I also have that problem, when trying to update an email's entity email_activity_parties, odata translaes the PATCH body request into the following. Now that's a problem because when the email entity is created From and To entities are not set therefore users do not have the option to know basic information about the email.


{
    "@odata.type": "#Microsoft.Dynamics.CRM.email",
    "email_activity_parties@odata.bind": [
        "https://domain.dynamics.com/api/data/v9.2/activityparties(null)",
        "https://domain.dynamics.com/api/data/v9.2/activityparties(null)"
    ]
}

The working one is the following which works through post man

{
    "@odata.type": "#Microsoft.Dynamics.CRM.email",
    "email_activity_parties": [
        {
            "participationtypemask": 2,
            "partyid_account@odata.bind": "/accounts(f6784e78-50f2-45b7-9a71-77fdf0f377a7)"
        },
        {
            "participationtypemask": 1,
            "partyid_queue@odata.bind": "/queues(cd90178b-1f8c-ed11-81ad-000d3adf7b4b)"
        }
    ]
}