Skip to content
Merged
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
16 changes: 10 additions & 6 deletions .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,32 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v2
with:
dotnet-version: 9.*
dotnet-version: 10.*
include-prerelease: true

- name: Build Reason
run: echo ${{github.ref}} and ${{github.event_name}}

- name: Build with dotnet
run: >-
dotnet build
--configuration Release
--nologo

- name: Run tests
run: >-
dotnet test
--configuration Release
--logger trx
--no-build
--nologo
- name: Publish test results
uses: dorny/test-reporter@v1

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: .NET tests
path: '**/*.trx'
reporter: dotnet-trx
name: test-results
path: '**/*.trx'

# PR merged or main tag created, create the CarterTemplate NuGet package
- if: github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/newtonsoft-')
Expand Down
26 changes: 26 additions & 0 deletions .github/workflows/test-results.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Test Results

on:
workflow_run:
workflows: [".NET Core"]
types:
- completed

jobs:
test-results:
name: Publish Test Results
runs-on: ubuntu-latest
if: always()
permissions:
contents: read
actions: read
checks: write

steps:
- name: Publish test results
uses: dorny/test-reporter@v2
with:
name: .NET tests
artifact: test-results
path: 'test-results/**/*.trx'
reporter: dotnet-trx
15 changes: 15 additions & 0 deletions Carter.sln
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Carter.ResponseNegotiators.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Carter.Analyzers", "src\Carter.Analyzers\Carter.Analyzers.csproj", "{C15C71C0-73CE-41DA-8EEE-C66318BF3A6C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFwk", "samples\EntityFwk\EntityFwk.csproj", "{E907925B-A874-40EA-A7A8-0A41E462A465}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -164,6 +166,18 @@ Global
{C15C71C0-73CE-41DA-8EEE-C66318BF3A6C}.Release|x64.Build.0 = Release|Any CPU
{C15C71C0-73CE-41DA-8EEE-C66318BF3A6C}.Release|x86.ActiveCfg = Release|Any CPU
{C15C71C0-73CE-41DA-8EEE-C66318BF3A6C}.Release|x86.Build.0 = Release|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Debug|x64.ActiveCfg = Debug|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Debug|x64.Build.0 = Debug|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Debug|x86.ActiveCfg = Debug|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Debug|x86.Build.0 = Debug|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Release|Any CPU.Build.0 = Release|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Release|x64.ActiveCfg = Release|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Release|x64.Build.0 = Release|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Release|x86.ActiveCfg = Release|Any CPU
{E907925B-A874-40EA-A7A8-0A41E462A465}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -179,6 +193,7 @@ Global
{D30E87B0-39AE-41FE-8BA3-E5F9FBFFDD64} = {5D056A8A-821C-4C3C-A281-4FA7F8CE251B}
{47DD3AA8-F072-41E3-AF7F-119DBBD8D14A} = {DCB5B9A0-F06D-4BDF-917D-A459C790C718}
{C15C71C0-73CE-41DA-8EEE-C66318BF3A6C} = {5D056A8A-821C-4C3C-A281-4FA7F8CE251B}
{E907925B-A874-40EA-A7A8-0A41E462A465} = {35DE35A0-758D-4FDD-BDA3-67F04F65677D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9096DE78-6327-48BA-AE0E-336F769681A7}
Expand Down
20 changes: 9 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ Other extensions include:

* `Validate<T> / ValidateAsync<T>` - [FluentValidation](https://github.com/JeremySkinner/FluentValidation) extensions to validate incoming HTTP requests which is not available with ASP.NET Core Minimal APIs.
* `BindFile/BindFiles/BindFileAndSave/BindFilesAndSave` - Allows you to easily get access to a file/files that has been uploaded. Alternatively you can call `BindFilesAndSave` and this will save it to a path you specify.
* Routes to use in common ASP.NET Core middleware e.g., `app.UseExceptionHandler("/errorhandler");`.
* `MapPost<T>/MapPut<T>` - Allows Carter to validate `T` and if it fails it returns a 422 Problem Details response.
* `MapFormPost<T>` - Allows Carter to model bind `T` when submitting a form to the route.
* `IResponseNegotiator`s allow you to define how the response should look on a certain Accept header(content negotiation). Handling JSON is built in the default response but implementing an interface allows the user to choose how they want to represent resources.
* Routes to use in common ASP.NET Core middleware e.g., `app.UseExceptionHandler("/errorhandler");`.
* All interface implementations for Carter components are registered into ASP.NET Core DI automatically. Implement the interface and off you go.

### Releases
Expand Down Expand Up @@ -118,6 +120,7 @@ public class HomeModule : ICarterModule
});
app.MapGet("/conneg", (HttpResponse res) => res.Negotiate(new { Name = "Dave" }));
app.MapPost("/validation", HandlePost);
app.MapFormPost("/formpost", (Person model) => TypedResults.Ok(model)).DisableAntiforgery();
}

