### Install FlowRight NuGet Packages Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Installs the core FlowRight Result pattern package and optional validation and HTTP integration packages using the .NET CLI. ```bash dotnet add package FlowRight.Core --prerelease dotnet add package FlowRight.Validation --prerelease dotnet add package FlowRight.Http --prerelease ``` -------------------------------- ### Install FlowRight NuGet Packages Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Installs the core FlowRight Result pattern package and optional validation and HTTP integration packages using the .NET CLI. ```bash dotnet add package FlowRight.Core --prerelease dotnet add package FlowRight.Validation --prerelease dotnet add package FlowRight.Http --prerelease ``` -------------------------------- ### Install FlowRight NuGet Packages Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Installs the core FlowRight Result pattern library and optional validation and HTTP integration packages using the .NET CLI. Assumes .NET 8.0 or later. ```bash dotnet add package FlowRight.Core --prerelease dotnet add package FlowRight.Validation --prerelease dotnet add package FlowRight.Http --prerelease ``` -------------------------------- ### C# FlowRight HTTP Integration Examples Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Demonstrates how to integrate FlowRight with HTTP requests and responses. It includes methods for converting HTTP responses to Results and explains the standard status code mappings to FlowRight Result types. ```C# // Convert HTTP response to Result await response.ToResultAsync() await response.ToResultFromJsonAsync() // Status code mappings // 2xx → Success // 400 → ValidationFailure // 401/403 → SecurityFailure // 404 → NotFound // 5xx → Failure ``` -------------------------------- ### C# FlowRight Essential Result Methods Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Provides examples of essential methods for creating, checking, and pattern matching with FlowRight's Result type. This includes static methods for success/failure creation and instance methods for accessing values, errors, and performing matches. ```C# // Creating Results Result.Success(value) Result.Failure(message) Result.NotFound(message) Result.ValidationFailure(message) Result.SecurityFailure(message) // Checking Results result.IsSuccess result.IsFailure result.Value // Only safe when IsSuccess result.Error // Only meaningful when IsFailure result.ResultType // Pattern Matching result.Match(onSuccess, onFailure) result.Switch(onSuccess, onFailure) // Combining Results Result.Combine(result1, result2, result3) ``` -------------------------------- ### Chain Operations with FlowRight in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html This C# example shows how to chain multiple operations using FlowRight's Match method. It demonstrates a functional approach to handling success and failure at each step, allowing for sequential processing of data transformations and validations. ```C# public Result ProcessUserData(int userId) { return GetUser(userId) .Match( onSuccess: user => ValidateUser(user) .Match( onSuccess: validUser => FormatUserData(validUser), onFailure: error => Result.Failure(error) ), onFailure: error => Result.Failure(error) ); } ``` -------------------------------- ### C# Service Layer Pattern Example Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Demonstrates the Service Layer pattern using FlowRight's Result type for handling operations like user creation. It includes input validation, repository interaction, and asynchronous email sending, with logging for failures. ```C# public class UserService { private readonly IUserRepository _repository; private readonly IEmailService _emailService; public async Task> CreateUserAsync(CreateUserRequest request) { // Validate input Result validationResult = ValidateCreateUserRequest(request); if (validationResult.IsFailure) return validationResult; // Create user Result createResult = await _repository.CreateAsync(validationResult.Value); if (createResult.IsFailure) return createResult; // Send welcome email (don't fail if this fails) Result emailResult = await _emailService.SendWelcomeEmailAsync(createResult.Value); if (emailResult.IsFailure) { // Log warning but continue _logger.LogWarning("Failed to send welcome email: {Error}", emailResult.Error); } return createResult; } } ``` -------------------------------- ### FlowRight Built-in Validation Rules Examples Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Provides examples of various built-in validation rules available in FlowRight for strings, numbers, and collections. It also shows how to implement custom validation logic using the Must method. ```csharp // String validation .NotEmpty() .MinimumLength(5) .MaximumLength(100) .Length(10, 20) .Matches(@"^\d{3}-\d{2}-\d{4}$") .EmailAddress() .Url() .AlphaNumeric() // Numeric validation .GreaterThan(0) .GreaterThanOrEqualTo(1) .LessThan(100) .LessThanOrEqualTo(99) .Between(1, 100) .Positive() .NotZero() // Collection validation .NotEmpty() .MinCount(1) .MaxCount(10) .Unique() // Custom validation .Must(value => IsValidBusinessRule(value)) .WithMessage("Custom validation failed") ``` -------------------------------- ### Get Weather Data with Basic HTTP Integration Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Demonstrates basic HTTP integration using FlowRight's extension methods. It shows how to make an asynchronous GET request to a weather API and convert the HttpResponseMessage to a Result of WeatherData. ```csharp using FlowRight.Http.Extensions; public class WeatherService { private readonly HttpClient _httpClient; public async Task> GetWeatherAsync(string city) { HttpResponseMessage response = await _httpClient.GetAsync($"/weather/{city}"); return await response.ToResultFromJsonAsync(); } } ``` -------------------------------- ### Bash: Install FlowRight Packages Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/migration-guide.html Command to install the core, validation, and HTTP packages for FlowRight using the .NET CLI. ```Bash # Install FlowRight packages dotnet add package FlowRight.Core dotnet add package FlowRight.Validation dotnet add package FlowRight.Http ``` -------------------------------- ### C# API Controller Pattern Example Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Illustrates the API Controller pattern with FlowRight integration for handling HTTP requests. It shows how to use the Result type to map operation outcomes to appropriate HTTP status codes like Ok, NotFound, Forbid, and BadRequest. ```C# [ApiController] [Route("api/[controller]")] public class UsersController : ControllerBase { private readonly IUserService _userService; [HttpGet("{id}")] public async Task> GetUser(int id) { Result result = await _userService.GetUserAsync(id); return result.Match>( onSuccess: user => Ok(user), onFailure: error => result.ResultType switch { ResultType.NotFound => NotFound(error), ResultType.SecurityFailure => Forbid(), _ => BadRequest(error) } ); } [HttpPost] public async Task> CreateUser(CreateUserRequest request) { Result result = await _userService.CreateUserAsync(request); return result.Match>( onSuccess: user => CreatedAtAction(nameof(GetUser), new { id = user.Id }, user), onFailure: error => BadRequest(error) ); } } ``` -------------------------------- ### Basic HTTP Integration with FlowRight in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Demonstrates how to use FlowRight's HTTP extensions to automatically convert HTTP responses into Result objects, simplifying API interactions. ```C# using FlowRight.Http.Extensions; public class WeatherService { private readonly HttpClient _httpClient; public async Task> GetWeatherAsync(string city) { HttpResponseMessage response = await _httpClient.GetAsync($"/weather/{city}"); return await response.ToResultFromJsonAsync(); } } ``` -------------------------------- ### FlowRight Built-in Validation Rules Examples Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Provides examples of various built-in validation rules available in FlowRight for strings, numbers, and collections. It also shows how to implement custom validation logic using the Must method. ```csharp // String validation .NotEmpty() .MinimumLength(5) .MaximumLength(100) .Length(10, 20) .Matches(@"^\d{3}-\d{2}-\d{4}$") .EmailAddress() .Url() .AlphaNumeric() // Numeric validation .GreaterThan(0) .GreaterThanOrEqualTo(1) .LessThan(100) .LessThanOrEqualTo(99) .Between(1, 100) .Positive() .NotZero() // Collection validation .NotEmpty() .MinCount(1) .MaxCount(10) .Unique() // Custom validation .Must(value => IsValidBusinessRule(value)) .WithMessage("Custom validation failed") ``` -------------------------------- ### Get Weather Data with Basic HTTP Integration Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Demonstrates basic HTTP integration using FlowRight's extension methods. It shows how to make an asynchronous GET request to a weather API and convert the HttpResponseMessage to a Result of WeatherData. ```csharp using FlowRight.Http.Extensions; public class WeatherService { private readonly HttpClient _httpClient; public async Task> GetWeatherAsync(string city) { HttpResponseMessage response = await _httpClient.GetAsync($"/weather/{city}"); return await response.ToResultFromJsonAsync(); } } ``` -------------------------------- ### FlowRight: Validation Rules Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Provides examples of common validation rules for strings, numbers, and collections, including custom rule creation with messages and conditional execution. ```csharp // String Rules .NotEmpty() .MinimumLength(n) .MaximumLength(n) .EmailAddress() .Url() // Numeric Rules .GreaterThan(n) .LessThan(n) .Between(min, max) .Positive() // Collection Rules .NotEmpty() .MinCount(n) .MaxCount(n) // Custom Rules .Must(predicate) .WithMessage(message) .When(condition) ``` -------------------------------- ### FlowRight: Validation Rules Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Provides examples of common validation rules for strings, numbers, and collections, including custom rule creation with messages and conditional execution. ```csharp // String Rules .NotEmpty() .MinimumLength(n) .MaximumLength(n) .EmailAddress() .Url() // Numeric Rules .GreaterThan(n) .LessThan(n) .Between(min, max) .Positive() // Collection Rules .NotEmpty() .MinCount(n) .MaxCount(n) // Custom Rules .Must(predicate) .WithMessage(message) .When(condition) ``` -------------------------------- ### Install FlowRight Packages using .NET CLI Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/migration-guide.md Installs the necessary FlowRight core, validation, and HTTP packages using the .NET CLI. This is a prerequisite for development and migration. ```bash # Install FlowRight packages dotnet add package FlowRight.Core dotnet add package FlowRight.Validation dotnet add package FlowRight.Http ``` -------------------------------- ### FlowRight: Creating and Managing Results Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Demonstrates how to create success and failure results, check their status, access values or errors, and use pattern matching for handling results. It also shows how to combine multiple results. ```csharp // Creating Results Result.Success(value) Result.Failure(message) Result.NotFound(message) Result.ValidationFailure(message) Result.SecurityFailure(message) // Checking Results result.IsSuccess result.IsFailure result.Value // Only safe when IsSuccess result.Error // Only meaningful when IsFailure result.ResultType // Pattern Matching result.Match(onSuccess, onFailure) result.Switch(onSuccess, onFailure) // Combining Results Result.Combine(result1, result2, result3) ``` -------------------------------- ### Install FlowRight Packages using .NET CLI Source: https://github.com/georgepharrison/flowright/blob/main/MIGRATION.md Installs the necessary FlowRight core, validation, and HTTP packages using the .NET CLI. This is a prerequisite for development and migration. ```bash # Install FlowRight packages dotnet add package FlowRight.Core dotnet add package FlowRight.Validation dotnet add package FlowRight.Http ``` -------------------------------- ### FlowRight: Creating and Managing Results Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Demonstrates how to create success and failure results, check their status, access values or errors, and use pattern matching for handling results. It also shows how to combine multiple results. ```csharp // Creating Results Result.Success(value) Result.Failure(message) Result.NotFound(message) Result.ValidationFailure(message) Result.SecurityFailure(message) // Checking Results result.IsSuccess result.IsFailure result.Value // Only safe when IsSuccess result.Error // Only meaningful when IsFailure result.ResultType // Pattern Matching result.Match(onSuccess, onFailure) result.Switch(onSuccess, onFailure) // Combining Results Result.Combine(result1, result2, result3) ``` -------------------------------- ### Create Success and Failure Results in C# Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Demonstrates how to create generic and non-generic `Result` objects representing success or failure states with optional values or error messages. ```csharp using FlowRight.Core.Results; // Success results Result successResult = Result.Success(42); Result operationResult = Result.Success(); // Failure results Result failureResult = Result.Failure("Something went wrong"); Result operationFailure = Result.Failure("Operation failed"); ``` -------------------------------- ### Pattern Matching with Results in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Illustrates two methods for handling `Result` objects in C#: the functional `Match` approach for transforming results into other values, and the imperative `Switch` approach for performing actions based on the result's success or failure. ```csharp Result userResult = GetUser(userId); string message = userResult.Match( onSuccess: user => $"Welcome back, {user.Name}!", onFailure: error => $"Login failed: {error}" ); Console.WriteLine(message); Result orderResult = CreateOrder(request); orderResult.Switch( onSuccess: order => { Console.WriteLine($"Order {order.Id} created successfully"); SendConfirmationEmail(order); }, onFailure: error => { Console.WriteLine($"Order creation failed: {error}"); LogError(error); } ); ``` -------------------------------- ### Create Success and Failure Results in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Demonstrates how to create generic and non-generic `Result` objects representing success or failure states with optional values or error messages. ```csharp using FlowRight.Core.Results; // Success results Result successResult = Result.Success(42); Result operationResult = Result.Success(); // Failure results Result failureResult = Result.Failure("Something went wrong"); Result operationFailure = Result.Failure("Operation failed"); ``` -------------------------------- ### Pattern Matching with Result Types in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Demonstrates how to handle different outcomes of an operation using the Match method on a Result object. It includes success, not found, security failure, and validation failure scenarios. ```C# Result productResult = GetProduct(productId); string response = productResult.Match( onSuccess: product => $"Product: {product.Name} - ${product.Price}", onFailure: error => productResult.ResultType switch { ResultType.NotFound => "Product not found", ResultType.SecurityFailure => "Access denied", ResultType.ValidationFailure => $"Invalid request: {error}", _ => $"Error: {error}" } ); ``` -------------------------------- ### Create and Handle Basic Results in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Demonstrates how to create success and failure `Result` objects in C# for operations that return a value or don't return a value. Includes checking the status of a result and accessing its value or error message. ```csharp using FlowRight.Core.Results; // Success results Result successResult = Result.Success(42); Result operationResult = Result.Success(); // Failure results Result failureResult = Result.Failure("Something went wrong"); Result operationFailure = Result.Failure("Operation failed"); Result result = GetUserName(userId); if (result.IsSuccess) { string userName = result.Value; // Safe to access Console.WriteLine($"Hello, {userName}!"); } else { string error = result.Error; // Contains error message Console.WriteLine($"Error: {error}"); } public Result DeleteUser(int userId) { try { // Perform deletion logic _userRepository.Delete(userId); return Result.Success(); } catch (UserNotFoundException) { return Result.Failure("User not found"); } catch (Exception ex) { return Result.Failure($"Failed to delete user: {ex.Message}"); } } // Usage Result deleteResult = DeleteUser(123); if (deleteResult.IsFailure) { Console.WriteLine($"Delete failed: {deleteResult.Error}"); } ``` -------------------------------- ### Imperative Result Switching in C# Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Employs the `Switch` method to execute different actions based on the success or failure state of a `Result` object. ```csharp Result orderResult = CreateOrder(request); orderResult.Switch( onSuccess: order => { Console.WriteLine($"Order {order.Id} created successfully"); SendConfirmationEmail(order); }, onFailure: error => { Console.WriteLine($"Order creation failed: {error}"); LogError(error); } ); ``` -------------------------------- ### Advanced Result Type Matching in C# Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Demonstrates advanced pattern matching on `Result` objects, allowing different handling based on specific `ResultType` values in case of failure. ```csharp Result productResult = GetProduct(productId); string response = productResult.Match( onSuccess: product => $"Product: {product.Name} - ${product.Price}", onFailure: error => productResult.ResultType switch { ResultType.NotFound => "Product not found", ResultType.SecurityFailure => "Access denied", ResultType.ValidationFailure => $"Invalid request: {error}", _ => $"Error: {error}" } ); ``` -------------------------------- ### Imperative Result Switching in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Employs the `Switch` method to execute different actions based on the success or failure state of a `Result` object. ```csharp Result orderResult = CreateOrder(request); orderResult.Switch( onSuccess: order => { Console.WriteLine($"Order {order.Id} created successfully"); SendConfirmationEmail(order); }, onFailure: error => { Console.WriteLine($"Order creation failed: {error}"); LogError(error); } ); ``` -------------------------------- ### Advanced Result Type Matching in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Demonstrates advanced pattern matching on `Result` objects, allowing different handling based on specific `ResultType` values in case of failure. ```csharp Result productResult = GetProduct(productId); string response = productResult.Match( onSuccess: product => $"Product: {product.Name} - ${product.Price}", onFailure: error => productResult.ResultType switch { ResultType.NotFound => "Product not found", ResultType.SecurityFailure => "Access denied", ResultType.ValidationFailure => $"Invalid request: {error}", _ => $"Error: {error}" } ); ``` -------------------------------- ### Handle Non-Generic Results in C# Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Illustrates how to return and handle non-generic `Result` objects for operations that do not produce a return value, including error handling. ```csharp public Result DeleteUser(int userId) { try { // Perform deletion logic _userRepository.Delete(userId); return Result.Success(); } catch (UserNotFoundException) { return Result.Failure("User not found"); } catch (Exception ex) { return Result.Failure($"Failed to delete user: {ex.Message}"); } } // Usage Result deleteResult = DeleteUser(123); if (deleteResult.IsFailure) { Console.WriteLine($"Delete failed: {deleteResult.Error}"); } ``` -------------------------------- ### FlowRight Result Type Examples Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/migration-guide.md Shows C# examples of using FlowRight's non-generic, generic, and specialized Result types for various operation outcomes. ```csharp // Non-generic Result for operations that don't return values Result operationResult = Result.Success(); Result errorResult = Result.Failure("Operation failed"); // Generic Result for operations that return values Result userResult = Result.Success(user); Result notFoundResult = Result.NotFound("User with ID 123"); // Specialized failure types Result validationResult = Result.ValidationFailure(errors); Result securityResult = Result.Failure(securityException); Result serverErrorResult = Result.ServerError("Database unavailable"); ``` -------------------------------- ### Use Specific Result Types in C# Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Demonstrates how to use specific result types (Success, NotFound, ValidationFailure) for clearer operation outcomes. Avoids generic failures for specific error conditions. ```csharp public Result GetUser(int id) => _users.ContainsKey(id) ? Result.Success(_users[id]) : Result.NotFound("User not found"); public Result ValidateUser(UserRequest request) => string.IsNullOrEmpty(request.Name) ? Result.ValidationFailure("Name is required") : Result.Success(new User(request.Name)); // Avoid: Generic failures for specific scenarios public Result GetUser(int id) => Result.Failure("Something went wrong"); // Too generic ``` -------------------------------- ### Handling Validation Results with Switch in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Illustrates how to process the outcome of a validation operation using the Switch method. It differentiates between successful user creation and various validation failures. ```C# Result userResult = CreateUser("", "invalid-email", -5); userResult.Switch( onSuccess: user => Console.WriteLine($"User created: {user.Email}"), onFailure: error => Console.WriteLine($"Validation failed: {error}") ); // Output: "Validation failed: Name cannot be empty. Email must be a valid email address. Age must be greater than 0." ``` -------------------------------- ### Handle Non-Generic Results in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Illustrates how to return and handle non-generic `Result` objects for operations that do not produce a return value, including error handling. ```csharp public Result DeleteUser(int userId) { try { // Perform deletion logic _userRepository.Delete(userId); return Result.Success(); } catch (UserNotFoundException) { return Result.Failure("User not found"); } catch (Exception ex) { return Result.Failure($"Failed to delete user: {ex.Message}"); } } // Usage Result deleteResult = DeleteUser(123); if (deleteResult.IsFailure) { Console.WriteLine($"Delete failed: {deleteResult.Error}"); } ``` -------------------------------- ### FlowRight Result Type Examples Source: https://github.com/georgepharrison/flowright/blob/main/MIGRATION.md Shows C# examples of using FlowRight's non-generic, generic, and specialized Result types for various operation outcomes. ```csharp // Non-generic Result for operations that don't return values Result operationResult = Result.Success(); Result errorResult = Result.Failure("Operation failed"); // Generic Result for operations that return values Result userResult = Result.Success(user); Result notFoundResult = Result.NotFound("User with ID 123"); // Specialized failure types Result validationResult = Result.ValidationFailure(errors); Result securityResult = Result.Failure(securityException); Result serverErrorResult = Result.ServerError("Database unavailable"); ``` -------------------------------- ### FlowRight: HTTP Integration Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Shows how to convert HTTP responses into FlowRight results, including mapping common HTTP status codes to specific result types like Success, ValidationFailure, NotFound, SecurityFailure, and Failure. ```csharp // Convert HTTP response to Result await response.ToResultAsync() await response.ToResultFromJsonAsync() // Status code mappings // 2xx → Success // 400 → ValidationFailure // 401/403 → SecurityFailure // 404 → NotFound // 5xx → Failure ``` -------------------------------- ### Functional Result Matching in C# Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Uses the `Match` method to transform a `Result` into another value based on whether it's a success or failure, providing concise handling. ```csharp Result userResult = GetUser(userId); string message = userResult.Match( onSuccess: user => $"Welcome back, {user.Name}!", onFailure: error => $"Login failed: {error}" ); Console.WriteLine(message); ``` -------------------------------- ### Create User with Basic Validation Rules Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Demonstrates creating a User object with validation rules for name, email, and age using FlowRight's ValidationBuilder. Ensures name is not empty and has a specific length, email is valid, and age is within a range. ```csharp using FlowRight.Validation.Builders; public Result CreateUser(string name, string email, int age) { return new ValidationBuilder() .RuleFor(x => x.Name, name) .NotEmpty() .MinimumLength(2) .MaximumLength(50) .RuleFor(x => x.Email, email) .NotEmpty() .EmailAddress() .RuleFor(x => x.Age, age) .GreaterThan(0) .LessThan(120) .Build(() => new User(name, email, age)); } ``` -------------------------------- ### FlowRight: HTTP Integration Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Shows how to convert HTTP responses into FlowRight results, including mapping common HTTP status codes to specific result types like Success, ValidationFailure, NotFound, SecurityFailure, and Failure. ```csharp // Convert HTTP response to Result await response.ToResultAsync() await response.ToResultFromJsonAsync() // Status code mappings // 2xx → Success // 400 → ValidationFailure // 401/403 → SecurityFailure // 404 → NotFound // 5xx → Failure ``` -------------------------------- ### Optimize Memory Allocations in C# with FlowRight Source: https://github.com/georgepharrison/flowright/blob/main/BEST-PRACTICES.md Provides examples of optimizing memory allocations in C# for performance. This includes using pre-allocated common success results and string interning for error messages. ```csharp public static class OptimizedResultFactories { // Pre-allocated common success results private static readonly Result SuccessResult = Result.Success(); private static readonly Result TrueResult = Result.Success(true); private static readonly Result FalseResult = Result.Success(false); public static Result GetCachedSuccess() => SuccessResult; public static Result GetCachedBoolResult(bool value) => value ? TrueResult : FalseResult; // String interning for common error messages private static readonly string RequiredFieldError = string.Intern("This field is required"); private static readonly string InvalidFormatError = string.Intern("Invalid format"); public static Result RequiredFieldFailure() => Result.Failure(RequiredFieldError, ResultFailureType.Validation); } ``` -------------------------------- ### Use Specific Result Types in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Demonstrates how to use specific result types (Success, NotFound, ValidationFailure) for clearer operation outcomes. Avoids generic failures for specific error conditions. ```csharp public Result GetUser(int id) => _users.ContainsKey(id) ? Result.Success(_users[id]) : Result.NotFound("User not found"); public Result ValidateUser(UserRequest request) => string.IsNullOrEmpty(request.Name) ? Result.ValidationFailure("Name is required") : Result.Success(new User(request.Name)); // Avoid: Generic failures for specific scenarios public Result GetUser(int id) => Result.Failure("Something went wrong"); // Too generic ``` -------------------------------- ### Functional Result Matching in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Uses the `Match` method to transform a `Result` into another value based on whether it's a success or failure, providing concise handling. ```csharp Result userResult = GetUser(userId); string message = userResult.Match( onSuccess: user => $"Welcome back, {user.Name}!", onFailure: error => $"Login failed: {error}" ); Console.WriteLine(message); ``` -------------------------------- ### Create Order with Complex Validation Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Illustrates complex validation scenarios for an Order object, including rules for customer email, number of items, total amount, and conditional shipping address validation. It uses a ValidationBuilder to define these rules. ```csharp public Result CreateOrder(OrderRequest request) { return new ValidationBuilder() .RuleFor(x => x.CustomerEmail, request.CustomerEmail) .NotEmpty() .EmailAddress() .RuleFor(x => x.Items, request.Items) .NotEmpty() .Must(items => items.Count <= 100) .WithMessage("Orders cannot contain more than 100 items") .RuleFor(x => x.TotalAmount, request.TotalAmount) .GreaterThan(0) .LessThan(10000) .RuleFor(x => x.ShippingAddress, request.ShippingAddress) .NotEmpty() .When(request => request.RequiresShipping) .Build(() => new Order(request)); } ``` -------------------------------- ### C# FlowRight Essential Validation Rules Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Outlines essential validation rules provided by FlowRight for strings, numerics, and collections. It also covers custom validation using predicates and message customization with conditional execution. ```C# // String Rules .NotEmpty() .MinimumLength(n) .MaximumLength(n) .EmailAddress() .Url() // Numeric Rules .GreaterThan(n) .LessThan(n) .Between(min, max) .Positive() // Collection Rules .NotEmpty() .MinCount(n) .MaxCount(n) // Custom Rules .Must(predicate) .WithMessage(message) .When(condition) ``` -------------------------------- ### Create Order with Complex Validation Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Illustrates complex validation scenarios for an Order object, including rules for customer email, number of items, total amount, and conditional shipping address validation. It uses a ValidationBuilder to define these rules. ```csharp public Result CreateOrder(OrderRequest request) { return new ValidationBuilder() .RuleFor(x => x.CustomerEmail, request.CustomerEmail) .NotEmpty() .EmailAddress() .RuleFor(x => x.Items, request.Items) .NotEmpty() .Must(items => items.Count <= 100) .WithMessage("Orders cannot contain more than 100 items") .RuleFor(x => x.TotalAmount, request.TotalAmount) .GreaterThan(0) .LessThan(10000) .RuleFor(x => x.ShippingAddress, request.ShippingAddress) .NotEmpty() .When(request => request.RequiresShipping) .Build(() => new Order(request)); } ``` -------------------------------- ### Handle Validation Results Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Shows how to handle the Result of a validation operation. It uses the Switch method to execute different actions based on whether the validation succeeded or failed, printing the user's email on success or the error message on failure. ```csharp Result userResult = CreateUser("", "invalid-email", -5); userResult.Switch( onSuccess: user => Console.WriteLine($"User created: {user.Email}"), onFailure: error => Console.WriteLine($"Validation failed: {error}") ); // Output: "Validation failed: Name cannot be empty. Email must be a valid email address. Age must be greater than 0." ``` -------------------------------- ### GuidNotEmptyRule Validation Examples (C#) Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/api/FlowRight.Validation.Rules.GuidNotEmptyRule.html Demonstrates the usage of the GuidNotEmptyRule for validating GUID values. Shows examples for valid non-empty GUIDs, the empty GUID, and null GUIDs. ```csharp // Valid non-empty GUID rule.Validate(Guid.NewGuid(), "ID") // Returns null (valid) // Invalid empty GUID rule.Validate(Guid.Empty, "ID") // Returns "ID cannot be empty" // Null GUID rule.Validate(null, "ID") // Returns "ID cannot be empty" ``` -------------------------------- ### FlowRight Built-in Validation Rules in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html Provides examples of various built-in validation rules available in FlowRight for strings, numbers, and collections, including custom validation logic. ```C# // String validation .NotEmpty() .MinimumLength(5) .MaximumLength(100) .Length(10, 20) .Matches(@"^\d{3}-\d{2}-\d{4}$") .EmailAddress() .Url() .AlphaNumeric() // Numeric validation .GreaterThan(0) .GreaterThanOrEqualTo(1) .LessThan(100) .LessThanOrEqualTo(99) .Between(1, 100) .Positive() .NotZero() // Collection validation .NotEmpty() .MinCount(1) .MaxCount(10) .Unique() // Custom validation .Must(value => IsValidBusinessRule(value)) .WithMessage("Custom validation failed") ``` -------------------------------- ### Chain Operations with Result Pattern in C# Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Illustrates chaining operations using the Result pattern's `Match` method. This allows for sequential execution where each step depends on the success of the previous one, providing a clean way to handle success and failure at each stage. ```csharp public Result ProcessUserData(int userId) { return GetUser(userId) .Match( onSuccess: user => ValidateUser(user) .Match( onSuccess: validUser => FormatUserData(validUser), onFailure: error => Result.Failure(error) ), onFailure: error => Result.Failure(error) ); } ``` -------------------------------- ### API Controller Action Patterns in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/best-practices.html Presents a standard pattern for ASP.NET Core API controllers, demonstrating how to handle various `Result` types from service calls and return appropriate HTTP responses. Includes examples for POST and GET actions. ```csharp [ApiController] [Route("api/[controller]")] public class UsersController : ControllerBase { private readonly IUserService _userService; public UsersController(IUserService userService) => _userService = userService; [HttpPost] public async Task CreateUserAsync(CreateUserRequest request) { Result result = await _userService.CreateUserAsync(request); return result.Match( onSuccess: user => CreatedAtAction(nameof(GetUser), new { id = user.Id }, new UserResponse(user)), onError: error => Problem(detail: error, statusCode: 500), onSecurityException: error => Problem(detail: "Access denied", statusCode: 403), onValidationException: errors => ValidationProblem(errors.ToDictionary( kvp => kvp.Key, kvp => kvp.Value)), onOperationCanceledException: error => Problem(detail: "Request cancelled", statusCode: 408) ); } [HttpGet("{id}")] public async Task GetUserAsync(int id) { Result result = await _userService.GetUserAsync(id); return result.Match( onSuccess: user => Ok(new UserResponse(user)), onFailure: error => result.FailureType switch { ResultFailureType.NotFound => NotFound(error), ResultFailureType.Security => Forbid(error), _ => Problem(detail: error) } ); } } ``` -------------------------------- ### Work with ASP.NET Core Problem Details Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Illustrates how FlowRight automatically parses ASP.NET Core Problem Details responses. It shows an example where validation errors from a Problem Details JSON are extracted and included in the Result's error message. ```csharp // Server returns: {"type": "validation", "errors": {"Name": ["Required"], "Email": ["Invalid format"]}} Result result = await response.ToResultFromJsonAsync(); if (result.IsFailure && result.ResultType == ResultType.ValidationFailure) { // Parsed validation errors are included in the error message Console.WriteLine(result.Error); // Output: "Name is required. Email must be in a valid format." ``` -------------------------------- ### Build and Serve FlowRight Docs (Linux/macOS) Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/README.html Bash script to build and serve the FlowRight API documentation. Includes commands for building and serving locally. ```bash # Build and generate documentation ./build-docs.sh # Serve locally after generation docfx serve docs/_site ``` -------------------------------- ### Work with ASP.NET Core Problem Details in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/getting-started.html This C# example shows how FlowRight automatically parses ASP.NET Core Problem Details, specifically for validation errors. It illustrates how to check the ResultType for ValidationFailure and access the detailed error messages, which are often aggregated into a user-friendly string. ```C# // Server returns: {"type": "validation", "errors": {"Name": ["Required"], "Email": ["Invalid format"]}} Result result = await response.ToResultFromJsonAsync(); if (result.IsFailure && result.ResultType == ResultType.ValidationFailure) { // Parsed validation errors are included in the error message Console.WriteLine(result.Error); // Output: "Name is required. Email must be in a valid format." ``` -------------------------------- ### Work with ASP.NET Core Problem Details Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Illustrates how FlowRight automatically parses ASP.NET Core Problem Details responses. It shows an example where validation errors from a Problem Details JSON are extracted and included in the Result's error message. ```csharp // Server returns: {"type": "validation", "errors": {"Name": ["Required"], "Email": ["Invalid format"]}} Result result = await response.ToResultFromJsonAsync(); if (result.IsFailure && result.ResultType == ResultType.ValidationFailure) { // Parsed validation errors are included in the error message Console.WriteLine(result.Error); // Output: "Name is required. Email must be in a valid format." ``` -------------------------------- ### C# GUID Validation Example Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/api/FlowRight.Validation.Rules.NotEmptyRule-1.html Illustrates the usage of NotEmptyRule for validating GUID values in C#. It covers scenarios with an empty GUID and a newly generated, valid GUID. ```csharp // GUID validation rule.Validate(Guid.Empty, "ID") // Returns "ID must not be empty" rule.Validate(Guid.NewGuid(), "ID") // Returns null (valid) ``` -------------------------------- ### Clean and Build Project with DocFX Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/README.html Cleans the project, builds it in Release configuration, and then runs DocFX to generate documentation, forcing a rebuild. ```bash dotnet clean && dotnet build --configuration Release cd docs && docfx --force ``` -------------------------------- ### Create User with Basic Validation Rules Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Demonstrates creating a User object with validation rules for name, email, and age using FlowRight's ValidationBuilder. Ensures name is not empty and has a specific length, email is valid, and age is within a range. ```csharp using FlowRight.Validation.Builders; public Result CreateUser(string name, string email, int age) { return new ValidationBuilder() .RuleFor(x => x.Name, name) .NotEmpty() .MinimumLength(2) .MaximumLength(50) .RuleFor(x => x.Email, email) .NotEmpty() .EmailAddress() .RuleFor(x => x.Age, age) .GreaterThan(0) .LessThan(120) .Build(() => new User(name, email, age)); } ``` -------------------------------- ### Validation Example in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/api/index.html Provides an example of fluent validation using FlowRight.Validation. It demonstrates building validation rules for properties like Email and Age, and then executing the validation to get a Result. ```C# using FlowRight.Validation.Builders; // Build fluent validation ValidationBuilder validator = new ValidationBuilder() .RuleFor(x => x.Email, user.Email) .NotEmpty() .Email() .RuleFor(x => x.Age, user.Age) .GreaterThan(0) .LessThan(150); // Validate and get result Result result = validator.Build(() => user); ``` -------------------------------- ### GuidNonZeroTimestampRule Validation Example (C#) Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/api/FlowRight.Validation.Rules.GuidNonZeroTimestampRule.html This C# code demonstrates the usage of the GuidNonZeroTimestampRule. It shows how to validate a GUID, including valid, invalid (epoch time), and null GUIDs, and the expected return values (null for valid, error message for invalid). ```csharp // Valid GUID with non-zero timestamp rule.Validate(Guid.NewGuid(), "ID") // Returns null (valid) // Invalid GUID with all-zero timestamp (very unlikely in practice) rule.Validate(someEpochGuid, "ID") // Returns "ID must have a valid timestamp component" // Null GUID rule.Validate(null, "ID") // Returns "ID must have a valid timestamp component" ``` -------------------------------- ### Chain Operations with Result Pattern in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Illustrates chaining operations using the Result pattern's `Match` method. This allows for sequential execution where each step depends on the success of the previous one, providing a clean way to handle success and failure at each stage. ```csharp public Result ProcessUserData(int userId) { return GetUser(userId) .Match( onSuccess: user => ValidateUser(user) .Match( onSuccess: validUser => FormatUserData(validUser), onFailure: error => Result.Failure(error) ), onFailure: error => Result.Failure(error) ); } ``` -------------------------------- ### C#: FlowRight Result Pattern Type Examples Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/articles/migration-guide.html Shows examples of using different FlowRight Result types in C#. This includes non-generic Results for operations without return values and generic Results for operations with return values, along with specialized failure types. ```csharp // Non-generic Result for operations that don't return values Result operationResult = Result.Success(); Result errorResult = Result.Failure("Operation failed"); // Generic Result for operations that return values Result userResult = Result.Success(user); Result notFoundResult = Result.NotFound("User with ID 123"); // Specialized failure types Result validationResult = Result.ValidationFailure(errors); Result securityResult = Result.Failure(securityException); Result serverErrorResult = Result.ServerError("Database unavailable"); ``` -------------------------------- ### Check Result Status in C# Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/getting-started.md Shows how to check if a `Result` object represents a success or failure and access its `Value` or `Error` properties accordingly. ```csharp Result result = GetUserName(userId); if (result.IsSuccess) { string userName = result.Value; // Safe to access Console.WriteLine($"Hello, {userName}!"); } else { string error = result.Error; // Contains error message Console.WriteLine($"Error: {error}"); } ``` -------------------------------- ### Manual FlowRight Documentation Build Source: https://github.com/georgepharrison/flowright/blob/main/docs/_site/README.html Steps to manually build the FlowRight documentation using DocFX, including installing DocFX, building the solution, and generating documentation. ```bash # 1. Install DocFX (if not already installed) dotnet tool install -g docfx # 2. Build the solution to generate XML documentation cd .. && dotnet build FlowRight.sln --configuration Release # 3. Generate documentation cd docs && docfx # 4. Serve locally (optional) docfx serve _site ``` -------------------------------- ### C# XML Documentation Example Source: https://github.com/georgepharrison/flowright/blob/main/CLAUDE.md Provides a comprehensive example of XML documentation for a C# method. It includes summary, type parameters, parameters, return values, and an inline code example, adhering to standard documentation practices. ```C# /// /// Creates a success result with the specified value. /// /// The type of the success value. /// The success value. /// A success result containing the value. /// /// /// Result result = Result.Success(42); /// /// public static Result Success(T value) ``` -------------------------------- ### Check Result Status in C# Source: https://github.com/georgepharrison/flowright/blob/main/GETTING-STARTED.md Shows how to check if a `Result` object represents a success or failure and access its `Value` or `Error` properties accordingly. ```csharp Result result = GetUserName(userId); if (result.IsSuccess) { string userName = result.Value; // Safe to access Console.WriteLine($"Hello, {userName}!"); } else { string error = result.Error; // Contains error message Console.WriteLine($"Error: {error}"); } ``` -------------------------------- ### Build and Serve FlowRight Docs (Linux/macOS) Source: https://github.com/georgepharrison/flowright/blob/main/docs/README.md Commands to build and generate FlowRight API documentation on Linux or macOS using Bash. Includes options to build and serve the documentation locally. ```Bash # Build and generate documentation ./build-docs.sh # Serve locally after generation docfx serve docs/_site ``` -------------------------------- ### Optimize Memory Allocations in C# with FlowRight Source: https://github.com/georgepharrison/flowright/blob/main/docs/articles/best-practices.md Provides examples of optimizing memory allocations in C# for performance. This includes using pre-allocated common success results and string interning for error messages. ```csharp public static class OptimizedResultFactories { // Pre-allocated common success results private static readonly Result SuccessResult = Result.Success(); private static readonly Result TrueResult = Result.Success(true); private static readonly Result FalseResult = Result.Success(false); public static Result GetCachedSuccess() => SuccessResult; public static Result GetCachedBoolResult(bool value) => value ? TrueResult : FalseResult; // String interning for common error messages private static readonly string RequiredFieldError = string.Intern("This field is required"); private static readonly string InvalidFormatError = string.Intern("Invalid format"); public static Result RequiredFieldFailure() => Result.Failure(RequiredFieldError, ResultFailureType.Validation); } ```