### ASP.NET Core Basic Authentication Setup and Usage Source: https://context7.com/codebeltnet/cuemon/llms.txt Configures and utilizes HTTP Basic Authentication in ASP.NET Core. It includes setting up the authentication service, defining a credential validator, and protecting an endpoint. It also demonstrates programmatic creation and parsing of the Basic Authorization header. ```csharp using Cuemon.AspNetCore.Authentication.Basic; using Cuemon.Extensions.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using System.Security.Claims; var builder = WebApplication.CreateBuilder(args); // Configure Basic authentication builder.Services.AddAuthentication("Basic") .AddBasic(options => { options.Realm = "My API"; // Credential validator options.Authenticator = (username, password, context) => { // Validate against your user store if (username == "admin" && password == "secret123") { return new ClaimsPrincipal(new ClaimsIdentity( new[] { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, "Administrator") }, "Basic" )); } return null; // Authentication failed }; }); var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); // Protected endpoint app.MapGet("/api/secure", () => Results.Ok("Authenticated!")) .RequireAuthorization(); app.Run(); // Programmatic header creation public class ApiClient { public void CreateAuthHeader() { // Create Basic auth header var header = new BasicAuthorizationHeader("admin", "secret123"); Console.WriteLine(header.ToString()); // Output: Basic YWRtaW46c2VjcmV0MTIz // Parse existing header var parsed = BasicAuthorizationHeader.Create("Basic YWRtaW46c2VjcmV0MTIz"); Console.WriteLine($"Username: {parsed.UserName}"); Console.WriteLine($"Password: {parsed.Password}"); } } ``` -------------------------------- ### Argument Validation with Validator in C# Source: https://context7.com/codebeltnet/cuemon/llms.txt Demonstrates the usage of the Validator class from Cuemon for .NET to perform various argument validations. This includes checking for null or whitespace strings, email formats, numeric ranges, GUID and URI formats, disposed states, and custom conditional logic. It helps reduce boilerplate validation code and provides consistent error messages. ```csharp using Cuemon; public class UserService { public User CreateUser(string username, string email, int age) { // Validate null or whitespace strings Validator.ThrowIfNullOrWhitespace(username); // Validate email format Validator.ThrowIfNotEmailAddress(email); // Validate numeric ranges Validator.ThrowIfLowerThan(age, 18, nameof(age), "User must be 18 or older"); Validator.ThrowIfGreaterThan(age, 120, nameof(age), "Invalid age value"); return new User { Username = username, Email = email, Age = age }; } public void ProcessItems(IEnumerable items) { // Validate collection is not null or empty Validator.ThrowIfSequenceNullOrEmpty(items); foreach (var item in items) { Validator.ThrowIfEmpty(item); } } public void ValidateGuid(string guidString) { // Validate GUID format Validator.ThrowIfNotGuid(guidString, GuidFormats.D); } public void ValidateUri(string url) { // Validate URI format Validator.ThrowIfNotUri(url, UriKind.Absolute); } // Validate state instead of arguments public void EnsureNotDisposed(bool isDisposed, object instance) { Validator.ThrowIfDisposed(isDisposed, instance, "Cannot access disposed resource"); } // Custom conditional validation public void ValidateCondition(bool condition, string paramName) { Validator.ThrowIfTrue(condition, paramName, "Condition must be false"); Validator.ThrowIfFalse(!condition, paramName, "Condition must be true"); } } // Output when validation fails: // ArgumentNullException: Value cannot be null. (Parameter 'username') // ArgumentException: Value must be an email address. (Parameter 'email') // ArgumentOutOfRangeException: User must be 18 or older (Parameter 'age') ``` -------------------------------- ### Build Solution and Projects with .NET CLI Source: https://github.com/codebeltnet/cuemon/blob/main/AGENTS.md Commands to build the entire .NET solution or individual projects in Release configuration. Also includes packing all NuGet packages. ```bash dotnet build -c Release dotnet build src/Cuemon.Core/Cuemon.Core.csproj -c Release dotnet pack -c Release ``` -------------------------------- ### Run Unit and Functional Tests with .NET CLI Source: https://github.com/codebeltnet/cuemon/blob/main/AGENTS.md Demonstrates how to execute all tests within a project, a single specific test using a filter, or all tests in the root test directory. ```bash # all tests in one project dotnet test test/Cuemon.Core.Tests/Cuemon.Core.Tests.csproj -c Release # single test (recommended when iterating) dotnet test test/Cuemon.Core.Tests/Cuemon.Core.Tests.csproj -c Release \ --filter "FullyQualifiedName~DateSpanTest.Parse_ShouldGetOneMonthOfDifference_UsingIso8601String" # all tests dotnet test -c Release test/ ``` -------------------------------- ### xUnit v3 Test File Template (C#) Source: https://github.com/codebeltnet/cuemon/blob/main/AGENTS.md A template for creating unit tests using xUnit v3 in C#. It demonstrates the correct base class, constructor signature, and test method structure. Ensure the namespace matches the System Under Test (SUT) namespace exactly. ```csharp using Codebelt.Extensions.Xunit; using Xunit; namespace Cuemon.Foo // matches SUT namespace exactly { public class BarTest : Test { public BarTest(ITestOutputHelper output) : base(output) { } [Fact] public void Method_ShouldExpectedBehavior_WhenCondition() { // Arrange / Act / Assert } } } ``` -------------------------------- ### Utility Patterns with Cuemon.Patterns in C# Source: https://context7.com/codebeltnet/cuemon/llms.txt Illustrates various utility methods provided by the Cuemon.Patterns class for common design patterns. This includes try-invoke for safe operations, safe resource handling for IDisposable objects, and options configuration. Dependencies include Cuemon and Cuemon.Configuration. ```csharp using Cuemon; using Cuemon.Configuration; public class PatternExamples { // Try-Parse pattern - attempt operation without throwing public void TryInvokeExample() { // Returns true/false based on success var success = Patterns.TryInvoke(() => { // Operation that might fail File.ReadAllText("config.json"); }); Console.WriteLine($"Operation succeeded: {success}"); // With result if (Patterns.TryInvoke(() => int.Parse("123"), out var number)) { Console.WriteLine($"Parsed: {number}"); } // Return default on failure var value = Patterns.InvokeOrDefault( () => int.Parse("not a number"), fallbackResult: -1 ); Console.WriteLine($"Value: {value}"); // -1 } // Options pattern configuration public void ConfigureOptionsExample() { // Configure options with delegate var options = Patterns.Configure(opt => { opt.Name = "Test"; opt.MaxRetries = 3; }); Console.WriteLine($"Name: {options.Name}, Retries: {options.MaxRetries}"); } // Safe invoke for IDisposable resources (CA2000 compliant) public void SafeInvokeExample() { var result = Patterns.SafeInvoke( initializer: () => new MemoryStream(), tester: (stream) => { stream.Write(new byte[] { 1, 2, 3 }); return stream; // Return stream if successful }, catcher: (ex) => { Console.WriteLine($"Error: {ex.Message}"); } ); // result is disposed automatically if tester fails } // Check for fatal exceptions in catch blocks public void HandleExceptionSafely() { try { DoSomething(); } catch (Exception ex) when (Patterns.IsRecoverableException(ex)) { // Safe to catch - not a fatal runtime exception Console.WriteLine($"Handled: {ex.Message}"); } // Fatal exceptions (OutOfMemoryException, etc.) propagate up } } // Options class example public class MyOptions : IParameterObject { public string Name { get; set; } public int MaxRetries { get; set; } = 5; } ``` -------------------------------- ### Non-Cryptographic Hashing with Cuemon.NET HashFactory Source: https://context7.com/codebeltnet/cuemon/llms.txt Demonstrates the use of `HashFactory` to create and compute various non-cryptographic hash values, including different variants of FNV (Fowler-Noll-Vo) and CRC (Cyclic Redundancy Check) algorithms. It shows how to configure algorithm variants and compute hashes for byte arrays. ```csharp using Cuemon.Security; using System; using System.Text; public class HashingExamples { public void ComputeHashes() { var data = "Hello, World!"; var bytes = Encoding.UTF8.GetBytes(data); // FNV-1a 32-bit hash (fast, non-cryptographic) using var fnv32 = HashFactory.CreateFnv32(); var hash32 = fnv32.ComputeHash(bytes); Console.WriteLine($"FNV32: {hash32.ToHexadecimalString()}"); // FNV-1a 64-bit hash using var fnv64 = HashFactory.CreateFnv64(); var hash64 = fnv64.ComputeHash(bytes); Console.WriteLine($"FNV64: {hash64.ToHexadecimalString()}"); // FNV-1a 128-bit hash using var fnv128 = HashFactory.CreateFnv128(); var hash128 = fnv128.ComputeHash(bytes); Console.WriteLine($"FNV128: {hash128.ToHexadecimalString()}"); // Configure FNV algorithm variant using var fnvCustom = HashFactory.CreateFnv(NonCryptoAlgorithm.Fnv256, options => { options.Algorithm = FowlerNollVoAlgorithm.Fnv1; // Original FNV-1 }); var hashCustom = fnvCustom.ComputeHash(bytes); Console.WriteLine($"FNV256 (FNV-1): {hashCustom.ToHexadecimalString()}"); // CRC32 checksum using var crc32 = HashFactory.CreateCrc32(); var crcHash = crc32.ComputeHash(bytes); Console.WriteLine($"CRC32: {crcHash.ToHexadecimalString()}"); // CRC64 with specific algorithm using var crc64 = HashFactory.CreateCrc(CyclicRedundancyCheckAlgorithm.Crc64Xz); var crc64Hash = crc64.ComputeHash(bytes); Console.WriteLine($"CRC64-XZ: {crc64Hash.ToHexadecimalString()}"); } } // Output: // FNV32: 7b2e2d58 // FNV64: 6ef05bd7cc857c54 // FNV128: 2c6d5a8b3f2e4d1c5a7b8e9f0a1b2c3d // FNV256 (FNV-1): ... // CRC32: 1c291ca3 // CRC64-XZ: 64b5e4c7a8d32f1e ``` -------------------------------- ### Configure Dependency Injection Services (C#) Source: https://context7.com/codebeltnet/cuemon/llms.txt This C# code snippet shows how to configure Cuemon services within the built-in Dependency Injection container in an ASP.NET Core application. It covers registering options, formatters, throttling services, and custom services with automatic lifetime detection. ```csharp using Cuemon.Extensions.DependencyInjection; using Cuemon.Extensions.AspNetCore.Authentication; using Cuemon.Extensions.AspNetCore.Diagnostics; using Microsoft.Extensions.DependencyInjection; var builder = WebApplication.CreateBuilder(args); // Add exception descriptor options with formatter builder.Services.AddExceptionDescriptorOptions(options => { options.SensitivityDetails = FaultSensitivityDetails.Evidence; }); // Add JSON formatters for exception responses builder.Services.AddExceptionResponseFormatters(formatters => { formatters.AddJsonExceptionFormatter(); formatters.AddXmlExceptionFormatter(); }); // Add throttling services builder.Services.AddThrottlingCache(); // Register services with automatic lifetime detection builder.Services.TryAdd(ServiceLifetime.Scoped); // Register multiple implementations builder.Services.AddServices(scanner => { scanner.FromAssemblyOf() .AddClasses(classes => classes.AssignableTo()) .AsImplementedInterfaces() .WithScopedLifetime(); }); var app = builder.Build(); ``` -------------------------------- ### ASP.NET Core Exception Handling Middleware Source: https://context7.com/codebeltnet/cuemon/llms.txt This middleware provides comprehensive exception handling with RFC 7807 Problem Details support. It allows for custom configuration of fault descriptors, sensitivity levels, and exception callbacks. ```APIDOC ## ASP.NET Core Exception Handling Middleware ### Description Provides RFC 7807 Problem Details compliant exception handling for ASP.NET Core applications. Allows customization of error responses, including sensitivity levels and custom error resolution. ### Method `UseFaultDescriptorExceptionHandler()` ### Endpoint Applies globally to the ASP.NET Core pipeline. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp // Example of configuring options in Program.cs builder.Services.Configure(options => { options.RootHelpLink = new Uri("https://api.example.com/docs/errors"); options.SensitivityDetails = FaultSensitivityDetails.All; // Development options.ExceptionCallback = (context, exception, descriptor) => { Console.WriteLine($"Error {descriptor.StatusCode}: {exception.Message}"); }; options.HttpFaultResolvers.Add(new HttpFaultResolver( typeof(DomainException), (exception) => new HttpExceptionDescriptor(exception, statusCode: 422, message: "Domain validation failed") )); }); // Applying the middleware app.UseFaultDescriptorExceptionHandler(); ``` ### Response #### Success Response (200) Standard HTTP 200 OK response for successful requests. #### Error Response (e.g., 400, 404, 422, 500) ```json { "error": { "status": 404, "code": "NotFound", "message": "User with ID 404 not found", "helpLink": "https://api.example.com/docs/errors" } } ``` #### Response Example (Specific Exception) ```json { "error": { "status": 422, "code": "DomainValidationFailed", "message": "Domain validation failed", "helpLink": "https://api.example.com/docs/errors/domain" } } ``` ``` -------------------------------- ### ASP.NET Core HTTP Request Throttling Middleware Source: https://context7.com/codebeltnet/cuemon/llms.txt Implements rate limiting for ASP.NET Core APIs using the Throttling Sentinel middleware. It allows configuration of request quotas, client identification methods, and custom responses for exceeding limits. Dependencies include Cuemon.AspNetCore.Http.Throttling and Microsoft.AspNetCore.Builder. ```csharp using Cuemon.AspNetCore.Http.Throttling; using Cuemon.Extensions.AspNetCore.Http.Throttling; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; var builder = WebApplication.CreateBuilder(args); // Register throttling cache (in-memory or distributed) builder.Services.AddSingleton(); var app = builder.Build(); // Add throttling middleware with configuration app.UseThrottlingSentinel(options => { // Maximum 100 requests per minute per client options.Quota = new ThrottleQuota(100, TimeSpan.FromMinutes(1)); // How to identify clients (by IP, API key, user, etc.) options.ContextResolver = context => { // Use API key if present, otherwise IP address if (context.Request.Headers.TryGetValue("X-API-Key", out var apiKey)) { return apiKey.ToString(); } return context.Connection.RemoteIpAddress?.ToString() ?? "unknown"; }; // Custom response when throttled options.RateLimitExceededMessage = "API rate limit exceeded. Please try again later."; // Add retry-after header options.RetryAfterHeader = true; }); // Endpoints are now protected by throttling app.MapGet("/api/data", () => Results.Ok(new { message = "Success" })); app.Run(); // When rate limit exceeded, response: // HTTP 429 Too Many Requests // Retry-After: 45 // { // "error": { // "status": 429, // "message": "API rate limit exceeded. Please try again later." // } // } ``` -------------------------------- ### ASP.NET Core Exception Handling with RFC 7807 Problem Details Source: https://context7.com/codebeltnet/cuemon/llms.txt Configures ASP.NET Core to handle exceptions using RFC 7807 Problem Details format. It allows customization of error responses, logging, and custom fault resolution for domain-specific exceptions. Dependencies include Cuemon.AspNetCore.Diagnostics and Microsoft.AspNetCore.Builder. ```csharp using Cuemon.AspNetCore.Diagnostics; using Cuemon.AspNetCore.Http; using Cuemon.Extensions.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; var builder = WebApplication.CreateBuilder(args); // Configure fault descriptor options builder.Services.Configure(options => { // Set root help link for API documentation options.RootHelpLink = new Uri("https://api.example.com/docs/errors"); // Configure sensitivity - what details to include in responses options.SensitivityDetails = FaultSensitivityDetails.All; // Development // options.SensitivityDetails = FaultSensitivityDetails.None; // Production // Custom exception callback for logging options.ExceptionCallback = (context, exception, descriptor) => { Console.WriteLine($"Error {descriptor.StatusCode}: {exception.Message}"); Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}"); }; // Add custom fault resolvers for domain exceptions options.HttpFaultResolvers.Add(new HttpFaultResolver( typeof(DomainException), (exception) => new HttpExceptionDescriptor( exception, statusCode: 422, message: "Domain validation failed", helpLink: new Uri("https://api.example.com/docs/errors/domain") ) )); }); var app = builder.Build(); // Use the fault descriptor exception handler app.UseFaultDescriptorExceptionHandler(); // Example endpoint that throws app.MapGet("/api/users/{id}", (int id) => { if (id <= 0) throw new BadRequestException("Invalid user ID"); if (id == 404) throw new NotFoundException($"User with ID {id} not found"); return Results.Ok(new { Id = id, Name = "John Doe" }); }); app.Run(); // Custom domain exception public class DomainException : Exception { public DomainException(string message) : base(message) { } } // Response for NotFoundException (HTTP 404): // { // "error": { // "status": 404, // "code": "NotFound", // "message": "User with ID 404 not found", // "helpLink": "https://api.example.com/docs/errors" // } // } ``` -------------------------------- ### C# TransientOperation: Basic Retry with Default Options Source: https://context7.com/codebeltnet/cuemon/llms.txt Implements a basic retry mechanism for an asynchronous operation using default TransientOperation settings. This typically involves a set number of retries with exponential backoff. It takes a URL as input and returns the string content fetched from that URL. ```csharp using Cuemon.Resilience; public class ResilientApiClient { private readonly HttpClient _httpClient; public ResilientApiClient(HttpClient httpClient) { _httpClient = httpClient; } // Basic retry with default options (5 retries, exponential backoff) public async Task GetDataWithRetryAsync(string url) { var result = await TransientOperation.WithFuncAsync( async () => await _httpClient.GetStringAsync(url) ); return result; } } ``` -------------------------------- ### C# TransientOperation: Global Fault Callback for Logging Source: https://context7.com/codebeltnet/cuemon/llms.txt Sets up a global fault callback for the TransientOperation class to log details about transient faults. This callback is executed whenever a retryable fault occurs, providing information such as the exception message, attempt number, and latency. This is typically defined in a static constructor. ```csharp using Cuemon.Resilience; public class ResilientApiClient { private readonly HttpClient _httpClient; public ResilientApiClient(HttpClient httpClient) { _httpClient = httpClient; } // Global fault callback for logging static ResilientApiClient() { TransientOperation.FaultCallback = evidence => { Console.WriteLine($"Transient fault occurred: {evidence.Exception.Message}"); Console.WriteLine($"Attempt: {evidence.Attempt}, Latency: {evidence.Latency}"); }; } } ``` -------------------------------- ### Add Server-Timing Header to HTTP Responses (C#) Source: https://context7.com/codebeltnet/cuemon/llms.txt This C# code snippet demonstrates how to add the Server-Timing header to HTTP responses in an ASP.NET Core application using Cuemon.AspNetCore.Diagnostics. It allows for performance metrics to be added, including custom timing metrics and descriptive information. ```csharp using Cuemon.AspNetCore.Diagnostics; using Cuemon.Extensions.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Builder; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); // Add Server-Timing header to all responses app.UseServerTiming(); app.MapGet("/api/data", async (HttpContext context) => { var serverTiming = context.GetServerTiming(); // Add custom timing metrics using (serverTiming.Measure("db-query")) { await Task.Delay(50); // Simulate database query } using (serverTiming.Measure("cache-lookup")) { await Task.Delay(10); // Simulate cache lookup } serverTiming.AddMetric("total-items", 42, "Total items processed"); return Results.Ok(new { data = "Response data" }); }); app.Run(); // Response Headers: // Server-Timing: db-query;dur=50.2, cache-lookup;dur=10.1, total-items;desc="Total items processed";dur=42 ``` -------------------------------- ### HTTP Request Throttling Middleware Source: https://context7.com/codebeltnet/cuemon/llms.txt This middleware implements rate limiting to protect APIs from abuse. It allows configuration of request quotas, client identification, and custom responses for exceeding limits. ```APIDOC ## HTTP Request Throttling Middleware ### Description Provides rate limiting capabilities to protect APIs from abuse and ensure fair usage. Configurable with quotas, client resolvers, and custom error messages. ### Method `UseThrottlingSentinel()` ### Endpoint Applies globally to the ASP.NET Core pipeline. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp // Example of configuring options in Program.cs builder.Services.AddSingleton(); // Register cache app.UseThrottlingSentinel(options => { options.Quota = new ThrottleQuota(100, TimeSpan.FromMinutes(1)); // 100 requests per minute options.ContextResolver = context => context.Connection.RemoteIpAddress?.ToString() ?? "unknown"; // Identify by IP options.RateLimitExceededMessage = "API rate limit exceeded. Please try again later."; options.RetryAfterHeader = true; }); ``` ### Response #### Success Response (200) Standard HTTP 200 OK response for successful requests. #### Error Response (429 Too Many Requests) Returned when the client exceeds the defined rate limit. #### Response Example ```json { "error": { "status": 429, "message": "API rate limit exceeded. Please try again later." } } ``` #### Headers - **Retry-After** (integer) - The number of seconds the client must wait before making another request (if `RetryAfterHeader` is true). ``` -------------------------------- ### Cache Validation with CacheValidator in C# Source: https://context7.com/codebeltnet/cuemon/llms.txt Demonstrates how to use the CacheValidator class for cache-friendly validation of data-centric content. It supports ETags and Last-Modified headers, and can be integrated into ASP.NET Core applications. Dependencies include Cuemon.Data.Integrity and Cuemon.Security. ```csharp using Cuemon.Data.Integrity; using Cuemon.Security; public class CacheValidationExample { public CacheValidator CreateValidator() { // Create validator from entity metadata var entity = new EntityInfo( created: DateTime.UtcNow.AddDays(-7), modified: DateTime.UtcNow, checksum: new byte[] { 1, 2, 3, 4, 5 } ); var validator = new CacheValidator( entity, () => HashFactory.CreateFnv128(), EntityDataIntegrityMethod.Combined ); Console.WriteLine($"Created: {validator.Created}"); Console.WriteLine($"Modified: {validator.Modified}"); Console.WriteLine($"Checksum: {validator.ComputedHash.ToHexadecimalString()}"); return validator; } public void CompareValidators() { var validator1 = CreateValidator(); var validator2 = CreateValidator(); // Get the most significant validator (most recently modified) var mostRecent = CacheValidator.GetMostSignificant(validator1, validator2); Console.WriteLine($"Most recent: {mostRecent.GetMostSignificant()}"); // Use reference point for assembly-level caching var refPoint = CacheValidator.ReferencePoint; Console.WriteLine($"Reference point: {refPoint.ComputedHash.ToHexadecimalString()}"); } // Use in ASP.NET Core for HTTP caching public IActionResult GetResource() { var validator = CreateValidator(); // Use for ETag header Response.Headers["ETag"] = $"\"{validator.ComputedHash.ToHexadecimalString()}\"""; // Use for Last-Modified header Response.Headers["Last-Modified"] = validator.GetMostSignificant() .ToString("R"); // RFC 1123 format return Ok(data); } } ``` -------------------------------- ### C# TransientOperation: Custom Retry Configuration Source: https://context7.com/codebeltnet/cuemon/llms.txt Configures custom retry logic for fetching data, specifying the number of retry attempts, delay between retries, and enabling recovery. It defines a custom detection strategy to retry on specific exceptions like HttpRequestException, TimeoutException, or TaskCanceledException. This method takes an endpoint string and returns the fetched data as a string. ```csharp using Cuemon.Resilience; public class ResilientApiClient { private readonly HttpClient _httpClient; public ResilientApiClient(HttpClient httpClient) { _httpClient = httpClient; } // Custom retry configuration public string FetchDataWithCustomRetry(string endpoint) { return TransientOperation.WithFunc( () => _httpClient.GetStringAsync(endpoint).Result, options => { options.RetryAttempts = 3; options.RetryDelay = TimeSpan.FromSeconds(2); options.EnableRecovery = true; // Define which exceptions should trigger retry options.DetectionStrategy = exception => exception is HttpRequestException || exception is TimeoutException || exception is TaskCanceledException; } ); } } ``` -------------------------------- ### C# TransientOperation: Execute Operation with Parameters and Retry Source: https://context7.com/codebeltnet/cuemon/llms.txt Performs a function that takes a parameter and returns a result, with retry logic. This allows for more complex operations to be retried by specifying the operation, its argument, and retry options. It configures a fixed number of retry attempts and enables recovery. The method is generic, accepting types T and TResult. ```csharp using Cuemon.Resilience; public class ResilientApiClient { private readonly HttpClient _httpClient; public ResilientApiClient(HttpClient httpClient) { _httpClient = httpClient; } // With parameters public TResult ExecuteWithRetry(Func operation, T argument) { return TransientOperation.WithFunc( operation, argument, options => { options.RetryAttempts = 3; options.EnableRecovery = true; } ); } } ``` -------------------------------- ### C# TransientOperation: Action with Retry (No Return Value) Source: https://context7.com/codebeltnet/cuemon/llms.txt Executes an action that does not return a value, with retry logic applied. This is suitable for operations like sending data where the success is determined by the absence of exceptions. It configures the number of retry attempts and the delay between them. The method takes a string 'data' as input. ```csharp using Cuemon.Resilience; public class ResilientApiClient { private readonly HttpClient _httpClient; public ResilientApiClient(HttpClient httpClient) { _httpClient = httpClient; } // Action with retry (no return value) public void SendDataWithRetry(string data) { TransientOperation.WithAction( () => { var content = new StringContent(data); var response = _httpClient.PostAsync("/api/data", content).Result; response.EnsureSuccessStatusCode(); }, options => { options.RetryAttempts = 5; options.RetryDelay = TimeSpan.FromMilliseconds(500); } ); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.