Azure .NET SDK not handling filters correctly (ConsumptionClient)? - c#

I'm calling the Azure Usage API trying to use a filter to get machine specific information.
The return values are valid, but it seems like either the REST API or the C# library is sending the request incorrectly.
This is the code:
var filterString = $"instanceName eq '{vm.VirtualMachineName}'";
vmConsumptionData = await consumptionClient.Item1.UsageDetails.ListAsync(
scope: $"/subscriptions/{subscriptionId}",
filter: filterString
);
According to the log, my request is being sent with the following:
https://management.azure.com//subscriptions/{SubscriptionId}/providers/Microsoft.Consumption/usageDetails?$filter=instanceName%20eq%20%27{correct instance name}%27&api-version=2017-11-30
However, this is always returning the same 24 results, even when submitting a different instance name.
I have tried removing certain parts of the filter 'query' and it always returns the same 24 results (which are not virtual machine resource types).
Am I calling the library incorrectly? Reference here

Apparently the SDK differs in the filtering and is somewhat clear from the documentation. You should call with the following:
properties/usageEnd (Utc time)
properties/usageStart (Utc time)
properties/resourceGroup
properties/instanceName
properties/instanceId
Changing my filterString to:
var filterString = $"properties/instanceName eq \'{vm.VirtualMachineName}\'";
Did the job.

Related

LuisV3.PredictionOptions doesn't let me timezone - how to do it?

I figured I'd upgrade my LuisRecognizer to use LuisRecognizerOptionsV3. However I can't seem to set prediction options the way I like - how do I set the timezone? The v3 prediction options lack this field.
In my bot I am currently doing:
var predictionOptions = new LuisPredictionOptions();
predictionOptions.TimezoneOffset = turnContext.Activity.LocalTimestamp.Value.Offset.TotalMinutes;
and I can't figure out the equivalent in v3's version of the data structure.
The timezoneOffset parameter was mostly provided as a way to determine what day it is for the user in case they say something like "today" or "tomorrow." It also helps when the user enters a relative time like "in three hours." When using the timezoneOffset parameter, the returned entity is in the provided timezone rather than universal time.
In LUIS v3, instead of providing an offset you provide a DateTime reference and LUIS uses that to process relative time. You can see that documented here. Note that the datetimeReference property is only available in POST requests and not GET requests because you provide it in the request body and not as a query parameter.
Also note that the datetimeReference property is not currently available in the Bot Builder SDK. You can write your own code to access the LUIS API directly with an HttpClient, but if you'd still like a prebuilt SDK to handle things then you can use this NuGet package: Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime 3.0.0
Here's an example of how to use it:
var appId = new Guid("<LUIS APP ID>");
var client = new LUISRuntimeClient(new ApiKeyServiceClientCredentials("<SERVICE KEY>"));
client.Endpoint = "https://westus2.api.cognitive.microsoft.com";
var options = new PredictionRequestOptions(activity.LocalTimestamp.Value.DateTime);
var request = new PredictionRequest("Book a flight in three hours", options);
var response = await client.Prediction.GetSlotPredictionAsync(appId, "PRODUCTION", request);
Console.WriteLine(JsonConvert.SerializeObject(response.Prediction.Entities, Formatting.Indented));

Show more than 5000 records from CRM in C#