private IResult HandlePost(HttpContext ctx, Person person, IDatabase database)
Expand Down Expand Up @@ -156,7 +159,7 @@ public class Database : IDatabase

### Configuration

As mentioned earlier Carter will scan for implementations in your app and register them for DI. However, if you want a more controlled app, Carter comes with a `CarterConfigurator` that allows you to register modules, validators and response negotiators manually.
As mentioned earlier Carter will scan for implementations in your app and register them for DI. However, if you want a more controlled app, Carter comes with a `CarterConfigurator` that allows you to register modules, validators and response negotiators manually and configure validator lifetimes.

Carter will use a response negotiator based on `System.Text.Json`, though it provides for custom implementations via the `IResponseNegotiator` interface. To use your own implementation of `IResponseNegotiator` (say, `CustomResponseNegotiator`), add the following line to the initial Carter configuration, in this case as part of `Program.cs`:

Expand All @@ -166,16 +169,11 @@ Carter will use a response negotiator based on `System.Text.Json`, though it pro
{
c.WithResponseNegotiator<CustomResponseNegotiator>();
c.WithModule<MyModule>();
c.WithValidator<TestModelValidator>()
c.WithValidator<TestModelValidator>();
c.WithDefaultValidatorLifetime(ServiceLifetime.Singleton);
c.WithValidatorServiceLifetimeFactory(t => {if t is PersonValidator...})
});

```

Here again, Carter already ships with a response negotiator using `Newtonsoft.Json`, so you can wire up the Newtonsoft implementation with the following line:

```csharp
builder.Services.AddCarter(configurator: c =>
{
c.WithResponseNegotiator<NewtonsoftJsonResponseNegotiator>();
});
```
If you wish to use `Newtonsoft.Json` Carter already ships a response negotiator in the package `Carter.ResponseNegotiators.Newtonsoft`. Once installed, it will automatically pick it up with no registration needed.
2 changes: 1 addition & 1 deletion samples/CarterAndMVC/CarterAndMVC.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<AssemblyName>CarterAndMVC</AssemblyName>
<OutputType>Exe</OutputType>
<LangVersion>latest</LangVersion>
Expand Down
32 changes: 15 additions & 17 deletions samples/CarterAndMVC/Program.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
namespace CarterAndMVC
{
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Carter;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel()
.UseStartup<Startup>()
.Build();
var builder = WebApplication.CreateBuilder(args);

host.Run();
}
}
}
builder.Services.AddCarter();
builder.Services.AddControllers();

var app = builder.Build();

app.MapCarter();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
25 changes: 0 additions & 25 deletions samples/CarterAndMVC/Startup.cs

This file was deleted.

2 changes: 1 addition & 1 deletion samples/CarterSample/CarterSample.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions samples/CarterSample/Features/Actors/ActorValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace CarterSample.Features.Actors;

using FluentValidation;

[ValidatorLifetimeAttribute(ServiceLifetime.Scoped)]
public class ActorValidator : AbstractValidator<Actor>
{
public ActorValidator()
Expand Down
23 changes: 23 additions & 0 deletions samples/EntityFwk/EntityFwk.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoDefaultLaunchSettingsFile>True</NoDefaultLaunchSettingsFile>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Carter\Carter.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.0-rc.1.25451.107" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0-rc.1.25451.107">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0-rc.1.25451.107" />
</ItemGroup>

</Project>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading