I want to build an Azure Function that responds to HTTP POST requests coming from another Azure function i.e. MasterFunction calling NotificationsFunction.
Say, I have the following simple POCO object:
public class Car
{
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
public int Mileage { get; set; }
}
Both functions will be sharing the same class library containing these POCO objects.
Am I right to assume that in the MasterFunction, I'll have to serialize my Car object to JSON, then make an HTTP call?
Could someone point me to some code samples on a similar scenario?
If both of your functions are in the same azure function app (which I think that's the case), I'd say the best way of calling other functions is using Queues.
In the sense that you put your POCO into a queue and define your second function with a QueueTrigger. So once an object gets into the queue, the other function gets called automatically and the object get dequeued.
You can find samples and more details in here : https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-queue
If I understand correctly you want service communication between services/endpoints.
You can use Orchestration or choreography for service communication.
orchestration in azure using 1. Durable function 2. Logic app
Choreography in azure using 1. Storage queue 2. Service Bus.
Hope it will help
Related
I'm taking over responsibility for an Azure Service Bus deployment. Documentation is incomplete in that there are undocumented Queues and Topic Subscriptions present.
What information can Azure provide me about the function that is consuming messages sent to a queue/topic subscription? I'd like ultimately to be able to locate the source code which is processing the messages.
e.g. a class library name, class name or even just a namespace of the function that receives the messages. Something. Anything.
Or am I asking the wrong question?
Seems like an oversight on Azure that all information about Service Bus ends at the definition of the "inbox" and offers nothing about the functions that deal with received messages.
Problem is, the whole idea of using a Service Bus is to decouple (parts of) applications, so the sender does not have a tight relationship with the receiver of the message. From your story it seems your consumers are probably Azure Functions but in other situations receiver might be running on-premises or in an other cloud environment like AWS or Google Cloud. The Azure Service Bus does simply not know what kind of hosting environment is consuming the messages. Tools like Application Insights can generate this kind of information but only if enabled on the consuming side.
What information can Azure provide me about the function that is consuming messages sent to a queue/topic subscription? I'd like ultimately to be able to locate the source code which is processing the messages.
e.g. a class library name, class name or even just a namespace of the function that receives the messages. Something. Anything.
If the producing/consuming applications have an Application Insights integration the Application Map might reveal this information.
Enabling Azure Functions to consume Service Bus messages is all based on configuration so you could scan your code repositories based topic names but there are plenty of other locations where this configuration can be stored like Azure Function Application Settings, Azure Key Vault, Azure App Configuration etc.
Even a statement "There are no consumers on this queue/subscription" would be a help.
The closest you can get is see whether there are active messages waiting to be delivered:
If there is no (active) consuming subscription while messages are pushed I would expect an increasing value of the Active Message Count metric. But do mind the Message Time to Live for the specific topic.
Or am I asking the wrong question?
It is a valid question and I definitely feel your pain but there is no satisfying answer to your question. For loosly coupled systems you need documentation, distributed tracing and possibly infrastructure as code to tackle issues like this.
Getting a list of Azure Functions and their bindings
In your comments you mention that it would help to get a list of functions and their bindings. I do know how to do that using the management SDK:
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.AppService;
internal class Program
{
private static async Task Main(string[] args)
{
var client = new ArmClient(new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{
ExcludeVisualStudioCredential = true,
ExcludeVisualStudioCodeCredential = true
}));
var azureFunctions = new List<SiteFunctionResource>();
foreach (var subscription in client.GetSubscriptions())
{
var resourceGroups = subscription.GetResourceGroups();
await foreach (var resourceGroup in resourceGroups.GetAllAsync())
{
var websites = resourceGroup.GetWebSites();
azureFunctions.AddRange(
websites
.Where(ws => ws.Data.Kind.Contains("functionapp", StringComparison.InvariantCultureIgnoreCase))
.SelectMany(ws => ws.GetSiteFunctions().ToList())
);
}
}
foreach (var azureFunction in azureFunctions)
{
var bindings = azureFunction.Data.Config.ToObjectFromJson<Config>().bindings;
Console.WriteLine(azureFunction.Id);
Console.WriteLine("bindings:");
foreach (var binding in bindings)
{
Console.WriteLine($"\t{binding.name}: {binding.type}");
}
Console.WriteLine("-----------------------------------");
}
Console.ReadLine();
}
public class Binding
{
public string type { get; set; }
public string route { get; set; }
public List<string> methods { get; set; }
public string authLevel { get; set; }
public string name { get; set; }
}
public class Config
{
public List<Binding> bindings { get; set; }
}
}
It needs the following NuGet packages:
<PackageReference Include="Azure.Identity" Version="1.7.0-beta.1" />
<PackageReference Include="Azure.ResourceManager" Version="1.3.0" />
<PackageReference Include="Azure.ResourceManager.AppService" Version="1.0.0-beta.3" />
Sample output:
We are planning to build a web application, and I was hoping someone could help us to decide whether to use Azure App Service or Azure Function for providing rest API to the client side.
Our requirements are as follows.
Authentication and authorization
CRUD on Azure SQL and Cosmos DB
Multi region
100,000,000 API calls per month
At first, we were going to build the backend using Azure App Service. But after studying pros and cons on Azure Functions, Azure Functions became more appealing to us.
So is it even a good idea to build a web application that depends on Azure Functions as a REST API provider?
Does anyone have an experience building, managing and scaling up and out Azure Functions as a REST API provider?
Is it even a good idea to build a web application that depends on Azure Functions as a REST API provider?
It seems you are planning to have REST API using Web Service or Azure Function. Your decision is perfect I would say. For Azure Function its not mandatory to have web service for that. Azure function would be best option for you. You can implement all the feature that Web API provides. So if your target is only develop API then you can start with Azure Function with no other alternative. Its outstanding actually!
Does anyone have an experience building, managing and scaling up and out Azure Functions as a REST API provider?
I am working with Azure Function for our AI Base Bot with LUIS integration. From my understanding it's a very easily maintainable, fastest response time, you can build it from anywhere. So you can undoubtedly go with Azure function.
Why Choose Azure Function:
It's stateless, need not any server to run
Full REST, can call from anywhere any Region
Can develop both Azure Portal and local Visual Studio
Cost-effective, you can pay only how much you use.
Multiple language support
Easy Authorization and Authentication functionality
No limit of calling as per your consumption plan
Do A Lot With Azure Function:
You can develop a robust API service with Azure functions. It has many outstanding features. Please check Check here
Authorization and Authentication:
You can simply integrate your authorization and authentication on your function App. Even you can implement it on each function separately or on a full application. It supports most of the popular authentication provider for example:
Azure Active Directory
Microsoft Identity
Goggle
Facebook
Twitter auth
See how can you implement authentication:
Step:1
Step:2
Rest Function Code Sample:
Here I am giving you a simple code snippet to start with: though it's on Azure Table Storage, but help you to develop azure function and CRUD concept.
Your Sample Class:
public class YourSampleClass
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
}
Table Storage Class:
public class TableStorageClass
{
public TableStorageClass()
{
}
public TableStorageClass(DynamicTableEntity entity)
{
PartitionKey = entity.PartitionKey;
RowKey = entity.RowKey;
}
public string PartitionKey { get; set; }
public string RowKey { get; set; }
}
Azure Function V2 Example:
public static class FunctionReadFromTableStorage
{
[FunctionName("FunctionReadFromTableStorage")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
//Read Request Body
var content = await new StreamReader(req.Body).ReadToEndAsync();
//Extract Request Body and Parse To Class
YourSampleClass objYourSampleClass = JsonConvert.DeserializeObject<YourSampleClass>(content);
// Validate param because PartitionKey and RowKey is required to read from Table storage In this case , so I am checking here.
dynamic validationMessage;
if (string.IsNullOrEmpty(objYourSampleClass.PartitionKey))
{
validationMessage = new OkObjectResult("PartitionKey is required!");
return (IActionResult)validationMessage;
}
if (string.IsNullOrEmpty(objYourSampleClass.RowKey))
{
validationMessage = new OkObjectResult("RowKey is required!");
return (IActionResult)validationMessage;
}
// Table Storage operation with credentials
var client = new CloudTableClient(new Uri("https://YourStorageURL.table.core.windows.net/"),
new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials("YourStorageName", "xtaguZokAWbfYG4QDkBjT+YourStorageKey+T/kId/Ng+cl3TfYHtg=="));
var table = client.GetTableReference("YourTableName");
//Query filter
var query = new TableQuery()
{
FilterString = string.Format("PartitionKey eq '{0}' and RowKey eq '{1}'", objYourSampleClass.PartitionKey, objYourSampleClass.RowKey)
};
//Request for storage query with query filter
var continuationToken = new TableContinuationToken();
var storageTableQueryResults = new List<TableStorageClass>();
foreach (var entity in table.ExecuteQuerySegmentedAsync(query, continuationToken).GetAwaiter().GetResult().Results)
{
var request = new TableStorageClass(entity);
storageTableQueryResults.Add(request);
}
//As we have to return IAction Type So converting to IAction Class Using OkObjectResult We Even Can Use OkResult
var result = new OkObjectResult(storageTableQueryResults);
return (IActionResult)result;
}
}
Point To Remember:
In case of Azure Portal execution just get rid of FunctionReadFromTableStorage class
You Need following reference to execute above code
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.WindowsAzure.Storage.Table;
using System.Collections.Generic;
Postman Request Pattern:
Function Invoke Sample:
{
"PartitionKey": "Your Param According to Table Storage Design" ,
"RowKey": "Your Param According to Table Storage Design",
"Directory": "Your Param According to Table Storage Design"
}
See The Screen Shot:
Post Man Response:
Response is subject to my own table design
[
{
"partitionKey": "Microsoft SharePoint Server",
"rowKey": "2016"
}
]
See The Screen Shot Below:
Note: For CosmosDb Integration you could check here. Azure SQL with Function take a look here.
I haw an aggregate in my domain that have some Guid secondary keys.I want to get more info about these keys from another domains via RESTfull.
public class ProductAggregate
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public Guid AgencyId { get; set; }
public string AgencyTitle { get; set; }
}
In above code the AgencyTitle not exists in current domain and I want to get it from another live service via Restfull and send aggregated object to the client.
Is it a acceptable way?
It sounds like you are talking about a read model that you present to a user rather than an aggregate.
There are various ways you can handle this:
Local Caching
Keep an in-memory cache locally in your service that maps between AgencyId and AgencyTitle - this can either be through:
listening to an event (i.e. AgencyCreated). This would be preferred if you are have an event-driven system. You could also listen to other events (i.e. AgencyTitleUpdated) if relevant.
by making a web request to the external services. You would query your local cache first, and then decide if to call the external service. You'd need to think about how stale you allow your cache to become.
Denormalising the data
You could duplicate the data by saving the AgencyTitle alongside the AgencyId. This way you have no call to an external service. The tradeoff is you need to consider how often the AgencyTitle is likely to change, and how you handle that change.
Reporting "domain"
You could have a completely separate service that listens for data from other services and maintains view models for UIs. This would keep your other services ignorant of other service's concerns. When using an event-driven system, you'd be listening for events form other services that allow you to build a view model for the UI
I just started to read a lot about service bus architectures and looked more closely into the NServiceBus framework. I am not really getting an idea on how to design multiple private contexts where a set of clients are interested in the copies of the same message (e.g. a chatroom application).
Is the service bus supposed to exist only once or would I create multiple service bus instances, one for each virtual chatroom, and subscribe a message handler instance for each interested client?
Does it have something to do with the concept of topics and subscribes which I already read about in the context of Azure?
Is the service bus supposed to exist only once or would I create multiple service bus instances, one for each virtual chatroom, and subscribe a message handler instance for each interested client?
When using NServiceBus, you will configure a bus for each endpoint that you create. You could think of an endpoint as a service which handles certain messages. Endpoints aren't dynamic, they need to specify a name so that other endpoints can be configured to send messages to or receive messages from them.
It depends on what the requirements of your system are, but I'm assuming that a virtual chatroom is something that you can generate dynamically and/or remove when it's no longer in use.
Does it have something to do with the concept of topics and subscribes which I already read about in the context of Azure?
NServiceBus and Azure Service Bus both provide the infrastructure to do pub/sub.
I am not really getting an idea on how to design multiple private contexts where a set of clients are interested in the copies of the same message
What exactly do you mean by multiple private contexts? I am understanding your question as how to establish a relationship between a client and a chatroom. The part that is missing from your description is persistence, i.e. storing the relationship between a client and a chatroom.
Using NServiceBus as an example, you could have a ClientService that handles messages regarding any actions that clients take and a ChatroomService that handles messages regarding actions that occur within Chatrooms. Then the workflow could go:
Client enters chatroom (client sends command to client service)
ClientService adds information to Client object and updates it (persistence)
ClientService sends command to ChatroomService to update the list of clients associated with the corresponding chat room. (command)
Chatroom service updates list of subscribing clients (persistence)
Another client creates a Post in the chat room. (client sends command to ClientService)
ClientService sends command to ChatroomService with new Post and ID of client who created it, and the ID of the chatroom it was sent to (command)
ChatroomService adds the Post to the list of Posts in the corresponding chatroom (persistence)
ChatroomService generates events for all other clients in the list subscribing to the corresponding chatroom (publish)
ClientService handles the events raised by ChatroomService and distributes the Post to the other subscribed clients. (subscribe)
I haven't actually created a chat room application, so this may not be the best design for your idea but it provided a means of describing how you can use NServiceBus to create your application. You can set up services with endpoints that handle messages corresponding to objects in your system. With this or similar design, you have separation of concern and can scale your services as required based on the traffic that each object type must handle.
Editing to add a more specific example based on question in comments
Note: changed all references of text message to Post so that theres no ambiguity between chat message and IMessage in NServiceBus. I've been using terms command and event on purpose. In NServiceBus, ICommand is a type of message that can only be sent to 1 endpoint, whereas IEvent is a type of message that can be published and subscribed to by many endpoints.
Apologies if the example wasn't clear. What I was trying to convey is that you can store the relationship between Clients and Chatrooms so that when a Chatroom gets a new Post, it can be distributed to only the Clients that are related to it. Imagine that you have a chatroom CR and 3 clients A, B, and C that are all in CR. Also, lets say we have the following classes:
class Chatroom
{
Guid Id { get; set; }
List<Client> Subscribers { get; set; }
List<Posts> Posts { get; set; }
}
class Client
{
Guid Id { get; set; }
List<Chatroom> Chatrooms { get; set; }
ConnectionInfo Info { get; set; }
}
class Post
{
Guid Id { get; set; }
Guid ClientId { get; set; }
Guid ChatroomId { get; set; }
string Text { get; set; }
}
class NewPostCommand : ICommand
{
Post NewPost { get; set; }
}
class NewChatroomPostEvent : IEvent
{
Post NewPost { get; set; }
Chatroom Chatroom { get; set; }
List<Client> Subscribers { get; set; }
}
A creates a Post to CR, and this is implemented using a HTTP call from the client to an API. The API is part of an NServiceBus service that serves as the ClientService. The API call creates a Post that contains the text, A.Id, and CR.Id.
ClientService sends a NewPostCommand to ChatroomService with the Post that was just created.
ChatroomService receives NewPostCommand and passes it to the appropriate handler.
Handler searches for the corresponding Chatroom (CR) in your database using ChatroomId on the Post. The new Post is added to CR.Posts and updates the database.
Handler gets the list of CR.Clients minus Post.ClientId from the CR (resulting in B and C).
Handler publishes a new NewChatroomPostEvent that contains the Post, Chatroom and Subscribers.
ClientService subscribes to NewChatroomPostEvent, receives the message and passes it to the approriate handler.
ClientService has all the functionality for communicating with Clients (using Client.Info) and sends the new Post to each client in the NewChatroomPostEvent.Subscribers list (B and C).
Now that we've walked through the message flow of a new post, you can imagine how you would handle adding and removing subscribers from each chatroom. A client would send a message to the HTTP API when it enters or leaves a chatroom, the ClientService sends a message to the ChatroomService, which would update the appropriate Chatroom.Subscribers list. Hopefully this clarifies how you control which clients are sent updates when new posts arrive.
I'm trying to figure out how to log from my Mobile Service with a .NET backend. So far, I've read that you can do this by calling:
ApiController.ApiServices.Log.Info("log string")
This is fine if you're in an ApiController as you can simply use this.Services, but what would you do if you wanted to log from somewhere besides a controller? Is this even possible?
If by "besides a controller" you mean in a custom controller, you can declare
public ApiServices Services { get; set; }
and then use the Services.Log.Error("your error")
If this is not what you're asking, please give some more information.