I am trying to understand how FetchXml works (or any other method) because I want to retrieve and process more than the limit of 5000 records that CRM returns on the api call below.
My base url looks like this: http://crm.domain.com:1234/api/data/v8.0/
the resource is: emails
and query options are: $top=50000&$filter=description ne null and not contains(sender, '#not-interesting.com')
I'm trying to copy the code from
https://learn.microsoft.com/en-us/previous-versions/dynamicscrm-2016/developers-guide/gg327917(v=crm.8)?redirectedfrom=MSDN
but I'm having issues with creating the OrganizationServiceProxy object like this:
var creds = new ClientCredentials();
creds.UserName.UserName = CrmApiUsername;
creds.UserName.Password = CrmApiPassword;
using (var _serviceProxy = new OrganizationServiceProxy(
new Uri(CrmApiBaseAddress), null, creds, null))
{
// This statement is required to enable early-bound type support.
_serviceProxy.EnableProxyTypes(); // ...
I'm getting an error:
Metadata contains a reference that cannot be resolved: 'http://crm.domain.com:1234/data/v8.0/?wsdl&sdkversion=90'.'
WebException: The remote server returned an error: (404) Not Found.
You mixed up these two:
Web API - which was available after v8.0
2011 endpoint - which is deprecated now but was available for really long time
Read more
When you use web api the url will be like: https://yourcrm.crm#.dynamics.com/api/data/v8.0/
In case of Organization Service Proxy still the 2011 endpoint: https://yourcrm.crm.dynamics.com/XRMServices/2011/Organization.svc
For breaking the 5000 records limitation & getting more than 5k records, the pagination concept has to be used. How to fetch more than 5000 entities from CRM
For more ideas, I have answered in this SO thread about other options.

DocumentClient.CreateDocumentQuery throws a "not an instance" error when running a query

I'm writing a .NET web service that takes documents from a cosmosDB database. I writing a function in another project (that is supposed to be as generic as possible) to retrieve a document, so that the WS will use it.
I'm using DocumentClients function CreateDocumentQuery like this:
public static async Task<T1> GetMyDocumentAsync<T1>(eDataBase databaseName, eCollection collectionName, eFields key, string val)
{
var option = new FeedOptions { EnableCrossPartitionQuery = true };
Uri uri = UriFactory.CreateDocumentCollectionUri(databaseName.ToString(), collectionName.ToString());
IQueryable<T1> res = Client.CreateDocumentQuery<T1>(uri, option);
document = res.AsEnumerable<T1>().FirstOrDefault();
}
This works fine, returning the first document in the database. But changing the usage of CreateDocumentQuery to this:
IQueryable<T1> res = Client.CreateDocumentQuery<T1>(uri, "SELECT * FROM c",option);
And wrapped inside a try-catch block throws an exception that has an InnerException that states:
Object not set to an instance of an object.
Also some of the exception fields are:
Data = {System.Collections.ListDictionaryInternal}
and
Error = {{ "code": "BadRequest",
"message": "\r\nActivityId: SOMEGUID" }}
The query works on that collection from the azure portal.
The client properties I'm using are:
ConnectionMode = Gateway and Protocol = Https.
Any ideas as to why this usage works and the other using an explicit query string won't? I also tried using a SqlQuerySpec object and the result was the same. I don't want to use the Where() function since I want to use generic types. The async keyword was meant for future use.
So I solved it.
When creating the collection I tried to query in the question, I noticed that a partition key is mandatory. All my other collections up in cosmos did not have any. So I figured that some of the settings should be different for collections that do have partition keys.
The part that throw the null exception was enumerating the document query. The function usage looked OK according to the documentation so I thought that the problem was with the CreateDocumentQuery. That is because it created a "faulty" object, with some null fields and it might be due to the change in collection partition keys.
So I tried updating the package Microsoft.Azure.DocumentDB for my entire solution to the lastest stable version (2.2.0 at the time being) and then it just worked.

Mobile Services: How to handle the case where your query string is too long?

With Azure Mobile Services Offline Support I'm issuing a PullAsync query like so:
// This list contains 53 emails
var deviceContactEmails = new List<string> { "derek#gmail.com", "sarah#gmail.com", ... };
var query = _userTable.Where(x => deviceContactEmails.Contains(x.Email));
await _userTable.PullAsync(query);
The Mobile Services SDK translates query into a URL encoded GET request with a filter like so (this was a list of 60 emails used for the Contains but I cut out a lot of the middle for brevity):
https://rememberwhen.azure-mobile.net/tables/User?$filter=((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((email%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net')%20or%20(email%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net'))%20or%20(email%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net'))%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net'))%20or%20(email%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net'))&$skip=0&$top=50&__includeDeleted=true&__systemproperties=__createdAt%2C__version
The problem is that if deviceContactEmails is too long, the service will complain about the query string length. Trying to filter on this many items in the URL is a problem, so I need to filter by passing the items in the body of the request with JSON or some other way.
So I guess the question is: How do I correctly set this up using the Mobile Service SDK with offline support so I can avoid exceeding the limit on the query string length in the URL encoded request?
It looks like I need to create a custom API to send the list of emails as the body of the request. I'll update this answer and accept if I solve it.

Bloomberg API - using .Net API to get the FUT_CHAIN on an underlying security

I am trying to query the Bloomberg API (.Net) to get the future chain on an underlying security. Preferably, I would be able to get the list of futures for a given date in the past.
The equivalent operation in Excel using the worksheet formula API would be the following:-
=BDS("ERA COMDTY","FUT_CHAIN","CHAIN_DATE=20120103",
"INCLUDE_EXPIRED_CONTRACTS=Yes")
I looked at a large number of online resources, and I don't seem to be getting anywhere.
For the v3 API, you need to use request overrides.
Request request = refDataService.createRequest("ReferenceDataRequest");
request.append("securities", "ERA Comdty");
request.append("fields","FUT_CHAIN");
Element overrides = request.getElement("overrides");
Element override1 = overrides.appendElement();
override1.setElement("fieldId", "CHAIN_DATE");
override1.setElement("value", "20120103");
Element override2 = overrides.appendElement();
override2.setElement("fieldId", "INCLUDE_EXPIRED_CONTRACTS);
verride2.setElement("value", 'Y');
session.sendRequest(request);

Categories