Automating FusionCache with a Source Generator: A Step-by-Step Guide

Automating FusionCache with a Source Generator: A Step-by-Step Guide Using a source generator to automate code for calling the GetOrSetAsync function from FusionCache is an elegant way to handle caching. Let’s walk through how you can use Roslyn, the .NET Compiler Platform, to create a generator tailored to your needs. Step 1: Create the Custom Attribute Start by defining a FusionCacheAttribute that will decorate the methods you want to cache: ...

March 15, 2025 · 2 min · Taner

Challenges in Microservices Architecture: Key Considerations

Challenges in Microservices Architecture: Key Considerations Microservices architecture offers many benefits, but it also comes with several challenges. Here are some of the key challenges: 1. Complexity Designing and managing microservices can be complex. Determining the size, boundaries, and integration points for each service requires careful planning 1. 2. Communication Overhead Microservices need to communicate with each other, often over a network. This can introduce latency and increase the complexity of managing inter-service communication 1. ...

March 15, 2025 · 2 min · Taner

Challenges in Microservices Architecture: Key Considerations

When evaluating real-world applications, the choice between monolithic and microservices architectures hinges on balancing simplicity versus flexibility, centralized control versus distributed agility, and immediate performance against long-term scalability. Monolithic Architecture A monolithic system bundles all business logic, user interfaces, databases, and integrations into a single, unified application. This integration simplifies development and testing, as there’s just one codebase, one repository, and one deployment pipeline. For smaller applications or early-stage startups, this approach minimizes overhead, enabling teams to iterate rapidly with fewer cross-cutting concerns. However, as applications grow, the monolith can become unwieldy. Scaling becomes a challenge because you must replicate the entire system—even if only one component requires additional resources. Moreover, deploying a change in one part of the application necessitates redeploying the whole system, which increases the risk of widespread issues and can slow down development velocity significantly . ...

March 15, 2025 · 4 min · Taner

Choosing the Right Laptop: Beyond Benchmarks and Performance

A Tale of Two CPUs: Choosing the Right Fit Beyond Performance When it comes to choosing a new computer, the decision isn’t always about raw performance numbers. Sometimes, the surrounding factors—like upgradeability, operating systems, and future-proofing—play a bigger role. This is the story of how I navigated the crossroads between two impressive CPUs and ultimately chose the Intel Core Ultra 7 155U over the AMD Ryzen 7 8840HS. The Dilemma: A Battle of Titans As a tech enthusiast, I was torn between two powerful options: ...

March 15, 2025 · 3 min · TC

Complete Implementation of a Message Envelope Using Newtonsoft.Json

Complete Implementation using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; // For serialization and deserialization public abstract class MessageEnvelope<T> { // Immutable properties public string EventType { get; private init; } public string SourceService { get; private init; } public DateTime Timestamp { get; private init; } public Guid TraceId { get; private init; } public T Payload { get; private init; } // Private constructor to enforce the use of the builder private MessageEnvelope() { } // Static method to start building the envelope public static Builder CreateBuilder() => new Builder(); // Nested Builder class public class Builder { private readonly MessageEnvelope<T> _envelope = new ConcreteMessageEnvelope(); public Builder WithEventType(string eventType) { if (string.IsNullOrWhiteSpace(eventType)) throw new ArgumentException("EventType cannot be null or empty"); _envelope.EventType = eventType; return this; } public Builder WithSourceService(string sourceService) { if (string.IsNullOrWhiteSpace(sourceService)) throw new ArgumentException("SourceService cannot be null or empty"); _envelope.SourceService = sourceService; return this; } public Builder WithPayload(T payload) { _envelope.Payload = payload; return this; } public Builder WithTimestamp(DateTime timestamp) { _envelope.Timestamp = timestamp; return this; } public Builder WithTraceId(Guid traceId) { _envelope.TraceId = traceId; return this; } public Builder WithoutPayload() { _envelope.Payload = default; return this; } public MessageEnvelope<T> Build() { // Set defaults if not already set _envelope.EventType ??= "Unknown"; _envelope.Timestamp = _envelope.Timestamp == default ? DateTime.UtcNow : _envelope.Timestamp; _envelope.TraceId = _envelope.TraceId == default ? Guid.NewGuid() : _envelope.TraceId; return _envelope; } } // Clone method to replicate an envelope with modifications public MessageEnvelope<T> Clone() { return CreateBuilder() .WithEventType(this.EventType) .WithSourceService(this.SourceService) .WithPayload(this.Payload) .WithTimestamp(this.Timestamp) .WithTraceId(this.TraceId) .Build(); } // Serialization to JSON public string ToJson() { return JsonConvert.SerializeObject(this); } // Deserialization from JSON public static MessageEnvelope<T> FromJson(string json) { return JsonConvert.DeserializeObject<ConcreteMessageEnvelope>(json); } // Batch creation for multiple payloads public static IEnumerable<MessageEnvelope<T>> CreateBatch(IEnumerable<T> payloads, string eventType, string sourceService) { return payloads.Select(payload => CreateBuilder() .WithEventType(eventType) .WithSourceService(sourceService) .WithPayload(payload) .Build()); } // Example of a concrete implementation private class ConcreteMessageEnvelope : MessageEnvelope<T> { } } Examples 1. Basic Envelope Creation var envelope = MessageEnvelope<Reservation> .CreateBuilder() .WithEventType("ReservationExpiry") .WithSourceService("ReservationService") .WithPayload(new Reservation { ReservationId = "res-001", SlotId = "slot-123", ExpiryTime = DateTime.UtcNow }) .Build(); Console.WriteLine(envelope.ToJson()); 2. Creating an Envelope Without Payload var metadataOnlyEnvelope = MessageEnvelope<object> .CreateBuilder() .WithEventType("SystemEvent") .WithSourceService("MonitoringService") .WithoutPayload() .Build(); 3. Cloning an Envelope var clonedEnvelope = envelope.Clone(); Console.WriteLine(clonedEnvelope.ToJson()); 4. Batch Creation var reservations = new List<Reservation> { new Reservation { ReservationId = "res-001", SlotId = "slot-123", ExpiryTime = DateTime.UtcNow }, new Reservation { ReservationId = "res-002", SlotId = "slot-456", ExpiryTime = DateTime.UtcNow.AddHours(1) } }; var envelopes = MessageEnvelope<Reservation>.CreateBatch(reservations, "ReservationExpiry", "ReservationService"); foreach (var env in envelopes) { Console.WriteLine(env.ToJson()); } 5. Serialization and Deserialization string serialized = envelope.ToJson(); var deserialized = MessageEnvelope<Reservation>.FromJson(serialized); Console.WriteLine($"Deserialized TraceId: {deserialized.TraceId}"); Conclusion This implementation leverages Newtonsoft.Json to serialize and deserialize objects efficiently. The inclusion of batch creation, cloning, and flexibility makes this envelope a robust solution for designing reliable messaging systems in distributed architectures.

