Skip to content

Commit ee9b83e

Browse files
committed
readme
1 parent 2b92095 commit ee9b83e

File tree

2 files changed

+100
-47
lines changed

2 files changed

+100
-47
lines changed

README.md

+8-9
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@ Danom is a C# library that provides (monadic) structures to facilitate durable p
88

99
- Implementation of common monads: [Option](#option) and [Result](#result).
1010
- Exhaustive matching to prevent null reference exceptions.
11-
- Fluent API for chaining operations.
11+
- Fluent API for chaining operations, including async support.
1212
- Integrated with [ASP.NET Core](#aspnet-core-mvc-integration) and [Fluent Validation](#fluent-validation-integration).
1313
- API for [parsing strings](#string-parsing) into .NET primitives and value types.
14-
- Supports asynchronous operations.
1514

1615
## Design Goals
1716

18-
- Easy to use API for common monadic operations.
19-
- Efficient implementation to minimize overhead.
20-
- Seamless integration with existing C# code and libraries.
17+
- Provide a safe and expressive way to handle nullable values.
2118
- Prevent direct use of internal value, enforcing exhaustive matching.
19+
- Efficient implementation to minimize overhead.
20+
- Opionated monads to encourage consistent use.
2221

2322
## Getting Started
2423

@@ -200,6 +199,8 @@ Result<int, string> resultOrElseWith =
200199
Result<int, string>.Ok(99)); // useful if creating the value is expensive
201200
```
202201

202+
### Result Errors
203+
203204
Since error messages are frequently represented as keyed string collections, the `ResultErrors` type is provided to simplify Result creation. The flexible constructor allows errors to be initialized with a single string, a collection of strings, or a key-value pair.
204205

205206
```csharp
@@ -315,7 +316,7 @@ Since Danom introduces types that are most commonly found in your model and busi
315316

316317
### Fluent Validation Integration
317318

318-
Danom is integrated with [Fluent Validation](https://fluentvalidation.net/) to provide a seamless way to validate your models and return a `Result` or `ResultOption` with the validation errors.
319+
[Fluent Validation](https://fluentvalidation.net/) is an excellent library for building validation rules for your models. A first-class integration is available via [Danom.Validation](src/Danom.Validation/README.md) to provide a seamless way to validate your models and return a `Result` or `ResultOption` with the validation errors.
319320

320321
A quick example:
321322

@@ -353,9 +354,7 @@ Documentation can be found [here](src/Danom.Validation/README.md).
353354

354355
### ASP.NET Core MVC Integration
355356

356-
Danom is integrated with [ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/?view=aspnetcore-5.0) to provide a set of utilities to help integrate the Danom library with common tasks in ASP.NET Core MVC applications.
357-
358-
Documentation can be found [here](src/Danom.Mvc/README.md).
357+
Danom is integrated with ASP.NET Core via [Danom.Mvc](src/Danom.Mvc/README.md). This library provides a set of utilities to help integrate the core types with common tasks in ASP.NET Core MVC applications.
359358

360359
### ASP.NET Core Minimal API Integration
361360

src/Danom.Mvc/README.md

+92-38
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
[![NuGet Version](https://img.shields.io/nuget/v/Danom.Mvc.svg)](https://www.nuget.org/packages/Danom.Mvc)
33
[![build](https://github.com/pimbrouwers/Danom/actions/workflows/build.yml/badge.svg)](https://github.com/pimbrouwers/Danom/actions/workflows/build.yml)
44

5-
Danom.Mvc is a library that provides a set of rendering utilities to help integrate the [Danom](../../README.md) library with common tasks in ASP.NET Core MVC applications.
5+
Danom.Mvc is a library that provides a set of utilities to help integrate the [Danom](../../README.md) library with common tasks in ASP.NET Core MVC applications.
66

77
## Getting Started
88

@@ -17,7 +17,20 @@ Or using the dotnet CLI
1717
dotnet add package Danom.Mvc
1818
```
1919

20-
## Working With `Option`
20+
## Controller
21+
22+
The `DanomController` class extends the base controller class to provide a set of methods to help work with `Result`, `Option`, and `ResultOption` types in ASP.NET Core MVC applications.
23+
24+
25+
### Option
26+
27+
The `ViewOption` method is used to render a view based on the presence of an `Option` value.
28+
29+
If the `Option` is `Some`, the view is rendered with the value. If the `Option` is `None`, the `noneAction` is invoked. By default, the `noneAction` returns a `NotFound` result.
30+
31+
A custom view name can be provided to render a view with a different name than the action.
32+
33+
Some examples demonstrating the use of `ViewOption` are shown below:
2134

2235
```csharp
2336
using Danom.Mvc;
@@ -26,29 +39,32 @@ using Microsoft.AspNetCore.Mvc;
2639
public sealed class OptionController
2740
: DanomController
2841
{
29-
private readonly Option<string> _someOption = Option.Some("Hello world");
30-
private readonly Option<string> _noneOption = Option<string>.None();
31-
3242
public IActionResult OptionSome() =>
3343
ViewOption(
34-
option: _someOption,
44+
option: Option.Some("Hello world"),
3545
viewName: "Detail");
3646

3747
// Returns the ASP.NET default `NotFound` result
3848
public IActionResult OptionNone() =>
3949
ViewOption(
40-
option: _noneOption,
50+
option: Option<string>.NoneValue,
4151
viewName: "Detail");
4252

4353
public IActionResult OptionNoneCustom() =>
4454
ViewOption(
45-
option: _noneOption,
55+
option: Option<string>.NoneValue,
4656
viewName: "Detail",
4757
noneAction: () => NotFound("Not found!"));
4858
}
4959
```
5060

51-
## Working with `Result`
61+
### Result
62+
63+
The `ViewResult` method is used to render a view based on the presence of a `Result` value.
64+
65+
By default the `ViewResult` method will render the view with the value if the `Result` is `Ok`. If the `Result` is `Error`, the `errorAction` is invoked.
66+
67+
A custom view name can be provided to render a view with a different name than the action.
5268

5369
```csharp
5470
using Danom.Mvc;
@@ -57,58 +73,96 @@ using Microsoft.AspNetCore.Mvc;
5773
public sealed class ResultController
5874
: DanomController
5975
{
60-
private readonly Result<string, ResultErrors> _okResult = Result.Ok("Success!");
61-
private readonly Result<string, ResultErrors> _errorResult = Result<string>.Error(["An error occurred."]);
62-
private readonly Result<string, string> _stringErrorResult = Result<string, string>.Error("An error occurred.");
63-
6476
public IActionResult ResultOk() =>
6577
ViewResult(
66-
result: _okResult,
78+
result: Result<string, string>.Ok("Success!"),
6779
viewName: "Detail");
6880

69-
public IActionResult ResultErrors() =>
70-
ViewResult(
71-
result: _errorResult,
72-
viewName: "Detail");
73-
74-
// Demonstrating error customization, using a string literal for error output
7581
public IActionResult ResultError() =>
7682
ViewResult(
77-
result: _stringErrorResult,
83+
result: Result<string, string>.Error("An error occurred."),
7884
errorAction: errors => View("Detail", errors),
7985
viewName: "Detail");
8086

8187
}
8288
```
8389

84-
## Working with `ResultOption`
90+
Built into Danom is the `ResultErrors` type, which is particularly well suited for reporting model errors in ASP.NET Core MVC applications. The `ViewResultErrors` method, provided by the `DanomController` class, is a proxy for the `View` method that will inject the `ResultErrors` value into the model state.
91+
92+
When using `ResultErrors` as the error type, the `ViewResultErrors` will default the `errorAction` to inject the `ResultErrors` value into the model state.
8593

8694
```csharp
8795
using Danom.Mvc;
8896
using Microsoft.AspNetCore.Mvc;
8997

90-
public sealed class ResultOptionController
98+
public sealed class ResultController
9199
: DanomController
92100
{
93-
private readonly ResultOption<string, ResultErrors> _okResult = ResultOption.Ok("Success!");
94-
private readonly ResultOption<string, ResultErrors> _errorResult = ResultOption<string>.Error("An error occurred.");
95-
private readonly ResultOption<string, string> _stringErrorResult = ResultOption<string, string>.Error("An error occurred.");
96-
97101
public IActionResult ResultOk() =>
98-
ViewResultOption(
99-
resultOption: _okResult,
100-
viewName: "Detail");
101-
102-
public IActionResult ResultErrors() =>
103-
ViewResultOption(
104-
resultOption: _errorResult,
102+
ViewResult(
103+
// notice the lack of second type parameter, which is inferred to be ResultErrors
104+
result: Result<string>.Ok("Success!"),
105105
viewName: "Detail");
106106

107-
// Demonstrating error customization, using a string literal for error output
108107
public IActionResult ResultError() =>
109-
ViewResultOption(
110-
resultOption: _stringErrorResult,
111-
errorAction: errors => View("Detail", errors),
108+
ViewResult(
109+
result: Result<string>.Error("An error occurred."),
112110
viewName: "Detail");
111+
112+
113+
public IActionResult ResultErrorView() =>
114+
// can be used directly
115+
ViewResultErrors(
116+
errors: new("An error occurred."));
117+
}
118+
```
119+
120+
## View
121+
122+
### Option
123+
124+
While not explicitly part of the `Danom.Mvc` library, there are some patterns that make rendering the `Option` type easier in Razor views. Two methods from the base library are especially valuable: `TryGet` and `ToString`.
125+
126+
The `TryGet` method is used to extract the value from an `Option` type. If the `Option` is `Some`, the value is assigned to the `out` parameter and the method returns `true`. If the `Option` is `None`, the method returns `false`.
127+
128+
The custom `ToString` method is used to convert the `Option` value to a string. If the `Option` is `Some`, the value is converted to a string. If the `Option` is `None`, the method returns the default value. The method optionally accepts a second parameter for the format string.
129+
130+
Consider the following type:
131+
132+
```csharp
133+
public record Person(
134+
string Name,
135+
Option<DateOnly> Birthdate,
136+
Option<string> Email);
137+
```
138+
139+
The `TryGet` and `ToString` methods can be used in a Razor view to help render the optional properties.
140+
141+
```cshtml
142+
@model Person
143+
144+
<h1>@Model.Name</h1>
145+
<h2>Email: <i>@Model.Email.ToString("-")</i></h2>
146+
147+
@if (Model.Birthdate.TryGet(out var birthdate))
148+
{
149+
var now = DateTime.Now;
150+
var a = (now.Year * 100 + now.Month) * 100 + now.Day;
151+
var b = (birthdate.Year * 100 + birthdate.Month) * 100 + birthdate.Day;
152+
var age = (a - b) / 10000;
153+
154+
<p>You are born on @birthdate, and are @age years old.</p>
155+
}
156+
else
157+
{
158+
<p>You are an ageless wonder!</p>
113159
}
114160
```
161+
162+
## Find a bug?
163+
164+
There's an [issue](https://github.com/pimbrouwers/Danom/issues) for that.
165+
166+
## License
167+
168+
Built with ♥ by [Pim Brouwers](https://github.com/pimbrouwers) in Toronto, ON. Licensed under [Apache License 2.0](https://github.com/pimbrouwers/Danom/blob/master/LICENSE).

0 commit comments

Comments
 (0)