diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index e697c35..1b4bdbe 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -11,7 +11,7 @@ jobs: test-versions: strategy: matrix: - csharpFunctionalExtensionsVersion: [ '2.29.0', '2.*', '3.0.0', '3.*' ] + csharpFunctionalExtensionsVersion: ["2.29.0", "2.*", "3.0.0", "3.*"] fail-fast: false uses: ./.github/workflows/test-version.yml with: @@ -46,3 +46,12 @@ jobs: - name: Lint run: dotnet csharpier --check . + + - name: Link Checker + id: lychee + uses: lycheeverse/lychee-action@v2 + with: + fail: true + args: --remap '${{ github.event.repository.default_branch }} ${{ github.head_ref }}' --include-fragments . + jobSummary: true + format: markdown diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/AddBook/AddBookEndpoint.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/AddBook/AddBookEndpoint.cs similarity index 96% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/AddBook/AddBookEndpoint.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/AddBook/AddBookEndpoint.cs index f6db45d..f01ecb5 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/AddBook/AddBookEndpoint.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/AddBook/AddBookEndpoint.cs @@ -1,9 +1,9 @@ -using CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.FindBook; +using CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.FindBook; using CSharpFunctionalExtensions.HttpResults.ResultExtensions; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.AddBook; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.AddBook; public static class AddBookEndpoint { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/AddBook/AddBookRequest.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/AddBook/AddBookRequest.cs similarity index 86% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/AddBook/AddBookRequest.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/AddBook/AddBookRequest.cs index 19b27b5..bbcf7c2 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/AddBook/AddBookRequest.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/AddBook/AddBookRequest.cs @@ -1,3 +1,3 @@ -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.AddBook; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.AddBook; public record AddBookRequest(string Title, string Author, byte[]? Cover); diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/Book.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/Book.cs similarity index 98% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/Book.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/Book.cs index a0399fe..fda6314 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/Book.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/Book.cs @@ -1,4 +1,4 @@ -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD; public class Book { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/BookService.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/BookService.cs similarity index 98% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/BookService.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/BookService.cs index f5537fa..9e3ecb9 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/BookService.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/BookService.cs @@ -1,4 +1,4 @@ -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD; public class BookService { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/BooksGroup.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/BooksGroup.cs similarity index 54% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/BooksGroup.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/BooksGroup.cs index a0441a9..8d526de 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/BooksGroup.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/BooksGroup.cs @@ -1,11 +1,11 @@ -using CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.AddBook; -using CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.DeleteBook; -using CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.FindBook; -using CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.FindBookCover; -using CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.GetBooks; -using CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.UpdateBook; +using CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.AddBook; +using CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.DeleteBook; +using CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.FindBook; +using CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.FindBookCover; +using CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.GetBooks; +using CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.UpdateBook; -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD; public static class BooksGroup { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/DeleteBook/DeleteBookEndpoint.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/DeleteBook/DeleteBookEndpoint.cs similarity index 96% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/DeleteBook/DeleteBookEndpoint.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/DeleteBook/DeleteBookEndpoint.cs index 978a4db..c1e2620 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/DeleteBook/DeleteBookEndpoint.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/DeleteBook/DeleteBookEndpoint.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.DeleteBook; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.DeleteBook; public static class DeleteBookEndpoint { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/FakeBooks.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/FakeBooks.cs similarity index 98% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/FakeBooks.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/FakeBooks.cs index ee8b5cf..0dbb2ad 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/FakeBooks.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/FakeBooks.cs @@ -2,7 +2,7 @@ using System.Web; using Bogus; -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD; public static class FakeBooks { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/FindBook/FindBookEndpoint.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/FindBook/FindBookEndpoint.cs similarity index 97% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/FindBook/FindBookEndpoint.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/FindBook/FindBookEndpoint.cs index 4f9e765..90f66b2 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/FindBook/FindBookEndpoint.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/FindBook/FindBookEndpoint.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.FindBook; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.FindBook; public static class FindBookEndpoint { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/FindBookCover/FindBookCoverEndpoint.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/FindBookCover/FindBookCoverEndpoint.cs similarity index 97% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/FindBookCover/FindBookCoverEndpoint.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/FindBookCover/FindBookCoverEndpoint.cs index ed8c662..81b3fd5 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/FindBookCover/FindBookCoverEndpoint.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/FindBookCover/FindBookCoverEndpoint.cs @@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.FindBookCover; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.FindBookCover; public static class FindBookCoverEndpoint { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/GetBooks/GetBooksEndpoint.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/GetBooks/GetBooksEndpoint.cs similarity index 97% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/GetBooks/GetBooksEndpoint.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/GetBooks/GetBooksEndpoint.cs index 1a33483..ba681a1 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/GetBooks/GetBooksEndpoint.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/GetBooks/GetBooksEndpoint.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.GetBooks; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.GetBooks; public static class GetBooksEndpoint { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/UpdateBook/UpdateBookEndpoint.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/UpdateBook/UpdateBookEndpoint.cs similarity index 97% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/UpdateBook/UpdateBookEndpoint.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/UpdateBook/UpdateBookEndpoint.cs index f98f076..98ad654 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/UpdateBook/UpdateBookEndpoint.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/UpdateBook/UpdateBookEndpoint.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.UpdateBook; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.UpdateBook; public static class UpdateBookEndpoint { diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/UpdateBook/UpdateBookRequest.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/UpdateBook/UpdateBookRequest.cs similarity index 85% rename from CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/UpdateBook/UpdateBookRequest.cs rename to CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/UpdateBook/UpdateBookRequest.cs index d3a420f..f5652fa 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/Books/UpdateBook/UpdateBookRequest.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD/UpdateBook/UpdateBookRequest.cs @@ -1,3 +1,3 @@ -namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.Books.UpdateBook; +namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD.UpdateBook; public record UpdateBookRequest(string Title, string Author, byte[]? Cover); diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Features/MultipleErrorChain/MultipleErrorChain.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Features/MultipleErrorChain/MultipleErrorChain.cs index 0a5158b..8459553 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Features/MultipleErrorChain/MultipleErrorChain.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Features/MultipleErrorChain/MultipleErrorChain.cs @@ -1,8 +1,14 @@ -using CSharpFunctionalExtensions.HttpResults.Examples.Features.Books; +using CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD; using Microsoft.AspNetCore.Http.HttpResults; namespace CSharpFunctionalExtensions.HttpResults.Examples.Features.MultipleErrorChain; +/// +/// Because C# does not natively support union types there is no optimal solution to handle different +/// types of errors in a chain of . +/// This is the best workaround I could find for now. +/// + // 1. Create base type for all errors and define concrete errors as child type public record BookError; diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/Program.cs b/CSharpFunctionalExtensions.HttpResults.Examples/Program.cs index e21ea6d..f993264 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/Program.cs +++ b/CSharpFunctionalExtensions.HttpResults.Examples/Program.cs @@ -1,5 +1,5 @@ using CSharpFunctionalExtensions.HttpResults; -using CSharpFunctionalExtensions.HttpResults.Examples.Features.Books; +using CSharpFunctionalExtensions.HttpResults.Examples.Features.CRUD; using CSharpFunctionalExtensions.HttpResults.Examples.Features.CustomError; using CSharpFunctionalExtensions.HttpResults.Examples.Features.FileStream; using Scalar.AspNetCore; diff --git a/CSharpFunctionalExtensions.HttpResults.Examples/README.md b/CSharpFunctionalExtensions.HttpResults.Examples/README.md index 220ea99..b723307 100644 --- a/CSharpFunctionalExtensions.HttpResults.Examples/README.md +++ b/CSharpFunctionalExtensions.HttpResults.Examples/README.md @@ -6,11 +6,11 @@ This project contains a WebApi to showcase several features of `CSharpFunctional ### CRUD -CRUD operations of an Book store are available under [`Features/Books`](./Features/Books). +CRUD operations of an Book store are available under [`Features/CRUD`](./Features/CRUD). ### Files -An example for a `FileContentResult` is available under [`Features/Books/FindBookCover/FindBookCoverEndpoint.cs`](./Features/Books/FindBookCover/FindBookCoverEndpoint.cs). +An example for a `FileContentResult` is available under [`Features/CRUD/FindBookCover/FindBookCoverEndpoint.cs`](./Features/CRUD/FindBookCover/FindBookCoverEndpoint.cs). ### Streams diff --git a/CSharpFunctionalExtensions.HttpResults/CSharpFunctionalExtensions.HttpResults.csproj b/CSharpFunctionalExtensions.HttpResults/CSharpFunctionalExtensions.HttpResults.csproj index 19b6e45..ebfbd69 100644 --- a/CSharpFunctionalExtensions.HttpResults/CSharpFunctionalExtensions.HttpResults.csproj +++ b/CSharpFunctionalExtensions.HttpResults/CSharpFunctionalExtensions.HttpResults.csproj @@ -15,7 +15,7 @@ CSharpFunctionalExtensions.HttpResults co-IT, Stimmler - Extensions for CSharpFunctionalExtensions to map Results to HttpResults in your Web-API + Seamlessly map Results from CSharpFunctionalExtensions to HttpResults for cleaner, more fluent Web APIs Copyright (c) co-IT.eu GmbH 2025 README.md https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults diff --git a/README.md b/README.md index 66a3858..1d06895 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,38 @@ [![nuget downloads](https://img.shields.io/nuget/dt/CSharpFunctionalExtensions.HttpResults)](https://www.nuget.org/packages/CSharpFunctionalExtensions.HttpResults/) [![GitHub license](https://img.shields.io/github/license/co-IT/CSharpFunctionalExtensions.HttpResults)](https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults/blob/main/LICENSE.md) -Extensions for [CSharpFunctionalExtensions](https://github.com/vkhorikov/CSharpFunctionalExtensions) to map Results to -HttpResults in your Web-API +Seamlessly map Results from [CSharpFunctionalExtensions](https://github.com/vkhorikov/CSharpFunctionalExtensions) to HttpResults for cleaner, more fluent Web APIs + +
+Table of Contents + +1. [Overview](#overview) +2. [Installation](#installation) +3. [Usage](#usage) + 1. [Available methods](#available-methods) + 2. [Default mapping](#default-mapping) + 3. [Custom error mapping](#custom-error-mapping) +4. [Analyzers](#analyzers) +5. [Examples](#examples) +6. [Development](#development) +
## Overview -This library streamlines returning HttpResults from endpoints that leverage [CSharpFunctionalExtensions](https://github.com/vkhorikov/CSharpFunctionalExtensions) by offering convenient extension methods to map you result to an HttpResult. -With these, you can maintain a fluent, railway-oriented style by simply invoking the appropriate method at the end of your result chain. -It also supports custom error types and ensures a clear separation between your domain logic and API by using specific mappers to translate domain details into API responses. +This library provides convenient extension methods to seamlessly map Results from [CSharpFunctionalExtensions](https://github.com/vkhorikov/CSharpFunctionalExtensions) to HttpResults. With this, it streamlines your Web API resulting in cleaner, more fluent code. + +### Key Benefits + +- ⚙️ **Zero Configuration:** Get started immediately — the mapping works out of the box without any configuration. +- 🛠️ **Customizable Mappings:** Tailor default mappings or define custom mappings for specific use cases. +- 🔗 **Fluent API:** Maintain a smooth, railway-oriented flow by chaining HttpResult mappings at the end of your Result chain. +- 🧱 **Separation of Domain and HTTP Errors:** Keeps domain errors distinct from HTTP errors, improving maintainability and clarity between business logic and web API concerns. +- ⚡ **Minimal APIs & Controllers Support:** Works with both Minimal APIs and traditional controllers in ASP.NET. +- 📦 **Full Support for ASP.NET Results:** Supports all built-in HTTP response types in ASP.NET, including `Ok`, `Created`, `NoContent`, `Accepted`, `FileStream`, and more. +- 🦺 **Typed Results:** Utilizes `TypedResults` for consistent, type-safe API responses. +- 📑 **OpenAPI Ready:** Ensures accurate OpenAPI generation for clear and reliable API documentation. +- 🛡️ **RFC Compliance:** Default mappings adhere to the RFC 9457 standard (`ProblemDetails`), ensuring your API errors are standardized and interoperable. +- 🧑‍💻 **Developer-Friendly:** Includes built-in analyzers and source generators to speed up development and reduce errors. ## Installation @@ -28,13 +52,13 @@ or PM> Install-Package CSharpFunctionalExtensions.HttpResults ``` -> [!TIP] -> This library references a fairly old version of CSharpFunctionalExtensions for compatibility reasons. -> It's recommended to also install the latest version of CSharpFunctionalExtensions in your project to get the latest features and fixes. +> [!NOTE] +> This library references an older version of CSharpFunctionalExtensions for wider compatibility. +> It's recommended to additionally install the latest version of CSharpFunctionalExtensions in your project to get the latest features and fixes. ## Usage -This library provides you extension methods to map the following `Result` types to `HttpResults`: +This library provides you extension methods to map the following `Result` types to `HttpResults` at the end of our result chain: - `Result` - `Result` @@ -49,7 +73,10 @@ app.MapGet("/books", (BookService service) => ); ``` -These methods are available: +### Available methods + +
+ Click here to view all available methods. | Method | Short Description | |---------------------------------------|------------------------------------------------------------------------------| @@ -79,12 +106,13 @@ These methods are available: | `.ToFileStreamHttpResult()` | Returns `FileStreamHttpResult` or custom error | | `.ToContentHttpResult()` | Returns `ContentHttpResult` or `ProblemHttpResult` | | `.ToContentHttpResult()` | Returns `ContentHttpResult` or custom error | +
All methods are available in sync and async variants. ### Default mapping -By default, `Result` and `Result` failures get mapped to a `ProblemHttpResult` based on [RFC9457](https://www.rfc-editor.org/rfc/rfc9457). +By default, `Result` and `Result` failures are mapped to a `ProblemHttpResult` based on [RFC9457](https://www.rfc-editor.org/rfc/rfc9457). - The `status` property contains the status code of the HTTP response. Note: For almost every method you can override the default status codes for Success/Failure case. - The `type` property contains a URI to the corresponding [RFC9110](https://tools.ietf.org/html/rfc9110) entry based on the status code. @@ -95,10 +123,10 @@ This default mapping behaviour is configured inside the [`ProblemDetailsMappingP #### Override default mapping -You can override this behaviour by providing your own dictionary which maps status code to title and type of the resulting `ProblemDetails` object. +You can override this behavior by providing your own dictionary that maps status codes to their corresponding `title` and `type` of the resulting `ProblemDetails` object.
-Example for changing the default mapping for german localization +Click here to see an example of changing the default mapping for German localization. ```csharp ProblemDetailsMappingProvider.DefaultMappings = new Dictionary @@ -126,7 +154,7 @@ ProblemDetailsMappingProvider.DefaultMappings = new Dictionary -You don't have to provide the whole dictionary but can also override or add only mappings for specific status codes like this: +You don't have to provide the whole dictionary; you can also override or add mappings for specific status codes like this: ```csharp ProblemDetailsMappingProvider.AddOrUpdateMapping(420, "Enhance Your Calm", "https://http-status-code.de/420/"); @@ -136,7 +164,7 @@ It's recommended to override the mappings during startup e.g. in `Program.cs`. #### Override mapping for single use case -If you need to override the mapping for a specific use case in a single location, you can provide an `Action` to fully customize the ProblemDetails. This is particularly useful when you want to add extensions or tailor the `ProblemDetails` specifically for that use case. +If you need to override the mapping for a specific use case in a single location, you can provide an `Action` to fully customize the `ProblemDetails`. This is particularly useful when you want to add extensions or tailor the `ProblemDetails` specifically for that use case. ```csharp ... @@ -155,7 +183,7 @@ When using `Result` or `UnitResult`, this library uses a Source Generato ```csharp public record UserNotFoundError(string UserId); ``` -2. Create a mapper that implements `IResultErrorMapper` which maps this custom error type to an HttpResult / `IResult` that you want to return in your Web-API: +2. Create a mapper that implements `IResultErrorMapper` which maps this custom error type to an HttpResult / `Microsoft.AspNetCore.Http.IResult` that you want to return in your Web API: ```csharp public class UserNotFoundErrorMapper : IResultErrorMapper { @@ -175,35 +203,44 @@ When using `Result` or `UnitResult`, this library uses a Source Generato ``` 3. Use the auto generated extension method: ```csharp - app.MapGet("/users/{id}", (string id) => { - return userRepository.Find(id) //Result - .ToOkHttpResult(); //Results,ProblemHttpResult> - }); + app.MapGet("/users/{id}", (string id, UserRepository repo) => + repo.Find(id) //Result + .ToOkHttpResult() //Results,ProblemHttpResult> + ); ``` > [!IMPORTANT] -> Make sure that every custom error type has exactly one corresponding `IResultMapper` implementation. - -You can use the `ProblemDetailsMappingProvider.FindMapping()` method to find a suitable title and type for a status code based on [RFC9110](https://tools.ietf.org/html/rfc9110). +> Make sure that each custom error type has exactly one corresponding `IResultMapper` implementation. > [!TIP] +> You can use the `ProblemDetailsMappingProvider.FindMapping()` method to find a suitable title and type for a status code based on [RFC9110](https://tools.ietf.org/html/rfc9110). + +> [!NOTE] > If extension methods for custom errors are missing, rebuild the project to trigger Source Generation. ## Analyzers This library includes analyzers to help you use it correctly. -For example, they can notify you if you have multiple mappers for the same custom error type. +For example, they will notify you if you have multiple mappers for the same custom error type. You can find a complete list of all analyzers [here](https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults/blob/main/CSharpFunctionalExtensions.HttpResults.Generators/AnalyzerReleases.Shipped.md). ## Examples -Examples for CRUD, FileStreams, custom errors, etc. in context of a Web-API are available in the [`CSharpFunctionalExtensions.HttpResults.Examples`](CSharpFunctionalExtensions.HttpResults.Examples) project. +The [`CSharpFunctionalExtensions.HttpResults.Examples`](https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults/blob/main/CSharpFunctionalExtensions.HttpResults.Examples) project contains various examples demonstrating how to use this library in different scenarios, including: + +- **[Basic CRUD operations](https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults/blob/main/CSharpFunctionalExtensions.HttpResults.Examples/Features/CRUD)** – Handling `GET`, `POST`, `PUT`, and `DELETE` requests +- **[File handling](https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults/blob/main/CSharpFunctionalExtensions.HttpResults.Examples/Features/FileStream)** – Returning files from your Web API +- **[Custom error mapping](https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults/blob/main/CSharpFunctionalExtensions.HttpResults.Examples/Features/CustomError)** – Defining and mapping custom error types to meaningful HTTP responses +- **[Multiple errors in chain](https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults/blob/main/CSharpFunctionalExtensions.HttpResults.Examples/Features/MultipleErrorChain)** – Using different kind of custom errors in the same result chain +- **[Customizing default mapping](https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults/blob/main/CSharpFunctionalExtensions.HttpResults.Examples/Program.cs)** – Overriding default mappings for localization or specific use cases + +Check out the example project for hands-on implementation details! ## Development -You're welcome to contribute. Please keep these few rules in mind: +Contributions are welcome! Please keep the following rules in mind: - add documentation in the form of summary comments - add tests for your additions @@ -220,4 +257,4 @@ To add new methods follow these steps: 2. Add methods for `Result` to `CSharpFunctionalExtensions.HttpResults.Generators.ResultExtensions` and add the class to `ResultExtensionsClassBuilder` 3. Add methods for `UnitResult` to `CSharpFunctionalExtensions.HttpResults.Generators.UnitResultExtensions` and add the class to `UnitResultExtensionsClassBuilder` 4. Add tests for **all** new methods to `CSharpFunctionalExtensions.HttpResults.Tests` -5. Add methods to [README](README.md) +5. Add methods to [README](https://github.com/co-IT/CSharpFunctionalExtensions.HttpResults/blob/main/README.md)