Search This Blog

2023-04-19

.NEt Core 6- Routing

 Routing is a process of matching incoming HTTP requests by checking the HTTP method and url; and then invoking corresponding endpoints (middlewares).


Example

Program.cs

 //routing with default parameter with constraint

    endpoints.Map("employee/profile/{employeename:minlength(3):maxlength(5)=Manab}", async (context) =>

    {

        string? employeename = Convert.ToString(context.Request.RouteValues["employeename"]);

        await context.Response.WriteAsync($"In Profle-{employeename}");

    });


    //routing with optional parameter with contraint

    endpoints.Map("products/details/{id:int?}", async (context) =>

    {

        if (context.Request.RouteValues.ContainsKey("id"))

        {

            int id = Convert.ToInt32(context.Request.RouteValues["id"]);

            await context.Response.WriteAsync($"In produts-{id}");

        }

        else

            await context.Response.WriteAsync($"In produts-id not supplied");

    });

2023-04-17

.NET Core 6- Middleware

 Middleware is a component that is assembled into the application pipeline to handle requests and responses.

Middlewares are chained one-after-other and execute in the same sequence how they're added.

Middleware can be a request delegate (anonymous method or lambda expression) [or] a class.

Middleware class is used to separate the middleware logic from a lambda expression to a separate / reusable class.

Middleware extension method is used to invoke the middleware with a single method call.


Example

Program.cs

using MyFirstApp.CustomMiddleware;


var builder = WebApplication.CreateBuilder(args);


builder.Services.AddTransient<MyCustomMiddleware>();//Add custom middleware using DI

var app = builder.Build();


//app.MapGet("/", () => "Hello World!");

//Request Response Modification

/*app.Run(async (HttpContext context) =>

{

    context.Response.StatusCode = 400;

    context.Response.Headers["MyKey"] = "my value";

    await context.Response.WriteAsync("<h1>Hello</h1>");

    await context.Response.WriteAsync("World");

}

);*/


//Middleware: Teminal or short circuit, it will not forward the request of the next middleware, so only render Hello

/*app.Run(async(HttpContext context) => {

    await context.Response.WriteAsync("Hello");

});


app.Run(async (HttpContext context) => {

    await context.Response.WriteAsync("Hello again");

});

*/



//Middleware Chain: O/p without queryString = From Middleware1 My custom middleware- starts From Middleware1 My custom middleware- ends. NOTE: data type HttpContext and RequestDelegate are optional

app.Use(async (HttpContext context, RequestDelegate next) => {

    await context.Response.WriteAsync("From Middleware1 ");

    await next(context);

});


//Middleware in custom class

//app.UseMiddleware<MyCustomMiddleware>();//without extension method, Option1

//app.UseMyCustomMiddleware();//Using extension method,Option2

//app.UseHelloCustomMiddleware();//use VS generated middleware class, Option3


//Middleware useWhen, O/p: From Middleware1 -Hello from Middleware Branch- From Middleware12 

app.UseWhen(context=>context.Request.Query.ContainsKey("userName"),

    app => {

        app.Use(async (context, next) =>

    {

        await context.Response.WriteAsync("-Hello from Middleware Branch-");

        await next(context);

    });

    });



app.Run(async (HttpContext context) => {

    await context.Response.WriteAsync(" From Middleware12 ");

});


app.Run();


MyCustomMiddleware.cs

namespace MyFirstApp.CustomMiddleware

{

    public class MyCustomMiddleware : IMiddleware

    {

        public async Task InvokeAsync(HttpContext context, RequestDelegate next)

        {

            await context.Response.WriteAsync("My custom middleware- starts");

           await next(context);

            await context.Response.WriteAsync("My custom middleware- ends");

        }        

    }

    public static class CustomMiddlewareExtension

    {

        public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder app) {

           return app.UseMiddleware<MyCustomMiddleware>();

        }

    }

}


HelloCustomMiddleware.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Threading.Tasks;
//generated automatically from add new item-?Middleware class
namespace MyFirstApp.CustomMiddleware
{
    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class HelloCustomMiddleware
    {
        private readonly RequestDelegate _next;

        public HelloCustomMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            if(httpContext.Request.Query.ContainsKey("firstName")
                && httpContext.Request.Query.ContainsKey("lastName"))
            {
                string fullName = httpContext.Request.Query
                    ["firstName"] + " " +
                  httpContext.Request.Query["lastName"];
                await httpContext.Response.WriteAsync(fullName);
            }

            await _next(httpContext);
        }
    }

    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class HelloCustomMiddlewareExtensions
    {
        public static IApplicationBuilder UseHelloCustomMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<HelloCustomMiddleware>();
        }
    }
}




2021-05-03

