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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 6.1.0
- Added support for .NET 10

# 6.0.4
- AuditLogging: Stored procedure cache was not being correctly persisted to avoid redundant `SELECT OBJECT_DEFINITION` queries.
- Added `CoalesceOptions.PreventAspNetBrowserRefresh()` utility method to block unwanted `aspnetcore-browser-refresh.js` script.
Expand Down
30 changes: 25 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,38 @@
</PropertyGroup>
<!-- TargetFramework is empty for projects that aren't multi-targeting (i.e. the playground
projects) -->
<PropertyGroup Condition=" '$(TargetFramework)' == 'net9.0' or '$(TargetFramework)' == '' ">
<PropertyGroup Condition=" '$(TargetFramework)' == 'net9.0'">
<DotNetPackageVersionSpec>9.0.7</DotNetPackageVersionSpec>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net10.0' or '$(TargetFramework)' == '' ">
<DotNetPackageVersionSpec>10.0.0</DotNetPackageVersionSpec>
</PropertyGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0'">
<PackageVersion Include="Microsoft.OpenApi" Version="1.6.24" />
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.24" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.2.2" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="9.0.3" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0'">
<PackageVersion Include="Microsoft.OpenApi" Version="1.6.24" />
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.24" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.2.2" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="9.0.3" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net10.0'">
<PackageVersion Include="Microsoft.OpenApi" Version="2.3.9" />
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.24" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.1.1" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.0.1" />
</ItemGroup>