March 15, 2025 · 3 min · Taner

Configuring Hugo to Serve from Multiple Domains and IPs with Lighttpd

Configuring Hugo to Serve from Multiple Domains and IPs with Lighttpd Hosting a Hugo site across multiple domains and IPs can be achieved effortlessly by combining Hugo’s flexibility with Lighttpd’s robust domain routing. Here’s a step-by-step guide to set this up. Step 1: Configure Hugo Set Up Your Hugo Site: If you haven’t already, create a new Hugo site: hugo new site mysite Add Content and Themes: Populate your site with content and customize it with your desired themes. Set the Base URL: ...

March 15, 2025 · 2 min · Taner

Configuring Hugo to Serve from Multiple Domains and IPs with Nginx

Configuring Hugo to Serve from Multiple Domains and IPs with Nginx Hosting your Hugo site across multiple domains and IPs is simple when combining Hugo’s flexibility with Nginx’s robust configuration capabilities. This guide walks you through the steps to set up your site seamlessly. Step 1: Configure Hugo Set Up Your Hugo Site: If you haven’t already, create a new Hugo site: hugo new site mysite Add Content and Themes: ...

March 15, 2025 · 2 min · Taner

Crafting Effective User Stories for Agile Product Backlogs

Crafting Effective User Stories for Agile Product Backlogs Writing a good user story for a product backlog item (PBI) is all about being clear, concise, and user-focused. This guide walks you through the essentials of creating impactful user stories that drive collaboration and deliver value. Steps to Write a Good User Story 1. Stick to the Format A widely-used formula for user stories is: As a [user role], I want to [action] so that [benefit/goal]. This format keeps the focus on the user and clearly defines the purpose. ...

March 15, 2025 · 2 min · Taner

CrmServiceClient vs IOrganizationService: Understanding the Differences

CrmServiceClient vs IOrganizationService: Understanding the Differences Both CrmServiceClient and IOrganizationService play crucial roles in Dynamics 365 and Dataverse development. While they serve similar purposes, they offer different advantages depending on your development scenario. CrmServiceClient The CrmServiceClient is a more modern, feature-rich client that extends the functionality of IOrganizationService. Advantages: Connection String Support: Easily connect using a connection string Automatic Token Management: Handles authentication token renewal automatically Retry Policies: Built-in support for retrying failed connections Helper Methods: Includes additional utility methods for common operations Example Usage: string connectionString = "AuthType=OAuth;Url=https://myorg.crm.dynamics.com;AppId=00000000-0000-0000-0000-000000000000;RedirectUri=http://localhost;LoginPrompt=Auto"; using (var svc = new CrmServiceClient(connectionString)) { if (svc.IsReady) { Entity account = new Entity("account"); account["name"] = "Sample Account"; Guid accountId = svc.Create(account); Console.WriteLine($"Created account with ID: {accountId}"); } } IOrganizationService The IOrganizationService interface is the core interface for interacting with Dataverse/Dynamics 365 data. ...

March 15, 2025 · 2 min · Taner

Getting Started with Scrutor for Dependency Injection in .NET Core

Scrutor: Enhancing Dependency Injection in .NET Core Scrutor is a lightweight library for .NET Core that enhances dependency injection (DI) by enabling automated assembly scanning and registration of services. With Scrutor, you can reduce manual configuration by automatically discovering and registering services based on conventions or attributes. How It Works Scrutor builds on top of .NET Core’s built-in Dependency Injection (DI) framework. It simplifies service registration by: Scanning Assemblies: It scans through your project’s assemblies for classes or interfaces that match certain patterns or conventions. Auto-Registering Services: It automatically registers discovered classes with the DI container, specifying their lifetimes (e.g., Transient, Scoped, or Singleton). Applying Filters: You can use predicates to include or exclude specific types during registration. How to Set It Up 1. Install Scrutor Add the NuGet package to your project: ...

March 15, 2025 · 2 min · Taner