Skip to content

Commit

Permalink
Update TargetFramework to .NET 7 (#112)
Browse files Browse the repository at this point in the history
* Update TargetFramework to .NET 7

* Update projects to reflect modern .NET patterns

* Update README

* Update package versions from 4.2.0 -> 7.0.0

* rename method

* update packages

* Update release notes and CI pipelines for .NET 7

* Use .NEt 7.x and update unit test project to .NET 7

* update package release notes
  • Loading branch information
KyleMcMaster committed Feb 23, 2023
1 parent e545953 commit 8432b42
Show file tree
Hide file tree
Showing 28 changed files with 177 additions and 203 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '7.0.x'
dotnet-version: '7.x'
- name: Install dependencies
run: dotnet restore
- name: Build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-result-related.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.x
dotnet-version: '7.x'
- name: Install dependencies
run: dotnet restore
- name: Build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-result.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.x
dotnet-version: '7.x'
- name: Install dependencies
run: dotnet restore
- name: Build
Expand Down
13 changes: 7 additions & 6 deletions Ardalis.Result.sln
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ardalis.Result.Sample.Core"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ardalis.Result.FluentValidation", "src\Ardalis.Result.FluentValidation\Ardalis.Result.FluentValidation.csproj", "{43443B4B-2305-4CDF-A7A4-32A80ED1D19B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ardalis.Result.AspNetCore.UnitTests", "tests\Ardalis.Result.AspNetCore.UnitTests\Ardalis.Result.AspNetCore.UnitTests.csproj", "{0BDA82F9-3602-4705-8DCD-A4724CAAF800}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ardalis.Result.SampleMinimalApi", "sample\Ardalis.Result.SampleMinimalApi\Ardalis.Result.SampleMinimalApi.csproj", "{60860685-37BB-47D9-B0DC-6FE7F0DB2AE5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ardalis.Result.SampleMinimalApi.FunctionalTests", "sample\Ardalis.Result.SampleMinimalApi.FunctionalTests\Ardalis.Result.SampleMinimalApi.FunctionalTests.csproj", "{A9769533-C9B2-4AD4-8B24-70C474D8EBB0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ardalis.Result.AspNetCore.UnitTests", "tests\Ardalis.Result.AspNetCore.UnitTests\Ardalis.Result.AspNetCore.UnitTests.csproj", "{C522FE42-BBEF-46A7-9E3E-44EA8339AF2E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -69,10 +69,6 @@ Global
{43443B4B-2305-4CDF-A7A4-32A80ED1D19B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{43443B4B-2305-4CDF-A7A4-32A80ED1D19B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{43443B4B-2305-4CDF-A7A4-32A80ED1D19B}.Release|Any CPU.Build.0 = Release|Any CPU
{0BDA82F9-3602-4705-8DCD-A4724CAAF800}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BDA82F9-3602-4705-8DCD-A4724CAAF800}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BDA82F9-3602-4705-8DCD-A4724CAAF800}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BDA82F9-3602-4705-8DCD-A4724CAAF800}.Release|Any CPU.Build.0 = Release|Any CPU
{60860685-37BB-47D9-B0DC-6FE7F0DB2AE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{60860685-37BB-47D9-B0DC-6FE7F0DB2AE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{60860685-37BB-47D9-B0DC-6FE7F0DB2AE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -81,6 +77,10 @@ Global
{A9769533-C9B2-4AD4-8B24-70C474D8EBB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9769533-C9B2-4AD4-8B24-70C474D8EBB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9769533-C9B2-4AD4-8B24-70C474D8EBB0}.Release|Any CPU.Build.0 = Release|Any CPU
{C522FE42-BBEF-46A7-9E3E-44EA8339AF2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C522FE42-BBEF-46A7-9E3E-44EA8339AF2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C522FE42-BBEF-46A7-9E3E-44EA8339AF2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C522FE42-BBEF-46A7-9E3E-44EA8339AF2E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -96,6 +96,7 @@ Global
{43443B4B-2305-4CDF-A7A4-32A80ED1D19B} = {865A74CD-F478-4AA5-AFA5-6C26FB38B849}
{60860685-37BB-47D9-B0DC-6FE7F0DB2AE5} = {FA061DC6-61B7-401F-87A4-D338B396CCD9}
{A9769533-C9B2-4AD4-8B24-70C474D8EBB0} = {FA061DC6-61B7-401F-87A4-D338B396CCD9}
{C522FE42-BBEF-46A7-9E3E-44EA8339AF2E} = {42693FB1-04E1-4635-B249-E1847609E801}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7CD0ED8C-3B1C-4F16-8B8D-3D8F1A8F1A5A}
Expand Down
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public async Task<ActionResult<CustomerDTO>>(int customerId)

Another approach is to return a `Tuple` of the expected result along with other things, like a status code and additional failure mode metadata. While tuples can be great for individual, flexible responses, they're not as good for having a single, standard, reusable approach to a problem.

The result pattern provides a standard, reusable way to return both success as well as multiple kinds of non-success responses from .NET services in a way that can easily be mapped to API response types. Although the [Ardalis.Result](https://www.nuget.org/packages/Ardalis.Result/) package has no dependencies on ASP.NET Core and can be used from any .NET Core application, the [Ardalis.Result.AspNetCore](https://www.nuget.org/packages/Ardalis.Result.AspNetCore/) companion package includes resources to enhance the use of this pattern within ASP.NET Core web API applications.
The Result pattern provides a standard, reusable way to return both success as well as multiple kinds of non-success responses from .NET services in a way that can easily be mapped to API response types. Although the [Ardalis.Result](https://www.nuget.org/packages/Ardalis.Result/) package has no dependencies on ASP.NET Core and can be used from any .NET Core application, the [Ardalis.Result.AspNetCore](https://www.nuget.org/packages/Ardalis.Result.AspNetCore/) companion package includes resources to enhance the use of this pattern within ASP.NET Core web API applications.

## Sample Usage

Expand Down Expand Up @@ -164,16 +164,16 @@ public ActionResult<WeatherForecastSummaryDto> CreateSummaryForecast([FromBody]
}
```

## Asp Net API Metadata
## ASP.NET API Metadata

By default, Asp Net Core and Api Explorer know nothing about `[TranslateResultToActionResult]` and what it is doing. To reflect `[TranslateResultToActionResult]` behavior in metadata generated by Api Explorer (which is then used by tools like Swashbuckle, NSwag etc.), you can use `ResultConvention`:
By default, Asp Net Core and API Explorer know nothing about `[TranslateResultToActionResult]` and what it is doing. To reflect `[TranslateResultToActionResult]` behavior in metadata generated by API Explorer (which is then used by tools like Swashbuckle, NSwag etc.), you can use `ResultConvention`:

```csharp
services.AddControllers(mvcOptions => mvcOptions.AddDefaultResultConvention());
```

This will add `[ProducesResponseType]` for every known `ResultStatus` to every endpoint marked with `[TranslateResultToActionResult]`.
To customize ResultConvention behavior, one may use `AddResultConvention` method:
To customize ResultConvention behavior, one may use the `AddResultConvention` method:

```csharp
services.AddControllers(mvcOptions => mvcOptions
Expand All @@ -182,9 +182,9 @@ services.AddControllers(mvcOptions => mvcOptions
));
```

This code is functionally equivalent to previous example.
This code is functionally equivalent to the previous example.

From here you can modify ResultStatus-to-HttpStatusCode mapping
From here you can modify the ResultStatus to HttpStatusCode mapping

```csharp
services.AddControllers(mvcOptions => mvcOptions
Expand All @@ -211,7 +211,7 @@ services.AddControllers(mvcOptions => mvcOptions
));
```

Alternatively, you can specify which (failure) result statuses are expected from certain endpoint:
Alternatively, you can specify which (failure) result statuses are expected from a certain endpoint:

```csharp
[TranslateResultToActionResult()]
Expand All @@ -223,9 +223,9 @@ public Result RemovePerson(int id)
}
```

`!!!` If you list certain result status in `ExpectedFailures`, it must be configured in `ResultConvention` on startup.
`!!!` If you list a certain Result status in `ExpectedFailures`, it must be configured in `ResultConvention` on startup.

Another configurability feature is what part of Result object is returned in case of specific failure:
Another configurable feature is what part of the Result object is returned in case of specific failure:

```csharp
services.AddControllers(mvcOptions => mvcOptions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<AssemblyName>Ardalis.Result.Sample.Core</AssemblyName>
<RootNamespace>Ardalis.Result.Sample.Core</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="6.0.13" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="7.0.3" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Runtime" Version="4.3.1" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.9.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="FluentAssertions" Version="6.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.13" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
Expand All @@ -12,7 +12,7 @@

<ItemGroup>
<ProjectReference Include="..\..\src\Ardalis.Result.AspNetCore\Ardalis.Result.AspNetCore.csproj">
<SetTargetFramework>TargetFramework=net6.0</SetTargetFramework>
<SetTargetFramework>TargetFramework=net7.0</SetTargetFramework>
</ProjectReference>
<ProjectReference Include="..\Ardalis.Result.Sample.Core\Ardalis.Result.Sample.Core.csproj" />
</ItemGroup>
Expand Down
2 changes: 0 additions & 2 deletions sample/Ardalis.Result.SampleMinimalApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddScoped<WeatherService>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.13" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@

namespace Ardalis.Result.SampleWeb.FunctionalTests;

public class PersonControllerDelete : IClassFixture<WebApplicationFactory<Startup>>
public class PersonControllerDelete : IClassFixture<WebApplicationFactory<WebMarker>>
{
private const string MEDIATR_CONTROLLER_POST_ROUTE = "/mediatr/person/remove/{0}";
private const string CONTROLLER_POST_ROUTE = "/person/remove/{0}";
private const string ENDPOINT_POST_ROUTE = "/person/delete/{0}";

private readonly HttpClient _client;

public PersonControllerDelete(WebApplicationFactory<Startup> factory)
public PersonControllerDelete(WebApplicationFactory<WebMarker> factory)
{
_client = factory.CreateClient();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@

namespace Ardalis.Result.SampleWeb.FunctionalTests;

public class WeatherForecastControllerPost : IClassFixture<WebApplicationFactory<Startup>>
public class WeatherForecastControllerPost : IClassFixture<WebApplicationFactory<WebMarker>>
{
private const string CONTROLLER_POST_ROUTE = "/weatherforecast/create";
private const string ENDPOINT_POST_ROUTE = "/forecast/new";
private readonly HttpClient _client;

public WeatherForecastControllerPost(WebApplicationFactory<Startup> factory)
public WeatherForecastControllerPost(WebApplicationFactory<WebMarker> factory)
{
_client = factory.CreateClient();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Ardalis.ApiEndpoints" Version="4.0.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.11" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion sample/Ardalis.Result.SampleWeb/Pages/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</p>
<p>WeatherForecast:</p>
<ul>
<li>PostalCode 55555 should work (200 OK)</li>
<li>PostalCode 55555 should work (201 Created)</li>
<li>PostalCode "" should fail (400 Bad Request with error list (required))</li>
<li>PostalCode "NotFound" should return (404 Not Found)</li>
<li>PostalCode "This is too long." should return (400 Bad Request with error list)</li>
Expand Down
77 changes: 64 additions & 13 deletions sample/Ardalis.Result.SampleWeb/Program.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,70 @@
using Ardalis.Result;
using Ardalis.Result.AspNetCore;
using Ardalis.Result.Sample.Core.Services;
using Ardalis.Result.SampleWeb.MediatrApi;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Globalization;
using System.Net;

namespace Ardalis.Result.SampleWeb;
var builder = WebApplication.CreateBuilder(args);

public class Program
var webAssembly = typeof(Program).Assembly;
builder.Services.AddMediatR(webAssembly);
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));

builder.Services.AddControllers(mvcOptions => mvcOptions
.AddResultConvention(resultStatusMap => resultStatusMap
.AddDefaultMap()
.For(ResultStatus.Ok, HttpStatusCode.OK, resultStatusOptions => resultStatusOptions
.For("POST", HttpStatusCode.Created)
.For("DELETE", HttpStatusCode.NoContent))
.Remove(ResultStatus.Forbidden)
.Remove(ResultStatus.Unauthorized)
));

builder.Services.AddRazorPages();
builder.Services.AddLocalization(opt => { opt.ResourcesPath = "Resources"; });
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-US"),
new CultureInfo("de-DE"),
};
options.DefaultRequestCulture = new RequestCulture("en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});

builder.Services.AddSwaggerGen();
builder.Services.AddTransient<PersonService>();
builder.Services.AddTransient<WeatherService>();
builder.Services.AddTransient<WeatherServiceWithExceptions>();

var app = builder.Build();

if (builder.Environment.IsDevelopment())
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
app.UseDeveloperExceptionPage();
}

app.UseHttpsRedirection();

app.UseRouting();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"));

var options = app.Services.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);

app.MapControllers();
app.MapRazorPages();

app.Run();
Loading

0 comments on commit 8432b42

Please sign in to comment.