How to expand OptionSet data from Microsoft Dynamics using Apache Olingo? - dynamics-crm

I am using Apache olingo v4 to fetch Microsoft Dynamics Data. I am trying to fetch an entity metadata with attributes expanded along with option set (if the attribute is of type 'Picklist').
Here is the sample code I tried:
URIBuilder absoluteUri = client.newURIBuilder("<URL>").appendEntitySetSegment("EntityDefinitions");
absoluteUri.filter("LogicalName eq 'account'");
absoluteUri.expand("Attributes($expand=OptionSet)");
URI uri = absoluteUri.build();
ODataRawRequest request = client.getRetrieveRequestFactory().getRawRequest(absoluteUri);
request.setAccept("application/json;odata.metadata=full");
ODataRawResponse response = request.execute();
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> result = mapper.readValue(response.getRawResponse(), new TypeReference<Map<String, Object>>(){});
return mapper.convertValue(result.get("value"), new TypeReference<List<Map<String,Object>>>(){});
When I run this, I get the below error:
org.apache.olingo.client.api.communication.ODataClientErrorException: (0x0) Could not find a property named 'OptionSet' on type 'Microsoft.Dynamics.CRM.AttributeMetadata'."Could not find a property named 'OptionSet' on type 'Microsoft.Dynamics.CRM.AttributeMetadata'." [HTTP/1.1 400 Bad Request]
How do I do this with Olingo? If I have to do this via postman, I can just hit this url
GET [Organization URI]/api/data/v9.0/EntityDefinitions(LogicalName='account')/Attributes/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$expand=OptionSet
Update:
I edited the 3rd line to below:
absoluteUri.expand("Attributes/Microsoft.Dynamics.CRM.PicklistAttributeMetadata($expand=OptionSet)");
Got the below error:
org.apache.olingo.client.api.communication.ODataClientErrorException: (0x0) Found a path traversing multiple navigation properties. Please rephrase the query such that each expand path contains only type segments and navigation properties."Found a path traversing multiple navigation properties. Please rephrase the query such that each expand path contains only type segments and navigation properties." [HTTP/1.1 400 Bad Request]

Maybe you should update the third lines as below:
absoluteUri.expand("Attributes/Microsoft.Dynamics.CRM.PicklistAttributeMetadata($expand=OptionSet)");
The error message says Microsoft.Dynamics.CRM.AttributeMetadata not PicklistAttributeMetadata

Related

Error when trying to query by file id in GAPI Drive v3 using Python's library

I'm using service.files().list() and providing a query string to retrieve files that match the ids in a given list. Yet Calling service.files.list errors out, and GAPI returns an error code of 400. I'm using a service object created using an access token.
I get the following message:
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/drive/v3/files?pageSize=50&fields=%2A&q=id+contains+%271234%27&spaces=drive&alt=json returned "Invalid Value". Details: "Invalid Value">
Here's the code. Is it possible to query by file id in the list API? I prefer to do it this way instead of making a get request for each individual file.
# Create file query string
queryStr = ""
for i in range(len(fileIds)):
queryStr += f"id='{fileIds[i]}'"
if i != len(fileIds) - 1:
queryStr += " or "
# Build files array
results = service.files().list(
pageSize=50,
fields="*",
q=queryStr,
spaces="drive"
).execute()
print(results.get("files", [0])[0])
You appear to be trying to search on id contains
If you check the documentation File query terms
You will find that Id is not a searchable field.
Try something like name contains car for example

Elasticsearch NEST Document count for default index

I am using NEST for Elasticsearch 6 and would like to get the number of documents for the default index.
The documentation refers to the 1.1 version of the API which no longer seems to work.
I have created the connection settings using a default index:
var connectionSettings = new ConnectionSettings().DefaultIndex("test_docs");
When I try the code from the 1.1 api documentation:
var result = client.Count();
I get the following error:
The type arguments for method
'ElasticClient.Count(Func, ICountRequest>)'
cannot be inferred from the usage. Try specifying the type arguments
explicitly.
When I supply a type it is appended to the path. For example:
client.Count<TestDocument>();
Generates a URL of http://localhost:9200/test_docs/testdocument/_count when what I really need is http://localhost:9200/test_docs/_count
For those needing the new way of doing this (like myself). I would use the following to get a count from a specific index.
var countRequest = new CountRequest(Indices.Index("videos"));
long count = (await _ecClient.CountAsync(countRequest)).Count;
You can use
var countResponse = client.Count<TestDocument>(c => c.AllTypes());
which will call the API
GET http://localhost:9200/test_docs/_count

Set CRM Lookup Values with WebAPI

