CRM do not support direct update of Entity Reference properties, Use Navigation properties instead - dynamics-crm

I am using Ms Dynamic Web Api with Simple OData. I need to add new record for link entities.
I am using the below code snip and refer the documentation on
https://github.com/object/Simple.OData.Client/wiki/Adding-entries-with-links
var newContactData = await _oDataClient
.For<Contacts>()
.Set(new
{
firstname = contactData.ContatDetails.firstname,
lastname = contactData.ContatDetails.lastname,
emailaddress1 = contactData.ContatDetails.emailaddress1
})
.InsertEntryAsync(true);
var newContactLink = await _oDataClient.For<New_project_contactses>()
.Set(new
{
_new_contact_project_name_new_value = contactData.ContatDetailsLink._new_contact_project_name_new_value,
new_project_contactsid = new Guid("0eb46b24-21a2-e611-80eb-c4346bc5b2d4"),
new_contact_type = contactData.ContatDetailsLink.new_contact_type,
})
.InsertEntryAsync(resultRequired: true);
i am getting exception
CRM do not support direct update of Entity Reference properties, Use
Navigation properties insteadS

Well, it is possible, but you need to use the special "#odata.bind" syntax to update your single-navigation properties.
For example, to update an account so that it references an existing primarycontactid, you can use a PATCH operation to the /api/data/v8.2/accounts endpoint with the following body:
{
"name":"Sample Account",
"primarycontactid#odata.bind":"/contacts(00000000-0000-0000-0000-000000000001)"
}
See https://msdn.microsoft.com/en-us/library/gg328090.aspx#Anchor_3 (it is discussed in terms of creating an entity, but it works for updating as well).

I figure out the issue With Dynamc CRM you cannot directly update reference entities Field. You can identify reference entity properties start with "_".

Related

XrmServiceContext object is not getting the latest data from CRM

i have a wcf which connects to crm (on prem) to retrieve an account record. i can see when the entity is retrieved it does not hold the current record i.e. some field will still hold the old column value. i tried with various merge option with no avail. please see the code below
using (XrmServiceContext cContext = new XrmServiceContext(con))
{
Entity ent = cContext.Retrieve(ConstantKVP.AccountSchema.ENTITY_LOGICAL_NAME, AccountId, new ColumnSet(true));
}
any suggestions?
Is it possible the data is being cached?
cContext.TryAccessCache(cache => cache.Mode = OrganizationServiceCacheMode.Disabled);
I took this approach for a CrmOrganizationServiceContext, so perhaps the same theory applies.
After save use clear changes cContext.ClearChanges();
For retrieves use MergeOption.OverwriteChanges
Or
Create a new XrmServiceContext object by passing a newed up organizationservice:
var uncachedOrganizationService = new OrganizationService("Xrm");
var uncachedXrmServiceContext = new XrmServiceContext(uncachedOrganizationService);
var ent = uncachedXrmServiceContext.Retrieve(ConstantKVP.AccountSchema.ENTITY_LOGICAL_NAME,AccountId,new ColumnSet(true));

EWS Managed API 2.2 Read\Write extended properties of attachments