My Azure Study Note - 15 - Messaging- Service Bus, Event Hubs

Service Bus

• Fully managed, full blown message queueing service

• Durable

• Supports point-to-point (Queue) and pub/sub (Topic) scenarios

• Compatible with AMQP protocol

• Compatible with JMS 2.0 API (Premium only)





 Advanced features:
• Message sessions (guarantees FIFO)
• Dead-letter queue
• Scheduled delivery
• Transactions
• Duplicate detection
• And more…

Availability:

• SLA: 99.9%

• Can be configured for geo-disaster recovery 


Event Hubs

Big Data streaming platform and event ingestion service

• Note: No “messaging” in the description

• Basically a managed Kafka implementation

• Can receive millions of events per second

Event Producers
- Components generating the events
- Can be done by anyone with the client /
HTTP client
- Simple connection and API

Partition

- Single event stream

- Can think of it as a single queue

- Guarantees order

- Limited availability

- Better to spread messages across

partitions to improve availability

- …but then order is not guaranteed

- Max 32 partitions on a single Event Hubs

Consumer Group

- Logical group of receivers, belong to the

same application

- Example:

- Receivers for processing telemetry

= Consumer Group

- Receivers for storing the telemetry

= Consumer Group

- Event receiving is done via AMQP

protocol 

SLA:

• Basic and Standard tier: 99.95%

• Dedicated: 99.99% 

Event Hubs Throughput Units

• Throughput is measured in Throughput Units (TU)

• 1 TU =

• Ingress (Input) – 1MB / sec or 1000 events / sec

• Egress (Output) – 2MB / sec or 4096 events / sec

• Prepurchased, billed by the hour 


 

 

2021-05-02

My Azure Study Note - 14 - Messaging- Event Grid

Event Grid

• Allows building event-based architectures

• Publishes events to interested parties

• No queue / no order

• Strong integration with many Azure services

• Cost effective, simple pricing

• No tiers, HA is built in


 


SLA:
• 99.99%
• Max event size:
• 1MB

Event Grid

• Performance:

• 10,000,000 events / sec

• 5,000 events / sec / topic

• Latency:

• Subsecond end-to-end latency in the 99th percentile 

Event Grid Pricing

• Based on:

• Number of operations

• First 100K operations are free 

 Create Event Grid

The event will be triggered when some item will be added to the storage account and write to the cosmos db


Install package- Microsoft.Azure.Webjobs.Extensions.EventGrid

Copy the connection strings




ProcessOrderCosmos.cs

using Microsoft.Azure.WebJobs;

using Microsoft.Azure.WebJobs.Extensions.Http;

using Microsoft.AspNetCore.Http;

using Microsoft.Extensions.Logging;

using System.Threading.Tasks;

using System;

using System.IO;

using Newtonsoft.Json;

using System.Collections.Generic;

using Microsoft.Azure.WebJobs.Extensions.EventGrid;

using Microsoft.Azure.EventGrid.Models;

using Microsoft.Azure.Storage.Blob;


namespace AzureCourse.Function

{

    public static class CosmosOrderFunction

    {

        [FunctionName("ProcessOrderCosmos")]

        public static void Run(

            [EventGridTrigger]EventGridEvent eventGridEvent,

            [Blob("neworders", FileAccess.Write, Connection = "StorageConnectionString")] CloudBlobContainer container,

            [CosmosDB(databaseName: "readit-orders", collectionName: "orders", ConnectionStringSetting = "CosmosDBConnection")]out Order order,

            ILogger log)            

        {        


            order=null;


            try  {    

                log.LogInformation("Function started");

                log.LogInformation($"Event details: Topic: {eventGridEvent.Topic}");

                log.LogInformation($"Event data: {eventGridEvent.Data.ToString()}");


                string eventBody = eventGridEvent.Data.ToString(); 


                log.LogInformation("Deserializing to StorageBlobCreatedEventData...");

                var storageData=JsonConvert.DeserializeObject<StorageBlobCreatedEventData>(eventBody);  

                log.LogInformation("Done");


                log.LogInformation("Get the name of the new blob...");

                var blobName=Path.GetFileName(storageData.Url);

                log.LogInformation($"Name of file: {blobName}");


                log.LogInformation("Get blob from storage...");

                var blockBlob=container.GetBlockBlobReference(blobName);

                var orderText=blockBlob.DownloadText();

                log.LogInformation("Done");

                log.LogInformation($"Order text: {orderText}");

                

                order=JsonConvert.DeserializeObject<Order>(orderText);  

            }

            catch (Exception ex)  {

                log.LogError(ex, "Error in function");

            }            

        }

    }   

}

Create Event Subscription




 Now Upload a file azure storage account->Container, check the function app log and check the cosmos DB





Content of the uploaded json file as below