Who had done CRM Web API calls to update CRM entities with Lookup values from another Entity.
I'm trying to set a Lookup Value to another Entity within CRM using WebAPI, CRM 2016. It works if I disable the Lookup value but once I enable the Lookup value, I receive Bad Request.
Below is my code in LinqPad so it does work.
void Main()
{
using(var webClient = new WebClient()){
webClient.Credentials = new NetworkCredential("Username", "Password", "Domain");
webClient.Headers.Add("OData-MaxVersion", "4.0");
webClient.Headers.Add("OData-Version", "4.0");
webClient.Headers.Add("accept", "application/json");
webClient.Headers.Add("Content-Type","application/json");
webClient.Headers.Add("Prefer", "odata.include-annotations=*");
webClient.BaseAddress = "http://dev.company.com/DEV2016/api/data/v8.0/";
var JO = new JObject();
JO.Add("col_name","My Name");
//JO.Add("col_contactid#odata.bind","/contacts(7266f26b-7105-e611-811e-005056b61789)");
var dataString = JO.ToString();
var responseString = webClient.UploadString("col_advisors", "POST", dataString);
Console.WriteLine(webClient.ResponseHeaders.Get("OData-EntityId"));
}
}
Case matters with the WebAPI. Make sure your col_contactid is the schema name, not the logical name. For example, the logical name of your attribute is col_contactid (logical names are always lowercase), but schema names often times have upper case letters. Yours might be col_ContactId for example, in which case you would want to use col_ContactId#odata.bind.
The easiest way to find the schema name of your attribute is by going to CRM -> Settings -> Solutions -> your solution -> Entites (on the left) -> Advisors -> Fields. In that grid you'll see a column for schema name.
I got it to work. The fields really have to be unique as it is case sensitive. Comments here and also this blog, really helped.
http://inogic.com/blog/2016/02/set-values-of-all-data-types-using-web-api-in-dynamics-crm/
Step 1 : Goto Cutomization  Developer Resource.
Step 2 : Click to “Download Odata Metadata” link and Download the same.
Step 3 : Once Download, open it and find out name of lookup attribute ( i.e. new_qualifiedleadid) and check its casing.
Step 4 : Verify it with the value which you are setting in the code it should be same.
While my column was col_contactid, CRM renames the Navigational Column to be what was above col_ContactId.
I also used Postman(google chrome) plugin and added the following Header to my Post.
webClient.Headers.Add("Prefer", "odata.include-annotations=*");

How to post json data using West Wind in VFP

There's a document from West Wind says you can post data using application/json format:
https://west-wind.com/webconnection/docs/_2110q21c9.htm
But when using it, actually it'll do a http get instead of post:
DO wwhttp
oHTTP=CREATEOBJECT("wwHttp")
oHTTP.nHTTPPostMode = 8
oHttp.cContentType = "application/json"
oHTTP.AddPostKey("name","somename")
lcURL = "https://mywebserver.com/"
lcXML = oHTTP.HTTPGet(lcURL)
If using nHTTPPostMode = 1 or 2, the http request parameters are not correctly formatted as json. If I change to 4, it's using Get instead of Post again. Is there anyway to get around this?
When you post JSON data you need to post a JSON document not key value pairs as you are doing in your example. Essentially you need to provide the full content - the entire JSON document as a string - that you're sending to the server (just like the example shows).
To post a JSON document looks like this:
DO wwHttp
oHTTP=CREATEOBJECT("wwHttp")
oHttp.cContentType = "application/json"
lcJson = "{ name: 'somename' }"
oHTTP.AddPostKey(lcJson) && this sets the entire post buffer
lcURL = "https://mywebserver.com/"
lcJson = oHTTP.HTTPGet(lcURL)
Using name value pairs only works with POST buffers for URLEncoded or Multipart documents - every other type of content is sent as raw data that you have to provide.
in version 6 and later you can also use the following simpler syntax to .Post data:
oHttp.cContentType = "application/json"
lcJson = oHttp.Post(lcUrl, lcJson)
If you want to create JSON documents under program control you can serialize data using the wwJsonSerializer class (also part of Client Tools). It can serialize from objects, arrays/collections and cursors.

How to find a template in Alfresco with OpenCMIS from Spring application?

I am working in a Spring 3.1 application and I need to find a String template document located in Alfresco's repository. I can already create a file in alfresco with OpenCMIS, but I couldn't figure out how to find a template, so if anyone knows how to do it or point me an example, please let me know, thanks in advance!
There are a number of options you can use. First of all, you need to have a criteria that uniquely identifies your document. Here below I'll show some, hopefully your case falls in one of them or they will inspire you towards a proper solution. The following uses pseudo code, please have a look to the OpenCMIS dev guide for working with the Java client API.
BY ID
Once you create a Document via CMIS, you get the unique ID of it that you can store in your application for later retrieval.
Map<String, Object> templateProperties = createDocumentProperties();
Folder folder = getTemplatesFolder();
ObjectId templateId = createTemplateIn(folder);
storeTemplateId(templateId.getId(), templateProperties); // persist the ID
...
// later on
...
String id = getTemplateId(); // retrieve the ID
Session session = openCMISSession();
Document template = (Document)session.getObject(id);
BY PATH
Similar to the previous example, you will have to take note of where you stored the document instead of its ID, or having a way to construct the path by hand.
String path = getTemplatePath(); // either recover it from DB or construct a path
Document template = (Document)session.getObjectByPath(path);
BY PROPERTY VALUE
Let's say you can use a specific metadata field on a template Document that allows you to easily retrieve it afterwards (e.g. you created some specific Alfresco metadata model for your use case).
String meta = TemplateProperties.TEMPLATE_ID; // e.g. my:templateId
String type = TemplateProperties.TEMPLATE_TYPE; // e.g. my:template
String templateMeta = "TEMPLATE1";
Map<String, Object> templateProperties = createDocumentProperties();
templateProperties.put(meta, templateMeta);
templateProperties.put(PropertyIds.OBJECT_TYPE_ID, type);
createTemplate(templateProperties);
...
// later on
...
String type = TemplateProperties.TEMPLATE_TYPE; // e.g. my:template
String meta = TemplateProperties.TEMPLATE_ID;
String tplId = "TEMPLATE1";
String query = String.format("SELECT * FROM % WHERE % = '%'", type, meta, tplId);
ItemIterable<QueryResult> i = session.query(query, false);
QueryResult qr = i.iterator().next(); // let's assume we have one single match
String templateId = qr.getPropertyByQueryName("cmis:objectId").getFirstValue()
Document template = (Document)session.getObject(templateId);
BY QUERY
The previous approach is not really tied to search by property name, and can be easily extended to use any kind of query that identifies your templates. Have a look at the Alfresco page on its CMIS query language implementation details to learn more ways of querying the repository.

Resources