Currently I'm working on migration of one big project from MAPI CDO to EWS (Managed API 2.2) to support Ex2016. All things were migrated well except one: I can't find the way how to read\write Attachments Extended Properties. Does anybody know how to do that or may be some workaround? This is very critical for me and I would be very appreciate for any help.
---Update:
Also tried to use native EWS to get property of attachment but without success too:
var ret = esb.GetAttachment(new GetAttachmentType()
{
AttachmentIds = new []{new AttachmentIdType()
{
Id = "AAMkADVhNjUzMzMyLTRiMDYtNDc4OS1hYjJjLWI1ZDA4ZWFhYTJkZQBGAAAAAADqFaOFYZSeQI5UObwGbjIJBwAOgaos6ORVS5+o5bQovn/kAAAAeN2cAAAOgaos6ORVS5+o5bQovn/kAAAeCoIuAAABEgAQAJPAuRg2gipPmEKfgW26mFU=",
}},
AttachmentShape = new AttachmentResponseShapeType()
{
BodyType = BodyTypeResponseType.Best,
BodyTypeSpecified = true,
IncludeMimeContent = false,
IncludeMimeContentSpecified = true,
AdditionalProperties = new []
{
new PathToExtendedFieldType() { PropertyType = MapiPropertyTypeType.Integer, PropertyTag = "0x3705"},
new PathToExtendedFieldType() { PropertyType = MapiPropertyTypeType.Integer, PropertyTag = "0x0E21"},
}
}
});
The response doesn't contain any of requested properties.
--- Update 2:
In project we use next properties of attachments:
PR_RECORD_KEY, PR_DISPLAY_NAME, PR_RENDERING_POSITION
PR_ATTACH_ENCODING, PR_ATTACH_NUM, PR_ATTACH_METHOD, PR_ATTACH_LONG_FILENAME, PR_ATTACHMENT_HIDDEN, PR_ATTACH_CONTENT_ID, PR_ATTACH_FLAGS, PR_ATTACH_MIME_TAG, PR_ATTACH_CONTENT_LOCATION, PR_ATTACH_SIZE
Also we create a couple of Custom Extended Properties with custom Property Set and tag some attachments with that props.
Some of Properties can be found in object model of EWS/ManagedApi like PR_ATTACH_SIZE but the problem with others and with custom props.
So we need to read/write standard attachment properties as well as custom.
In project we mark attachment itself, not embedded Item.
You can't access extended properties on Attachments or the Recipients collection in EWS outside of those properties that are made accessible as strongly typed properties by the API. The only place you can use Extended properties are at the message level.
That said can you explain more as to how your using Extended properties eg are these extended properties on embeded items. If that is the case then you could access those extended properties via the Item Attachment.
Looking at your code 0x3705 is the PR_ATTACH_METHOD property on an attachment there is no equivalent to this in EWS, rather EWS will return a different Attachment Class based on the Attachment type. Eg ItemAttachment, FileAttachment or ReferanceAttachment (eg for OneDrive Attachments). 0x0E21 is that Attachment number EWS is going to return the Attachments in the order of that number in GetItem request so you can compute that yourself. But the property is useless in EWS because to get an Attachment you need the EWSId unlike MAPI.
Cheers
Glen

Add a note using the OOB dialog from a webresource

Im working with Microsoft Dynamics CRM. The client is requesting to be able to add notes from a webresources.
I thought that something like this will do the trick:
Xrm.Utility.openEntityForm("annotation", null, parameters);
or even the classic
/main.aspx?etn=annotation&pagetype=entityrecord#
But I receive a "Query Builder Error: The specified record type does not exist in Microsoft Dynamics CRM"
It seems like notes is not something we can open in that way but I cannot found the right way (if even exists!)
Any help?
Maybe this can help someone in the future: This will open a dialog with the Regarding field filled, the textboxs for title and description and the attachments field.
function createNote() {
var EntityID = Xrm.Page.data.entity.getId(); // to get entity id
var ServicerURL = Xrm.Page.context.getClientUrl(); // to get server url
var etc =Xrm.Page.context.getQueryStringParameters().etc; // to get entity type code, make sure not to hard code it, because it could changed in another deployment
var NotesURL = ServicerURL + "/notes/edit.aspx?pId=" + EntityID + "&pType=" + etc;
var features = "copyhistory=no,top=110,left=280,width=600,height=400";
window.open(NotesURL, "", features);
}

What is the correct way to call patch from an OData client in Web Api 2

