Azure Function for Bot Framework C# - c#

I've made a bot using BotFramework, and I want to have an azure function triggered every 5 minutes (for example). And when it's triggered my bot must be notified.
But I have no idea how to do this, I read this https://docs.botframework.com/en-us/azure-bot-service/templates/proactive/ but the thing is he didn't use a Timmer Trigger Azure Function but a Queue Trigger.
I tryed to do something like that :
using System;
using System.Net;
using System.Net.Http;
using Microsoft.Azure.WebJobs.Host;
public class BotMessage
{
public string Source { get; set; }
public string Message { get; set; }
}
public static HttpResponseMessage Run(TimerInfo myTimer,out BotMessage message ,TraceWriter log)
{
message = new BotMessage()
{
Source = "AzureFunction",
Message = "Testing"
};
return new HttpResponseMessage(HttpStatusCode.OK);
}
but i have this error :
2017-03-02T14:49:40.460 Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.TimerTriggerCSharp1'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'message' to type BotMessage&. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. config.UseServiceBus(), config.UseTimers(), etc.).
Plus, to indicate which bot has to be notified where the event is triggered is added a output with the direct line key :
but as u can see there is the same error than above ...
Does someone have some docs or example for that.
Thank you for reading me.

Your binding configuration is set to use the return value of your function (also, in this case, that doesn't match any of the types supported by the binding)
You have a couple of options:
Uncheck the box to use the return value of of your function and name the parameter message
Or
Change the return type of your function to BotMessage return the message instance from your Run method and remove the out BotMessage message parameter.
Either option should fix this problem.

Related

AWS Annotations Framework Input Parameters for C#

I'm having trouble getting a Lambda function written using the AWS Annotations Framework to accept input parameters. This is the article I'm using: https://aws.amazon.com/blogs/developer/introducing-net-annotations-lambda-framework-preview/, but it only goes so far. When I publish the functions to Amazon and test clicking the TEST button, the input parameters aren't populated.
This is my function:
[LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
[LambdaFunction()]
[HttpApi(LambdaHttpMethod.Get, "/add/{x}/{y}")]
public int Add(int x, int y, ILambdaContext context)
{
context.Logger.LogInformation($"{x} plus {y} is {x + y}");
return x + y;
}
and this is the Event JSON within the AWS test harness
The log shows that the parameters have no value:
2022-05-09T10:47:02.435Z 51291252-f7cb-4a1e-9f4a-f7aebdec6b02 info 0
plus 0 is 0
I'm using this as an example, I don't actually need a calculator, but I do need to pass input parameters from an Amazon Connect contact flow and I will be passing in parameters like this:
I've spent a few days Googling and reading articles, but so far I've not found anything that helps, so any assistance is gratefully received!
Using the HttpApi attribute exposes the Lambda function as a REST API called via some http client. Amazon Connect invokes your Lambda function directly using its own event object documented here https://docs.aws.amazon.com/connect/latest/adminguide/connect-lambda-functions.html#function-contact-flow. In .NET the event object is represented as the Amazon.Lambda.ConnectEvents.ContactFlowEvent type from the Amazon.Lambda.ConnectEvents NuGet package.
Currently the Amazon.Lambda.Annotations has support for breaking up the HTTP API event object to follow typical .NET REST patterns. We haven't done that for other types of event sources like Connect, although this is something we want to do.
You can still use Amazon.Lambda.Annotations for your use case to get the dependency injection and syncing CloudFormation template features by using just the LambdaFunction attribute and then having your function take in the Connect event object. Something like this.
[LambdaFunction()]
public IDictionary<string, string> ProcessConnectContactFlow(Amazon.Lambda.ConnectEvents.ContactFlowEvent contactFlowEvent)
{
// Process the event
var response = new Dictionary<string, string>()
{
{ "Name", "CustomerName" },
{ "Address", "1234 Main Road" },
{ "CallerType", "Patient" }
};
return response;
}

Can QueueTrigger function have response as controller

is it possible to have from QueueTrigger function response as controller? When I call a get method from controller response body could be something like
{
"error": {
"message": "The resource does not exist",
...
Is there a way to do similar response from the function? I found only output binding where it can return string to another queue, but this is not what I am looking for:
[FunctionName("QueueOutput")]
[return: Queue("myqueue-items")]
public static string Run([HttpTrigger] dynamic input, ILogger log)
{
...
}
If I do this:
[FunctionName("QueueOutput")]
public static Task<string> Run([HttpTrigger] dynamic input, ILogger log)
{
...
return "...";
}
I have following error:
The 'CleanDataFunction' function is in error:
Microsoft.Azure.WebJobs.Host: Error indexing method 'CleanDataFunction'.
Microsoft.Azure.WebJobs.Host: Cannot bind parameter '$return' to type
String&. Make sure the parameter Type is supported by the binding. If
you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers,
etc.) make sure you've called the registration method for the extension(s)
in your startup code (e.g. builder.AddAzureStorage(),
builder.AddServiceBus(), builder.AddTimers(), etc.).
Probably it is not possible. Found answer here:
Azure Function doesn't work with QueueTrigger and non-void return value?
You could simply create the json you need, either manually as a string or using JSON.NET, and return it serialized.

Azure Service Bus Triggered Function - Bind to MessageReceiver

I'm trying to bind to MessageReceiver in an Azure Service Bus Triggered Function.
My goal is to handle dead letter queue messages and complete them.
public static class Function1
{
[FunctionName("Function1")]
public static async Task Run(
[ServiceBusTrigger(
"<topicName>",
"<subscriptionName>/$DeadLetterQueue",
Connection = "connectionstring")]
Message message,
ILogger logger,
MessageReceiver messageReceiver)
{
// TODO: Perform some actions
await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
}
The problem is that it fails to bind to the MessageReceiver class.
Microsoft.Azure.WebJobs.Host: Error indexing method 'Function1'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'receiver' to type MessageReceiver. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
Any ideas why the binding fails?
I figured out what was wrong. I was using 'receiver' as parameter name for MessageReceiver. It turned out that the parameter name has to be 'messageReceiver'. The example I was looking at first used 'receiver', so is this maybe something that has changed?

ServiceStack RedisMessageQueueClient strange behavior

My infrastructure:
Main - ServiceStack self hosted console app. 'Main' sends messages to MQ.
Background - ServiceStack self hosted console app. 'Background' receives messages from MQ.
Locally installed Redis
In 'Main' AppHost I configure Redis manager:
container.Register<IRedisClientsManager>(
new PooledRedisClientManager("localhost:6379"));
Then I run this code somewhere in service:
using (var client = new RedisMessageQueueClient(TryResolve<IRedisClientsManager>()))
{
client.Publish(new TestMessage { Value = "From ping" });
}
Everything works great and I can get message in my 'Background'. But problem comes when I wrap this code in class:
public class MessageQueuePublisher : IMessageQueuePublisher
{
public void Publish(object message)
{
using (var client = new RedisMessageQueueClient(
EndpointHost.AppHost.TryResolve<IRedisClientsManager>()))
{
client.Publish(message);
}
}
}
When I call MessageQueuePublisher.Publish method from the exactly same place where previous code was executed, it seems like it works correctly (no exceptions are thrown), but my message doesn't reach 'Background'.
Is this OK?
I found a solution. On my 'Background' I expect message with type TestMessage
mqService.RegisterHandler<TestMessage>(ServiceController.ExecuteMessage);
But when using MessageQueuePublisher.Publish message was of type object and went to the object queue and wasn't handled.
So to solve this problem Publish method should be generic:
public void Publish<T>(T message)
It doesn't change how method is called but code is not so good because if you look at it, it's not clear why generic is used. But at least it works.

MassTransit binary serialized messages are not handled correctly

I've been using MassTransit for handling e-mail messages. Using this code: http://meandaspnet.blogspot.com/2009/10/how-to-binary-serialize-mailmessage-for.html I'm able to binary serialize my e-mails and publish them to my service bus. They're handled correctly too.
Bus.Initialize(
sbc =>
{
sbc.EnableMessageTracing();
sbc.ReceiveFrom("msmq://localhost/MyQueue");
sbc.UseMsmq();
sbc.VerifyMsmqConfiguration();
sbc.UseMulticastSubscriptionClient();
sbc.UseBinarySerializer();
sbc.Subscribe(subs => subs.Instance(new MessageHandler()));
});
Now I added a new type and handler:
// Check out the sequence of the Consumes<> !
public class MessageHandler :
Consumes<SerializeableMailMessage>.All,
Consumes<AangifteOmzetbelasting>.All
{
public void Consume(AangifteOmzetbelasting message)
{
// Some code - method will NOT be called
}
public void Consume(SerializeableMailMessage mailMessage)
{
// Some code - this method is called by Mass Transit
}
}
The weird thing is that this works if I Publish a SerializableMailMessage - but not for AangifteOmzetbelasting. If I change the interface order - it works for AangifteOmzetbelasting and not for SerializableMailMessage. Like so:
// Check out the sequence of the Consumes<> !
public class MessageHandler :
Consumes<AangifteOmzetbelasting>.All,
Consumes<SerializeableMailMessage>.All
In the latter case, the SerializedMailMessges do not appear on the service bus either. Both are published using:
Bus.Instance.Publish(object)
What am I doing wrong here?
Publishing messages without type information is a real struggle; the type information is hugely important for routing.
What I would look at doing here, if you must publish as object, is we have FastActivator helpers you can take a peek at (should be in the referenced Magnum library) that would be like Bus.Instance.FastActivator("Publish", message, { message.GetType() }). I might have the order of the parameters wrong, but you need the method name, parameters, and generic type parameters.
Additionally, I'd suggest joining the MT mailing list to help with this issue further if you need it. https://groups.google.com/forum/#!forum/masstransit-discuss

Categories