I am attempting to use the newer Azure.Messaging.EventGrid over the traditional Azure.EventGrid. I am getting hung up on my unit tests attempting to create object of type IotHubDeviceTelemetryEventData(). In the older library, I was able to create this no problem using the following convention.
return new object[]
{
new
{
id = "73813f6e-4d43-eb85-d6f1-f2b6a0657731",
topic = "testTopic",
data = new IotHubDeviceTelemetryEventData <-- New Up the object (no problem!)
{
Body = body} <-- Body has a setter. Great!
,
eventType = "Microsoft.Devices.DeviceTelemetry",
subject = "devices/b82bfa90fb/gw-uplink",
dataVersion = "1.0"
}
With the latest offering however, all of this is removed for some reason.
Old documentation with constructor etc (https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.eventgrid.models.iothubdevicetelemetryeventdata.-ctor?view=azure-dotnet
New documentation with no constructor, no setter on the body (DeviceTelemetry is sealed) etc:
https://learn.microsoft.com/en-us/dotnet/api/azure.messaging.eventgrid.systemevents.iothubdevicetelemetryeventdata?view=azure-dotnet
Anyone run into this? I would like to get off the old but I have existing unit tests that logically create TelemetryEventData and send to the function. I see no way of unit testing this ? I have tried mocking IotHubDeviceTelemetryEventData with
_mockHubTelemEventData.setup(c => c.Body).Returns(foo)
but this as well throws me an error of no setter on Body.
Super frustrating.
Other attempts have included creating EventGridEvent() but this as well is missing core functionality as the EventGridEvent.parse won't find any object of type Body.
EventGridEvent[] egEvents = EventGridEvent.ParseMany(BinaryData.FromStream(req.Body));
Mocking code you don't own comes with downsides, and you just one of them. But that's not why you're here. If you want to create instances of IotHubDeviceTelemetryEventData, you can try creating them as JSON and deserialize them. Give this a shot:
using System.Text.Json;
using Azure.Messaging.EventGrid.SystemEvents;
var json = #"
{
""body"":
{
""property"": { ""foo"": ""bar"" }
}
}
";
var eventData = JsonSerializer.Deserialize<IotHubDeviceTelemetryEventData>(json);
Related
I am new to Google APIs. I want to know how to call Google Dialogflow API in C# to get intent form the input text. But I can't find any example to call Dialogflow using C#.
Please provide some example to call Dialogflow from C#.
If I understand your question correctly you want to call the DialogFlow API from within a C# application (rather than writing fulfillment endpoint(s) that are called from DialogFlow. If that's the case here's a sample for making that call:
using Google.Cloud.Dialogflow.V2;
...
...
var query = new QueryInput
{
Text = new TextInput
{
Text = "Something you want to ask a DF agent",
LanguageCode = "en-us"
}
};
var sessionId = "SomeUniqueId";
var agent = "MyAgentName";
var creds = GoogleCredential.FromJson("{ json google credentials file)");
var channel = new Grpc.Core.Channel(SessionsClient.DefaultEndpoint.Host,
creds.ToChannelCredentials());
var client = SessionsClient.Create(channel);
var dialogFlow = client.DetectIntent(
new SessionName(agent, sessionId),
query
);
channel.ShutdownAsync();
In an earlier version of the DialogFlowAPI I was running into file locking issues when trying to re-deploy a web api project which the channel.ShutDownAsync() seemed to solve. I think this has been fixed in a recent release.
This is the simplest version of a DF request I've used. There is a more complicated version that passes in an input context in this post:
Making DialogFlow v2 DetectIntent Calls w/ C# (including input context)
(Nitpicking: I assume you know DialogFlow will call your code as specified/registered in the action at DialogFlow? So your code can only respond to DialogFlow, and not call it.)
Short answer/redirect:
Don't use Google.Apis.Dialogflow.v2 (with GoogleCloudDialogflowV2WebhookRequest and GoogleCloudDialogflowV2WebhookResponse) but use Google.Cloud.Dialogflow.v2 (with WebhookRequest and WebhookResponse) - see this eTag-error. I will also mention some other alternatives underneath.
Google.Cloud.Dialogflow.v2
Using Google.Cloud.Dialogflow.v2 NuGet (Edit: FWIW: this code was written for the beta-preview):
[HttpPost]
public dynamic PostWithCloudResponse([FromBody] WebhookRequest dialogflowRequest)
{
var intentName = dialogflowRequest.QueryResult.Intent.DisplayName;
var actualQuestion = dialogflowRequest.QueryResult.QueryText;
var testAnswer = $"Dialogflow Request for intent '{intentName}' and question '{actualQuestion}'";
var dialogflowResponse = new WebhookResponse
{
FulfillmentText = testAnswer,
FulfillmentMessages =
{ new Intent.Types.Message
{ SimpleResponses = new Intent.Types.Message.Types.SimpleResponses
{ SimpleResponses_ =
{ new Intent.Types.Message.Types.SimpleResponse
{
DisplayText = testAnswer,
TextToSpeech = testAnswer,
//Ssml = $"<speak>{testAnswer}</speak>"
}
}
}
}
}
};
var jsonResponse = dialogflowResponse.ToString();
return new ContentResult { Content = jsonResponse, ContentType = "application/json" }; ;
}
Edit: It turns out that the model binding may not bind all properties from the 'ProtoBuf-json' correctly (e.g. WebhookRequest.outputContexts[N].parameters),
so one should probably use the Google.Protobuf.JsonParser (e.g. see this documentation).
This parser may trip over unknown fields, so one probably also wants to ignore that. So now I use this code (I may one day make the generic method more generic and thus useful, by making HttpContext.Request.InputStream a parameter):
public ActionResult PostWithCloudResponse()
{
var dialogflowRequest = ParseProtobufRequest<WebhookRequest>();
...
var jsonResponse = dialogflowResponse.ToString();
return new ContentResult { Content = jsonResponse, ContentType = "application/json" }; ;
}
private T ParseProtobufRequest<T>() where T : Google.Protobuf.IMessage, new()
{
// parse ProtoBuf (not 'normal' json) with unknown fields, else it may not bind ProtoBuf correctly
// https://github.com/googleapis/google-cloud-dotnet/issues/2425 "ask the Protobuf code to parse the result"
string requestBody;
using (var reader = new StreamReader(HttpContext.Request.InputStream))
{
requestBody = reader.ReadToEnd();
}
var parser = new Google.Protobuf.JsonParser(JsonParser.Settings.Default.WithIgnoreUnknownFields(true));
var typedRequest = parser.Parse<T>(requestBody);
return typedRequest;
}
BTW: This 'ProtoBuf-json' is also the reason to use WebhookResponse.ToString() which in turn uses Google.Protobuf.JsonFormatter.ToDiagnosticString.
Microsoft's BotBuilder
Microsoft's BotBuilder packages and Visual Studio template.
I havent't used it yet, but expect approximately the same code?
Hand written proprietary code
A simple example of incoming request code (called an NLU-Response by Google) is provided by Madoka Chiyoda (Chomado) at Github. The incoming call is simply parsed to her DialogFlowResponseModel:
public static async Task<HttpResponseMessage> Run([...]HttpRequestMessage req, [...]CloudBlockBlob mp3Out, TraceWriter log)
...
var data = await req.Content.ReadAsAsync<Models.DialogFlowResponseModel>();
Gactions
If you plan to work without DialogFlow later on, please note that the interface for Gactions differs significantly from the interface with DialogFlow.
The json-parameters and return-values have some overlap, but nothing gaining you any programming time (probably loosing some time by starting 'over').
However, starting with DialogFlow may gain you some quick dialog-experience (e.g. question & answer design/prototyping).
And the DialogFlow-API does have a NuGet package, where the Gactions-interface does not have a NuGet-package just yet.
public ISearchResponse<object> GetById(string id) {
var uri = new Uri("<myendpoint>");
var settings = new ConnectionSettings(uri).DefaultIndex("useraction-*").PrettyJson().DisableDirectStreaming(); //or try _all
var client = new ElasticClient(settings);
var search = new SearchRequest<object>
{
Query = new TermQuery
{
Field = "field",
Value = "example"
}
};
var response = client.Search<object>(search);
return response;
}
I'm having trouble getting NEST to work. When I try to call the query defined above, I get the following error:
System.Exception: If you use a custom contract resolver be sure to subclass from ElasticResolver
at Nest.JsonExtensions.GetConnectionSettings(JsonSerializer serializer) in C:\Users\russ\source\elasticsearch-net-master\src\Nest\CommonAbstractions\Extensions\JsonExtensions.cs
I've searched the internet for mention of this and can't seem to find anything other than the source code. I've pretty much followed the documentation exactly so I don't know what to change.
Does anyone out there know what this error is trying to tell me? I feel like it's an error behind the scenes that I don't have control over.
I'm happy to answer additional questions if people need more info.
Thanks.
Also I don't know where that path is coming from in the exception because I have no user "russ"
Using Visual Studio, and AWS .NET V 3.0.
I'm trying to perform a real-time Predict operation, and to verify the basic setup works, I first perform a GetMLModel() which works and returns the endpoint (Somewhere in the documentation is was mentioned to use that result as the service endpoint, but it's the same that is listed in the console). Is has status "READY", so far so good.
The exception occurs below on the line below "Prediction P = RTP.Predict(Data)". Data contains a Dictionary with all the prediction values.
Error: Error making request with Error Code UnknownOperationException and Http Status Code BadRequest. No further error information was returned by the service.
public static APIResult GetRealTimePrediction(Dictionary<string, string> Data, string PayloadJSON = null) {
AmazonMachineLearningConfig MLConfig = new AmazonMachineLearningConfig();
MLConfig.RegionEndpoint = Amazon.RegionEndpoint.USEast1;
MLConfig.Validate();
AmazonMachineLearningClient MLClient = new AmazonMachineLearningClient("xxx", "xxx", MLConfig);
GetMLModelResponse MLMOdelResp = MLClient.GetMLModel("xxx"); // <-- WORKS
MLConfig.ServiceURL = MLMOdelResp.EndpointInfo.EndpointUrl;
Console.WriteLine(MLConfig.ServiceURL);
MLConfig.Validate();
Amazon.MachineLearning.Util.RealtimePredictor RTP = new Amazon.MachineLearning.Util.RealtimePredictor(MLClient, "xxx");
Prediction P = RTP.Predict(Data); // <----------------EXCEPTION HERE
}
(Obviously replace xxx with relevant values) :)
It turns out that this line:
MLConfig.ServiceURL = MLMOdelResp.EndpointInfo.EndpointUrl;
cases the MLConfig.RegionEndpoint to be reset. Even though the documentation indicates the RegionEndpoint can be determined from the ServiceURL (I'm pretty sure I read that), the RegionEndpoint needs to be set again before the RTP.Predict(Data) call.
Once I figured that out, I was able to reduce the code to just this, in case anyone else needs help. I guess adding too much information to the Configuration is NOT a good thing, as the AWS. NET library seems to figure all this out on its own.
public static APIResult GetRealTimePrediction(Dictionary<string, string> Data, string PayloadJSON = null) {
AmazonMachineLearningConfig MLConfig = new AmazonMachineLearningConfig();
MLConfig.RegionEndpoint = Amazon.RegionEndpoint.USEast1;
MLConfig.Validate(); // Just in case, not really needed
AmazonMachineLearningClient MLClient = new AmazonMachineLearningClient("xxx", "xxx", MLConfig);
Amazon.MachineLearning.Util.RealtimePredictor RTP = new Amazon.MachineLearning.Util.RealtimePredictor(MLClient, "xxx");
Prediction P = RTP.Predict(Data);
}
I am getting Redmine Issue with parameters.
I tried:
var rmMan = new RedmineManager(RedmineHost, RedmineKey);
rmMan.GetObjectList<Issue>(new NameValueCollection { { "parent_id", "1111" } }).Where(i=>i.Tracker.Name == "MyTrackerName");
How can I overcome this?
I want to get "Issue" object, found in the parameters without specifying Id. For example on the tracker.
GetObjectList wont do any filtering unless you specify the parameters. It will get all objects of type Issue (in your case). Adding the Where clause does the filtering after you've selected everything. I'm not sure that your NameValueCollection using parent_id will do anything either and redmine-net-api has terrible documentation.
Try this:
var parameters = new NameValueCollection
{
{ "parent_id", "1111" },
{ "tracker", "MyTrackerName" },
}
var rmMan = new RedmineManager(RedmineHost, RedmineKey);
var issues = rmMan.GetObjectList<Issue>(parameters);
Again, since the redmine-net-api documentation is very bad, this is kind of a shot in the dark.
I've forked the repository on GitHub and I'm going to try to generate the XMLDoc comments for the library in the next few days. Hopefully it'll get released with the next version.
I am currently working on an MVC site that will hopefully consume an old .asmx Web Service. The documentation for the Web Service provides the following example:
// Construct a request object
TrimRequest request = new TrimRequest();
// Construct a RecordStringSearchClause, with type
// TitleWord, and argument "reef"
RecordStringSearchClause clause = new RecordStringSearchClause();
clause.Type = RecordStringSearchClauseType.TitleWord;
clause.Arg = "reef";
// Construct a record search, and put our search clause in it
WorkerPortalTest.TRIMWS.RecordSearch search = new WorkerPortalTest.TRIMWS.RecordSearch();
search.Items = new RecordClause[] { clause };
// If we had more than one clause, it would look like:
// search.Items = new RecordClause[] { clause1, clause2, clause3 }
// Put our search operation into our TrimRequest
request.Items = new Operation[] { search };
// Send it off. Whatever comes back will be in response
Engine engine = new Engine();
engine.Credentials = newSystem.Net.NetworkCredential(username, password);
TrimResponse response = engine.Execute(request);
As a fairly new C# programmer I understand all of it apart from the last three lines. I have never seen or used the Engine object and Visual Studio does not know of it either.. I looked through MSDN and found this page but it said it was deprecated.
I am just looking for some pointers in the right direction to call the Web Service and receive back the desired result.
Thanks.
Engine is an example of the webservice class. It calls a method in Engine class known as "Execute"..