Following the OData samples created by the web api team, my controller has the following for supporting Patch:
public HttpResponseMessage Patch([FromODataUri] int key, Delta<Foo> item)
{
var dbVersion = myDb.GetById(key);
if(dbVersion == null)
throw Request.EntityNotFound();
item.Patch(dbVersion);
myDb.Update(dbVersion);
return Request.CreateResponse(HttpStatusCode.NoContent);
}
and using the auto-generated client (derived from DataServiceContext), I submit a patch request like this:
var foo = svcContainer.Foos.Where (f => f.Id == 1).SingleOrDefault();
foo.Description = "Updated Description";
svcContainer.UpdateObject(foo);
svcContainer.SaveChanges(SaveChangesOptions.PatchOnUpdate);
However, tracing the call in fiddler, I see that all other properties of Foo are serialized and sent to the service. Is that the correct behavior? I expected only the Id and Description to be sent over the wire. Also, if I debug the service method and call
GetChangedPropertyNames on item, all its property names are returned.
Should I be creating some sort of Delta instance on the client?
I understand the disconnected nature of the service and thus the service side does not have a context for tracking changes, but it seems to me the api team added support for patch for a reason, so I'd like to know if the client ought to be invoking the update in a different manner.
Update
The link YiDing provided explains how to create a true PATCH request from the client (using the Microsoft.OData.Client.DataServiceContext created by the Microsoft.OData.Client 6.2.0 and above.
For convenience, here is the code snippet:
var svcContainer = new Default.Container(<svcUri>);
var changeTracker = new DataServiceCollection<Foo>(svcContainer.Foos.Where(f => f.Id == 1));
changeTracker[0].Description = "Patched Description";
svcContainer.SaveChanges();
The DataServiceCollection implements property tracking, and using this pattern, only the updated properties are sent to the service.
Without using DataServiceCollection and simply using
svcContainer.UpdateObject(foo);
svcContainer.SaveChanges();
all properties are still sent over the wire despite documentation to the contrary, at least as of Microsoft.OData.Client 6.7.0
The client side property tracking is now supported from Microsoft.OData.Client version 6.2.0. It will detect only the modified properties of an entity and send the update request as PATCH instead of PUT to meet the requirement of your scenario. Please refer to this blog post for more details:
https://devblogs.microsoft.com/odata/tutorial-sample-client-property-tracking-for-patch/

Dynamics CRM saving Entity Changes - Getting Errors

I'm really scratching my head with this. I'm trying to use the Dynamics CRM SDK to update an account record. No matter what I try, it's failing. Here goes.
Account sampleAccount = CrmAccount.GetAccountsBySubmissionCode(crmService, "ERZZUP").Single<Account>();
sampleAccount.Name = "AMC Edited";
crmService.Update(sampleAccount);
Gives the error: EntityState must be set to null, Created (for Create message) or Changed (for Update message)
XrmServiceContext ctx = new XrmServiceContext(crmService);
Account sampleAccount = CrmAccount.GetAccountsBySubmissionCode(crmService, "ERZZUP").Single<Account>();
sampleAccount.Name = "AMC Edited";
ctx.UpdateObject(sampleAccount);
ctx.SaveChanges();
Gives the error: The context is not currently tracking the 'account' entity.
XrmServiceContext ctx = new XrmServiceContext(crmService);
Account sampleAccount = CrmAccount.GetAccountsBySubmissionCode(crmService, "ERZZUP").Single<Account>();
sampleAccount.Name = "AMC Edited";
ctx.Attach(sampleAccount);
ctx.UpdateObject(sampleAccount);
ctx.SaveChanges();
Gives the error: The 'account' entity is already attached to a context.
For reference,
1. The Account object is created by the SDK Early Bound Code Generation Tool
2. crmService is the IOrganizationService connection object
3. GetAccounts ... performs a LINQ query and return an IEnumerable
Please help.
Thanks,
Chris.
Refer to http://msdn.microsoft.com/en-us/library/gg695783.aspx, particularly the "Multiple Data Contexts" part. It seems you're using multiple contexts to track the entities. The CrmAccount.GetAccountsBySubmissionCode method just hides this from you.
Make sure within the CrmAccount.GetAccountsBySubmissionCode method to dispose of the context/service before returning the IEnumerable<Account>, or make sure you use the same context/service to Update.

Resources