Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ You can find samples on new features available in ASP.NET Core 9(3) [here](/proj
| [Localization and Globalization](/projects/localization) | 6 | |
| [Middleware](/projects/middleware) | 14 | |
| [Mini Apps](/projects/mini) | 2 | |
| [Minimal API](/projects/minimal-api) | 36 | Routing, Parameter Bindings, etc |
| [Minimal API](/projects/minimal-api) | 37 | Routing, Parameter Bindings, etc |
| [Minimal Hosting](/projects/minimal-hosting) | 23 | |
| [MVC](/projects/mvc) | 47 | Localization, Routing, Razor Class Library, Tag Helpers, View Component, etc |
| [Output Cache Middleware](/projects/output-cache-middleware) | | |
Expand All @@ -72,7 +72,7 @@ You can find samples on new features available in ASP.NET Core 9(3) [here](/proj
| [Syndications](/projects/syndications) | 3 | |
| [Testing](/projects/testing) | 1 | |
| [Unpoly](/projects/unpoly) | 5 | |
| [URL Redirect/Rewrite](/projects/rewrite) | 6 | |
| https://weblogs.asp.net/owscott/rewrite-vs-redirect-what-s-the-difference(/projects/rewrite) | 6 | |
| [Uri Helper](/projects/uri-helper) | 5 | |
| [Windows Service](/projects/windows-service) | 1 | |
| [Web Sockets](/projects/web-sockets) | 6 | |
Expand All @@ -85,6 +85,12 @@ You can find samples on new features available in ASP.NET Core 9(3) [here](/proj

To run these samples, simply open your command line console, go to each folder and execute `dotnet watch run`.

### Minimal API (37)

- [Primitive Obsession Prevention](./projects/minimal-api/primitive-obsession)

This sample demonstrates how to prevent **Primitive Obsession** by using **Value Objects** and the `static TryParse` pattern for automatic parameter binding in Minimal APIs.

### Misc (6)

- [Application Environment](/projects/application-environment)
Expand Down Expand Up @@ -166,6 +172,4 @@ All these samples require `SixLabors.ImageSharp.Web` middleware package. This mi
## Misc

- [Contributor Guidelines](https://github.com/dodyg/practical-aspnetcore/blob/master/CONTRIBUTING.md)
- [Code of Conduct](https://github.com/dodyg/practical-aspnetcore/blob/master/CODE_OF_CONDUCT.md)


- [Code of Conduct](https://github.com/dodyg/practical-aspnetcore/blob/master/CODE_OF_CONDUCT.md)
1 change: 1 addition & 0 deletions global.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
"rollForward": "major",
"allowPrerelease": true
}

}
25 changes: 25 additions & 0 deletions projects/minimal-api/Primitive-Obsession/Primitive-Obsession.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36414.22 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Primitive-Obsession", "Primitive-Obsession\Primitive-Obsession.csproj", "{3722E737-D7F9-444B-BB09-C4B80452ACB4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3722E737-D7F9-444B-BB09-C4B80452ACB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3722E737-D7F9-444B-BB09-C4B80452ACB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3722E737-D7F9-444B-BB09-C4B80452ACB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3722E737-D7F9-444B-BB09-C4B80452ACB4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A9FE2ACE-83FF-4EDA-A57F-2237F9A761E7}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>Primitive_Obsession</RootNamespace>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// -------------------------------
// CASE 1: Primitive Obsession
// -------------------------------
// We rely on primitive types (string) to represent a domain concept.
// This forces validation logic to be repeated everywhere.

app.MapPost("/orders-bad", (string email) =>
{
if (string.IsNullOrWhiteSpace(email) || !email.Contains("@"))
return Results.BadRequest("Invalid email address");

return Results.Ok($"Order placed for {email}");
});


// -------------------------------
// CASE 2: Value Object
// -------------------------------
// We represent the concept using a dedicated type.
// ASP.NET Core will use TryParse during model binding.

app.MapPost("/orders-good", (EmailAddress email) =>
{
// If execution reaches here, the email is guaranteed to be valid
return Results.Ok($"Order placed for {email.Value}");
});


app.Run();


// -------------------------------
// Value Object
// -------------------------------
public sealed record EmailAddress
{
public string Value { get; }

private EmailAddress(string value)
{
Value = value;
}

// ASP.NET Core Minimal APIs automatically use TryParse
// during parameter binding.
public static bool TryParse(string? value, out EmailAddress? result)
{
if (!string.IsNullOrWhiteSpace(value) && value.Contains("@"))
{
result = new EmailAddress(value);
return true;
}

result = null;
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}