<ItemGroup>
<PackageVersion Include="Bogus" Version="35.6.1" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="GenFu" Version="1.4.22" />
<PackageVersion Include="McMaster.Extensions.CommandLineUtils" Version="2.3.0" />
<PackageVersion Include=" Microsoft.Build.Tasks.Core " Version="17.14.28" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(DotNetPackageVersionSpec)" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(DotNetPackageVersionSpec)" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="$(DotNetPackageVersionSpec)" />
Expand All @@ -24,7 +48,6 @@
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing" Version="1.1.2" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.14.0" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.2.2" />
<PackageVersion Include="Microsoft.DotNet.Cli.Utils" Version="2.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="$(DotNetPackageVersionSpec)" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="$(DotNetPackageVersionSpec)" />
Expand All @@ -33,8 +56,6 @@
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="$(DotNetPackageVersionSpec)" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(DotNetPackageVersionSpec)" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="Microsoft.OpenApi" Version="1.6.24" />
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.24" />
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.60.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Agents.Core" Version="1.60.0" />
<PackageVersion Include="Moq" Version="4.20.72" />
Expand All @@ -43,7 +64,6 @@
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
<PackageVersion Include="Roslynator.Analyzers" Version="4.12.7" />
<PackageVersion Include="Scalar.AspNetCore" Version="2.8.10" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="9.0.3" />
<PackageVersion Include="System.Net.Http.Json" Version="8.0.1" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
Expand Down
6 changes: 3 additions & 3 deletions coalesce-vue3.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"webProject": {
"projectFile": "./playground/Coalesce.Web.Vue3/Coalesce.Web.Vue3.csproj",
"framework": "net9.0"
"framework": "net10.0"
},
"dataProject": {
"projectFile": "./playground/Coalesce.Domain/Coalesce.Domain.csproj",
"framework": "net9.0"
"framework": "net10.0"
},
//"rootTypesWhitelist": [
// "CaseDto"
//],
"rootGenerator": "Vue"
}
}
4 changes: 2 additions & 2 deletions docs/stacks/agnostic/generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ Coalesce's code generation is run via a dotnet CLI tool, ``dotnet coalesce``. In
``` xml
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>

<!-- Necessary to use DotNetCliToolReference with modern framework versions -->
<DotnetCliToolTargetFramework>net8.0</DotnetCliToolTargetFramework>
<DotnetCliToolTargetFramework>net10.0</DotnetCliToolTargetFramework>
</PropertyGroup>

...
Expand Down
4 changes: 2 additions & 2 deletions docs/topics/coalesce-json.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ A full example of a `coalesce.json` file, along with an explanation of each prop

// Optional: Framework to use when evaluating & building dependencies.
// Not needed if your project only specifies a single framework - only required for multi-targeting projects.
"framework": "net8.0",
"framework": "net10.0",

// Optional: Build configuration to use when evaluating & building dependencies.
// Defaults to "Debug".
Expand All @@ -43,7 +43,7 @@ A full example of a `coalesce.json` file, along with an explanation of each prop

// Optional: Framework to use when evaluating & building dependencies.
// Not needed if your project only specifies a single framework - only required for multi-targeting projects.
"framework": "net8.0",
"framework": "net10.0",

// Optional: Build configuration to use when evaluating & building dependencies.
// Defaults to "Release".
Expand Down
2 changes: 1 addition & 1 deletion playground/Coalesce.Domain/Coalesce.Domain.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<!-- All these frameworks are included for testing code generation.
Override the used framework by specifying (framework: "tfm") in coalesce.json. -->
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
7 changes: 4 additions & 3 deletions playground/Coalesce.Web.Vue3/Coalesce.Web.Vue3.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>

<InterceptorsNamespaces>$(InterceptorsNamespaces);Microsoft.AspNetCore.OpenApi.Generated</InterceptorsNamespaces>

<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<UserSecretsId>9383b630-8d8c-43f5-afd7-46f1a33f2aa9</UserSecretsId>
Expand All @@ -18,4 +19,4 @@
<ProjectReference Include="..\..\src\IntelliTect.Coalesce.Swashbuckle\IntelliTect.Coalesce.Swashbuckle.csproj" />
</ItemGroup>

</Project>
</Project>
1 change: 0 additions & 1 deletion playground/Coalesce.Web.Vue3/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public HomeController(IWebHostEnvironment hostingEnvironment)

public IActionResult Index()
{

IFileProvider provider = new PhysicalFileProvider(hostingEnvironment.WebRootPath);
IFileInfo fileInfo = provider.GetFileInfo("index.html");
if (!fileInfo.Exists)
Expand Down
18 changes: 18 additions & 0 deletions playground/Coalesce.Web.Vue3/Pages/TestPage.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@page
@model Coalesce.Web.Vue.Pages.TestPageModel
@{
}

<!DOCTYPE html>
<html>

<head>
<title>Test Page</title>
</head>

<body>
<h1>Test Razor Page</h1>
<p>This is a test page.</p>
</body>

</html>
10 changes: 10 additions & 0 deletions playground/Coalesce.Web.Vue3/Pages/TestPage.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Coalesce.Web.Vue.Pages;

public class TestPageModel : PageModel
{
public void OnGet()
{
}
}
5 changes: 3 additions & 2 deletions playground/Coalesce.Web.Vue3/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using IntelliTect.Coalesce;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging.Console;
using Microsoft.OpenApi.Models;
using Microsoft.SemanticKernel;
using Scalar.AspNetCore;
using System.Reflection;
Expand Down Expand Up @@ -43,6 +42,7 @@
}));
services.AddScoped<Person.WithoutCases>();

services.AddRazorPages();
services.AddMvc();

services.Configure<Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions>(options =>
Expand All @@ -56,7 +56,7 @@
services.AddSwaggerGen(c =>
{
c.AddCoalesce();
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
c.SwaggerDoc("v1", new() { Title = "My API", Version = "v1" });
});

services.AddScoped<IWeatherService, WeatherService>();
Expand Down Expand Up @@ -103,6 +103,7 @@
app.UseNoCacheResponseHeader();

app.UseCors(c => c.AllowAnyOrigin().AllowAnyHeader());
app.MapRazorPages();
app.MapControllers();

app.MapOpenApi();
Expand Down
2 changes: 1 addition & 1 deletion src/Common.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<Project>
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ private static void SetupSolutionState(SolutionState solutionState)
solutionState.ReferenceAssemblies = ReferenceAssemblies.Net.Net80;
#elif NET9_0
solutionState.ReferenceAssemblies = ReferenceAssemblies.Net.Net90;
#elif NET10_0
solutionState.ReferenceAssemblies = new ReferenceAssemblies(
targetFramework: "net10.0",
referenceAssemblyPackage: new PackageIdentity("Microsoft.NETCore.App.Ref", "10.0.0"),
referenceAssemblyPath: System.IO.Path.Combine("ref", "net10.0"));
#else
#error "Add reference assemblies for new target framework.
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@ namespace IntelliTect.Coalesce.AuditLogging.Tests;

public class SqlServerAuditTests
{
private const string SqlServerConnString = "Server=(localdb)\\MSSQLLocalDB;Database=CoalesceAuditLoggingTests" +
#if NET9_0
"net9" +
#else
"net8" +
#endif
";Trusted_Connection=True;Timeout=5";
private static readonly string SqlServerConnString = $"Server=(localdb)\\MSSQLLocalDB;Database=CoalesceAuditLoggingTestsnet{Environment.Version.Major};Trusted_Connection=True;Timeout=5";

[SkippableFact]
public async Task WithSqlServer_UpdatesExistingRecordForLikeChanges()
Expand Down Expand Up @@ -271,6 +265,7 @@ private static TestDbContext BuildDbContextWithStoredProcedures()
try
{
db.Database.EnsureDeleted();
AuditOptions.ClearStoredProcedureCache();
db.Database.EnsureCreated();
}
catch (SqlException ex) when (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using IntelliTect.Coalesce.DataAnnotations;
using Microsoft.Extensions.Caching.Memory;
using System;

namespace IntelliTect.Coalesce.AuditLogging;
Expand Down Expand Up @@ -75,6 +76,21 @@ public class AuditOptions
/// that we make in CoalesceAuditLoggingBuilder.
/// </summary>
internal AuditConfiguration? AuditConfiguration { get; set; }

/// <summary>
/// Cache for stored procedure names. Size is limited in case there is an application whose Model
/// is not a singleton, e.g. dynamic model configuration for schema-based tenancy.
/// </summary>
internal static readonly MemoryCache StoredProcedureCache = new MemoryCache(new MemoryCacheOptions() { SizeLimit = 4_000 });

/// <summary>
/// Wipes the cache of known existing audit log merge stored procedures
/// that is used if <see cref="UseStoredProcedures" /> is enabled.
/// </summary>
public static void ClearStoredProcedureCache()
{
StoredProcedureCache.Clear();
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,21 +308,17 @@ @MergeWindowSeconds INT
""";
}

/// <summary>
/// Cache for stored procedure names. Size is limited in case there is an application whose Model
/// is not a singleton, e.g. dynamic model configuration for schema-based tenancy.
/// </summary>
private static readonly MemoryCache _storedProcedureCache = new MemoryCache(new MemoryCacheOptions() { SizeLimit = 4_000 });

/// <summary>
/// Ensures the stored procedure exists and returns its name.
/// </summary>
private async ValueTask<string> EnsureStoredProcedureExists(DbContext db, string sql, bool async)
{
var cacheKey = (db.Model, db.Database.GetConnectionString());

var procedureName = GetStoredProcedureName(sql);

// Check if we've already verified this procedure exists for this model
if (_storedProcedureCache.TryGetValue<string>(db.Model, out var cachedName) && cachedName == procedureName)
if (AuditOptions.StoredProcedureCache.TryGetValue<string>(cacheKey, out var cachedName) && cachedName == procedureName)
{
return procedureName;
}
Expand All @@ -346,9 +342,9 @@ private async ValueTask<string> EnsureStoredProcedureExists(DbContext db, string
}

// Cache that we've verified this procedure exists with the correct content
_storedProcedureCache.Set(db.Model, procedureName, new MemoryCacheEntryOptions
AuditOptions.StoredProcedureCache.Set(cacheKey, procedureName, new MemoryCacheEntryOptions
{
Size = procedureName.Length,
Size = procedureName.Length + cacheKey.Item2?.Length,
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) // Re-verify after an hour
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<IsPackable>false</IsPackable>
<InterceptorsNamespaces>$(InterceptorsNamespaces);Microsoft.AspNetCore.OpenApi.Generated</InterceptorsNamespaces>
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -31,4 +32,4 @@
<PackageReference Include="Xunit.SkippableFact" />
</ItemGroup>

</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
#if NET10_0_OR_GREATER
using Microsoft.OpenApi;
#else
using Microsoft.OpenApi.Models;
#endif
using Microsoft.OpenApi.Readers;
using System.Net;
using System.Reflection;
Expand Down Expand Up @@ -63,12 +67,20 @@ public async Task<OpenApiDocument> GetDocumentAsync()

// OpenApiDocument cannot be parsed directly with a JSON deserializer,
// as it is a midly non-normalized format that requires special rules to understand.
#if NET10_0_OR_GREATER
var result = await OpenApiDocument.LoadAsync(await openApiDoc.Content.ReadAsStreamAsync(), "json");
Assert.NotNull(result.Document);
Assert.Empty(result.Diagnostic.Errors);
Assert.Empty(result.Diagnostic.Warnings);
return result.Document;
#else
var openApiDocument = new OpenApiStreamReader()
.Read(await openApiDoc.Content.ReadAsStreamAsync(), out var diagnostic);
Assert.NotNull(openApiDocument);
Assert.Empty(diagnostic.Errors);
Assert.Empty(diagnostic.Warnings);
return openApiDocument;
#endif
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace IntelliTect.Coalesce.CodeGeneration.Tests;
public class TargetClassesFullGenerationTest : CodeGenTestBase
{
// #IF directive so this doesn't needlessly run for multiple TFMs. It only needs to run for one.
#if NET8_0
#if NET10_0
/// <summary>
/// This test isn't asserting anything in .NET land.
/// Its purpose is to produce generated files that we can build our
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../Common.props" />
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>

Expand Down
Loading