Skip to content

Commit

Permalink
Vnext (#258)
Browse files Browse the repository at this point in the history
* Enable ASP.NET integration without needing MVC (#205)
* Update various NuGet refs
* Drop netstandard2.0 support
* Bump to V3 because of breaking changes
* Fix all Messages in the Error List (#212)
  • Loading branch information
idg10 authored Dec 17, 2021
1 parent de5074f commit 1aac7f1
Show file tree
Hide file tree
Showing 70 changed files with 1,827 additions and 514 deletions.
18 changes: 17 additions & 1 deletion GitVersion.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
# DO NOT EDIT THIS FILE
# This file was generated by the pr-autoflow mechanism as a result of executing this action:
# https://github.com/endjin/.github/actions/workflows/deploy_pr_autoflow.yml
# This repository participates in this mechanism due to an entry in this file:
# https://github.com/endjin/.github/blob/b69ff1d66541ae049fb0457c65c719c6d7e9b862/repos/live/corvus-dotnet.yml

mode: ContinuousDeployment
branches:
master:
regex: ^master|main$
tag: preview
increment: patch
next-version: "2.1"
dependabot-pr:
regex: ^dependabot
tag: dependabot
source-branches:
- develop
- master
- release
- feature
- support
- hotfix
next-version: "3.0"

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

This provides abstractions for the Menes framework.

It is built for netstandard2.0.
It is built for netstandard2.1. (netstandard2.0 support is available in v2.x releases.)

## Features

Expand Down
9 changes: 8 additions & 1 deletion Solutions/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,11 @@ dotnet_style_qualification_for_property = true:suggestion
dotnet_style_qualification_for_event = true:suggestion

# Style - using
csharp_using_directive_placement = inside_namespace:warning
csharp_using_directive_placement = inside_namespace:warning

# IDE0090: Use 'new(...)'
# This is a bit aggressive. It suggests simplified new(...) even for:
# public static Thing MakeThing(string arg) => new(arg);
# That seems a step to far for me because you have to go searching for where
# the type name is.
dotnet_diagnostic.IDE0090.severity = silent
4 changes: 2 additions & 2 deletions Solutions/Menes.Abstractions/Menes.Abstractions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Import Project="$(EndjinProjectPropsPath)" Condition="$(EndjinProjectPropsPath) != ''" />

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>

<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
Expand All @@ -11,7 +11,7 @@
<!--
RCS1194 - we don't want the standard ctor patterns, as they clash with nullable references
-->
<NoWarn>RCS1194</NoWarn>
<NoWarn>$(NoWarn);RCS1194</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private void AddProblemDetails()

if (!string.IsNullOrEmpty(this.PolicyName))
{
this.AddProblemDetailsExtension("Policy Name", this.PolicyName!); // ! required as netstandard2.0 lacks nullable attributes
this.AddProblemDetailsExtension("Policy Name", this.PolicyName);
}

if (this.Requests?.Length > 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ private void AddProblemDetails()

if (!string.IsNullOrEmpty(this.ContentType))
{
this.AddProblemDetailsExtension("Owner ContentType", this.ContentType!); // ! required as netstandard2.0 lacks nullable attributes
this.AddProblemDetailsExtension("Owner ContentType", this.ContentType);
}

this.AddProblemDetailsExtension("Owner CLR type", this.FullTypeName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,8 @@ public OpenApiConfiguration(IServiceProvider serviceProvider)
/// <inheritdoc/>
public Dictionary<string, Type> DiscriminatedTypes
{
get
{
return this.discriminators ?? (this.discriminators = new Dictionary<string, Type>());
}

set
{
this.discriminators = value;
}
get => this.discriminators ??= new Dictionary<string, Type>();
set => this.discriminators = value;
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private void ValidateStatusCode(int statusCode)
{
throw new ArgumentException(
nameof(statusCode),
$"Do not explicitly map exceptions to the 500 status code.");
"Do not explicitly map exceptions to the 500 status code.");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public enum HalDocumentLinkRemovalOptions
NonRecursive = 1,

/// <summary>
/// Perform an unsafe check. With this options set, link checking will skip any <code>self</code> links
/// Perform an unsafe check. With this options set, link checking will skip any <c>self</c> links
/// and will also not validate any links that have a corresponding document in the <see cref="HalDocument.EmbeddedResources"/>
/// collection.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion Solutions/Menes.Abstractions/Menes/Links/WebLink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public bool Equals(WebLink? other)
/// <inheritdoc/>
public override int GetHashCode()
{
return (this.Href, this.Name, this.IsTemplated, this.Hreflang, this.Title, this.Type, this.Profile).GetHashCode();
return HashCode.Combine(this.Href, this.Name, this.IsTemplated, this.Hreflang, this.Title, this.Type, this.Profile);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static OpenApiDocument GetOpenApiServiceFromEmbeddedDefinition(

if (diagnostics.Errors.Count > 0)
{
throw new OpenApiServiceMismatchException($"Errors reading the YAML file at resource name attribute.ResourceName")
throw new OpenApiServiceMismatchException($"Errors reading the YAML file at resource name {resourceName}")
.AddProblemDetailsExtension("OpenApiErrors", diagnostics.Errors);
}

Expand Down
17 changes: 10 additions & 7 deletions Solutions/Menes.Hosting.AspNetCore/Menes.Hosting.AspNetCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,29 @@
<Import Project="$(EndjinProjectPropsPath)" Condition="$(EndjinProjectPropsPath) != ''" />

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Nullable>enable</Nullable>

<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageDescription>Menes is a framework for hosting Web APIs with OpenAPI-based service definitions. This library defines the ASP.NET-Core-specific aspects of hosting in Menes.</PackageDescription>

<WarningsAsErrors />

<!-- Don't want ConfigureAwait warnings because ASP.NET Core doesn't use synchronization context, so such calls are overhead with no purpose. -->
<NoWarn>$(NoWarn);RCS1090</NoWarn>
</PropertyGroup>

<ItemGroup>
<InternalsVisibleTo Include="Menes.Specs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Endjin.RecommendedPractices" Version="1.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Nullable" Version="1.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// <copyright file="MenesCatchAllMiddleware.cs" company="Endjin Limited">
// Copyright (c) Endjin Limited. All rights reserved.
// </copyright>

namespace Menes.Hosting.AspNetCore
{
using System.Threading.Tasks;

using Menes.Internal;

using Microsoft.AspNetCore.Http;

/// <summary>
/// Middleware that passes all requests on to Menes. This never forwards requests further down the pipeline.
/// </summary>
internal class MenesCatchAllMiddleware : IMiddleware
{
private static readonly object EmptyParameters = new ();
private readonly IOpenApiHost<HttpRequest, IHttpResponseResult> host;

/// <summary>
/// Creates a <see cref="MenesCatchAllMiddleware"/>.
/// </summary>
/// <param name="host">The Menes host.</param>
public MenesCatchAllMiddleware(IOpenApiHost<HttpRequest, IHttpResponseResult> host)
{
this.host = host;
}

/// <inheritdoc/>
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
await this.host.HandleRequestAsync(context, EmptyParameters);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// <copyright file="OpenApiAspNetApplicationBuilderExtensions.cs" company="Endjin Limited">
// Copyright (c) Endjin Limited. All rights reserved.
// </copyright>

namespace Menes.Hosting.AspNetCore
{
using Microsoft.AspNetCore.Builder;

/// <summary>
/// Extension methods for adding Menes to an ASP.NET Core pipeline.
/// </summary>
public static class OpenApiAspNetApplicationBuilderExtensions
{
/// <summary>
/// Adds middleware that directs all requests to Menes.
/// </summary>
/// <param name="app">The pipeline builder.</param>
/// <returns>The modified pipeline builder.</returns>
public static IApplicationBuilder UseMenesCatchAll(this IApplicationBuilder app)
{
return app.UseMiddleware<MenesCatchAllMiddleware>();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
// <copyright file="HttpRequestExtensions.cs" company="Endjin Limited">
// <copyright file="OpenApiHostActionResultExtensions.cs" company="Endjin Limited">
// Copyright (c) Endjin Limited. All rights reserved.
// </copyright>

namespace Menes.Hosting.AspNetCore
{
using System.Threading.Tasks;

using Menes;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

/// <summary>
/// Extension methods for HttpRequest.
/// </summary>
public static class HttpRequestExtensions
/// <remarks>
/// This is used in scenarios where we want to return an <see cref="IActionResult"/> to the
/// hosting framework (e.g. in Azure Functions v3).
/// </remarks>
public static class OpenApiHostActionResultExtensions
{
/// <summary>
/// Uses the <see cref="IOpenApiHost{HttpRequest, IActionResult}"/> to handle the request.
Expand All @@ -26,4 +32,4 @@ public static Task<IActionResult> HandleRequestAsync(this IOpenApiHost<HttpReque
return host.HandleRequestAsync(httpRequest.Path, httpRequest.Method, httpRequest, parameters);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// <copyright file="OpenApiHostDirectPipelineExtensions.cs" company="Endjin Limited">
// Copyright (c) Endjin Limited. All rights reserved.
// </copyright>

namespace Menes.Hosting.AspNetCore
{
using System.Threading.Tasks;

using Menes.Internal;

using Microsoft.AspNetCore.Http;

/// <summary>
/// Extension methods for <see cref="IOpenApiHost{HttpRequest, IHttpResponseResult}"/>.
/// </summary>
/// <remarks>
/// <para>
/// Applications typically don't use this directly. Instead, they will normally use
/// <see cref="OpenApiAspNetApplicationBuilderExtensions.UseMenesCatchAll(Microsoft.AspNetCore.Builder.IApplicationBuilder)"/>
/// to Menes middleware that calls this to an ASP.NET Core pipeline.
/// </para>
/// <para>
/// This does not require a dependency on MVC.
/// </para>
/// </remarks>
public static class OpenApiHostDirectPipelineExtensions
{
/// <summary>
/// Uses the <see cref="IOpenApiHost{HttpRequest, IActionResult}"/> to handle the request.
/// </summary>
/// <param name="host">The host to handle the request.</param>
/// <param name="httpContext">The context for the request to handle.</param>
/// <param name="parameters">Any dynamically constructed parameters sent to the request.</param>
/// <returns>The result of the request.</returns>
public static async Task HandleRequestAsync(
this IOpenApiHost<HttpRequest, IHttpResponseResult> host, HttpContext httpContext, object parameters)
{
HttpRequest httpRequest = httpContext.Request;
IHttpResponseResult result = await host.HandleRequestAsync(httpRequest.Path, httpRequest.Method, httpRequest, parameters);
await result.ExecuteResultAsync(httpContext.Response);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace Menes.Internal
/// <summary>
/// An implementation of an <see cref="IOpenApiParameterBuilder{TRequest}"/>.
/// </summary>
public class HttpRequestParameterBuilder : IOpenApiParameterBuilder<HttpRequest>
internal class HttpRequestParameterBuilder : IOpenApiParameterBuilder<HttpRequest>
{
private readonly IEnumerable<IOpenApiConverter> converters;
private readonly ILogger<HttpRequestParameterBuilder> logger;
Expand Down Expand Up @@ -276,7 +276,7 @@ private async Task TryAddBody(HttpRequest request, OpenApiOperationPathTemplate

string? requestBaseContentType = this.GetBaseContentType(request.ContentType);

if (string.IsNullOrEmpty(requestBaseContentType) || !operationPathTemplate.Operation.RequestBody.Content.TryGetValue(requestBaseContentType, out OpenApiMediaType openApiMediaType))
if (string.IsNullOrEmpty(requestBaseContentType) || !operationPathTemplate.Operation.RequestBody.Content.TryGetValue(requestBaseContentType, out OpenApiMediaType? openApiMediaType))
{
if (operationPathTemplate.Operation.RequestBody.Required)
{
Expand All @@ -299,7 +299,7 @@ private async Task TryAddBody(HttpRequest request, OpenApiOperationPathTemplate
request.Path,
request.Method,
request.ContentType,
string.Join(", ", operationPathTemplate?.Operation?.RequestBody?.Content?.Keys));
string.Join(", ", operationPathTemplate?.Operation?.RequestBody?.Content?.Keys ?? Array.Empty<string>()));
}

return;
Expand Down Expand Up @@ -514,7 +514,7 @@ private bool TryGetParameterFromPath(
return false;
}

if (templateParameters.TryGetValue(parameter.Name, out object value))
if (templateParameters.TryGetValue(parameter.Name, out object? value))
{
if (this.logger.IsEnabled(LogLevel.Debug))
{
Expand All @@ -523,7 +523,7 @@ private bool TryGetParameterFromPath(
parameter.Name);
}

result = this.ConvertValue(parameter.Schema, value.ToString());
result = this.ConvertValue(parameter.Schema, value.ToString() !);
return true;
}

Expand Down Expand Up @@ -674,4 +674,4 @@ private object ConvertValue(OpenApiSchema schema, string value)
throw new OpenApiServiceMismatchException($"Unable to convert value to match [{schema.GetLoggingInformation()}]");
}
}
}
}
Loading

0 comments on commit 1aac7f1

Please sign in to comment.