Skip to content

Commit bbe7fd6

Browse files
authored
Primary ctors (#34858)
1 parent 8825f36 commit bbe7fd6

File tree

11 files changed

+136
-20
lines changed

11 files changed

+136
-20
lines changed

aspnetcore/blazor/security/includes/usermanager-signinmanager.md

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ services.Configure<IdentityOptions>(options =>
3030
The following `WeatherForecastController` logs the <xref:Microsoft.AspNetCore.Identity.IdentityUser%601.UserName> when the `Get` method is called.
3131

3232
> [!NOTE]
33-
> The following example uses a [file-scoped namespace](/dotnet/csharp/language-reference/keywords/namespace), which is a C# 10 or later (.NET 6 or later) feature.
33+
> The following example uses:
34+
>
35+
> * A [file-scoped namespace](/dotnet/csharp/language-reference/keywords/namespace), which is a C# 10 or later (.NET 6 or later) feature.
36+
> * A [primary constructor](/dotnet/csharp/whats-new/tutorials/primary-constructors), which is a C# 12 or later (.NET 8 or later) feature.
3437
3538
```csharp
3639
using System;
@@ -49,25 +52,15 @@ namespace BlazorSample.Server.Controllers;
4952
[Authorize]
5053
[ApiController]
5154
[Route("[controller]")]
52-
public class WeatherForecastController : ControllerBase
55+
public class WeatherForecastController(ILogger<WeatherForecastController> logger,
56+
UserManager<ApplicationUser> userManager) : ControllerBase
5357
{
54-
private readonly UserManager<ApplicationUser> userManager;
55-
5658
private static readonly string[] Summaries = new[]
5759
{
5860
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm",
5961
"Balmy", "Hot", "Sweltering", "Scorching"
6062
};
6163

62-
private readonly ILogger<WeatherForecastController> logger;
63-
64-
public WeatherForecastController(ILogger<WeatherForecastController> logger,
65-
UserManager<ApplicationUser> userManager)
66-
{
67-
this.logger = logger;
68-
this.userManager = userManager;
69-
}
70-
7164
[HttpGet]
7265
public async Task<IEnumerable<WeatherForecast>> Get()
7366
{

aspnetcore/fundamentals/aot/request-delegate-generator/rdg.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
---
2-
32
title: ASP.NET Core Request Delegate Generator (RDG) for Native AOT
43
description: Turn Map methods into request delegates with the ASP.NET Core Request Delegate Generator (RDG) for Native AOT.
54
author: rick-anderson
@@ -48,7 +47,17 @@ The RDG:
4847
* Is enabled automatically in projects when publishing with Native AOT is enabled or when trimming is enabled.
4948
* Can be manually enabled even when not using Native AOT by setting `<EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>` in the project file:
5049

51-
:::code language="xml" source="~/fundamentals/aot/samples/rdg/RDG.csproj" highlight="7":::
50+
:::moniker range=">= aspnetcore-10.0"
51+
52+
:::code language="xml" source="~/fundamentals/aot/samples/10.0/rdg/RDG.csproj" highlight="7":::
53+
54+
:::moniker-end
55+
56+
:::moniker range="< aspnetcore-10.0"
57+
58+
:::code language="xml" source="~/fundamentals/aot/samples/8.0/rdg/RDG.csproj" highlight="7":::
59+
60+
:::moniker-end
5261

5362
Manually enabling RDG can be useful for:
5463

@@ -57,7 +66,17 @@ Manually enabling RDG can be useful for:
5766

5867
Minimal APIs are optimized for using <xref:System.Text.Json>, which requires using the [System.Text.Json source generator](/dotnet/standard/serialization/system-text-json/source-generation). All types accepted as parameters to or returned from request delegates in Minimal APIs must be configured on a <xref:System.Text.Json.Serialization.JsonSerializerContext> that's registered via ASP.NET Core's dependency injection:
5968

60-
:::code language="csharp" source="~/fundamentals/aot/samples/rdg/Program.cs" highlight="5-9,32-99":::
69+
:::moniker range=">= aspnetcore-10.0"
70+
71+
:::code language="csharp" source="~/fundamentals/aot/samples/10.0/rdg/Program.cs" highlight="5-9,34-36":::
72+
73+
:::moniker-end
74+
75+
:::moniker range="< aspnetcore-10.0"
76+
77+
:::code language="csharp" source="~/fundamentals/aot/samples/8.0/rdg/Program.cs" highlight="5-9,32-35":::
78+
79+
:::moniker-end
6180

6281
## Diagnostics for unsupported RDG scenarios
6382

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Text.Json.Serialization;
2+
3+
var builder = WebApplication.CreateSlimBuilder(args);
4+
5+
builder.Services.ConfigureHttpJsonOptions(options =>
6+
{
7+
options.SerializerOptions.TypeInfoResolverChain.Insert(
8+
0, AppJsonSerializerContext.Default);
9+
});
10+
11+
var app = builder.Build();
12+
13+
Todo[] sampleTodos =
14+
[
15+
new(1, "Walk the dog"),
16+
new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
17+
new(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
18+
new(4, "Clean the bathroom"),
19+
new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2)))
20+
];
21+
22+
var todosApi = app.MapGroup("/todos");
23+
todosApi.MapGet("/", () => sampleTodos);
24+
todosApi.MapGet("/{id}", (int id) =>
25+
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
26+
? Results.Ok(todo)
27+
: Results.NotFound());
28+
29+
app.Run();
30+
31+
public record Todo(int Id, string? Title, DateOnly? DueBy = null, bool IsComplete = false);
32+
33+
[JsonSerializable(typeof(Todo[]))]
34+
internal partial class AppJsonSerializerContext : JsonSerializerContext
35+
{
36+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>
8+
</PropertyGroup>
9+
10+
</Project>

aspnetcore/fundamentals/aot/samples/rdg/Program.cs renamed to aspnetcore/fundamentals/aot/samples/8.0/rdg/Program.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,4 @@ public record Todo(int Id, string? Title, DateOnly? DueBy = null, bool IsComplet
3232
[JsonSerializable(typeof(Todo[]))]
3333
internal partial class AppJsonSerializerContext : JsonSerializerContext
3434
{
35-
3635
}

aspnetcore/fundamentals/aot/samples/Program.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,4 @@
2525
[JsonSerializable(typeof(Todo[]))]
2626
internal partial class AppJsonSerializerContext : JsonSerializerContext
2727
{
28-
2928
}

aspnetcore/grpc/aspnetcore.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,31 @@ For more information about using the `Microsoft.AspNetCore.App` framework refere
153153

154154
## Integration with ASP.NET Core APIs
155155

156-
gRPC services have full access to the ASP.NET Core features such as [Dependency Injection](xref:fundamentals/dependency-injection) (DI) and [Logging](xref:fundamentals/logging/index). For example, the service implementation can resolve a logger service from the DI container via the constructor:
156+
gRPC services have full access to the ASP.NET Core features such as [dependency injection](xref:fundamentals/dependency-injection) (DI) and [logging](xref:fundamentals/logging/index). For example, the service implementation can resolve a logger service from the DI container.
157+
158+
Constructor injection:
157159

158160
```csharp
159161
public class GreeterService : Greeter.GreeterBase
160162
{
163+
private readonly ILogger<GreeterService> _logger;
164+
161165
public GreeterService(ILogger<GreeterService> logger)
162166
{
167+
_logger = logger;
163168
}
164169
}
165170
```
166171

172+
Primary constructor injection (.NET 8 or later):
173+
174+
```csharp
175+
public class GreeterService(ILogger<GreeterService> logger) : Greeter.GreeterBase
176+
{
177+
...
178+
}
179+
```
180+
167181
By default, the gRPC service implementation can resolve other DI services with any lifetime (Singleton, Scoped, or Transient).
168182

169183
### Resolve HttpContext in gRPC methods

aspnetcore/grpc/index.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ uid: grpc/index
1414
By [James Newton-King](https://twitter.com/jamesnk)
1515

1616
:::moniker range=">= aspnetcore-6.0"
17+
1718
[gRPC](https://grpc.io) is a language agnostic, high-performance Remote Procedure Call (RPC) framework.
1819

1920
The main benefits of gRPC are:
@@ -73,6 +74,30 @@ gRPC requires the [Grpc.AspNetCore](https://www.nuget.org/packages/Grpc.AspNetCo
7374

7475
The **ASP.NET Core gRPC Service** project template provides a starter service:
7576

77+
:::moniker-end
78+
79+
:::moniker range=">= aspnetcore-10.0"
80+
81+
```csharp
82+
public class GreeterService(ILogger<GreeterService> logger) : Greeter.GreeterBase
83+
{
84+
public override Task<HelloReply> SayHello(HelloRequest request,
85+
ServerCallContext context)
86+
{
87+
logger.LogInformation("Saying hello to {Name}", request.Name);
88+
89+
return Task.FromResult(new HelloReply
90+
{
91+
Message = "Hello " + request.Name
92+
});
93+
}
94+
}
95+
```
96+
97+
:::moniker-end
98+
99+
:::moniker range=">= aspnetcore-6.0 < aspnetcore-10.0"
100+
76101
```csharp
77102
public class GreeterService : Greeter.GreeterBase
78103
{
@@ -87,6 +112,7 @@ public class GreeterService : Greeter.GreeterBase
87112
ServerCallContext context)
88113
{
89114
_logger.LogInformation("Saying hello to {Name}", request.Name);
115+
90116
return Task.FromResult(new HelloReply
91117
{
92118
Message = "Hello " + request.Name
@@ -95,6 +121,10 @@ public class GreeterService : Greeter.GreeterBase
95121
}
96122
```
97123

124+
:::moniker-end
125+
126+
:::moniker range=">= aspnetcore-6.0"
127+
98128
`GreeterService` inherits from the `GreeterBase` type, which is generated from the `Greeter` service in the `.proto` file. The service is made accessible to clients in `Program.cs`:
99129

100130
```csharp
@@ -132,6 +162,7 @@ For more information on creating clients, and calling different service methods,
132162
:::moniker-end
133163

134164
:::moniker range=">= aspnetcore-3.0 < aspnetcore-6.0"
165+
135166
[gRPC](https://grpc.io) is a language agnostic, high-performance Remote Procedure Call (RPC) framework.
136167

137168
The main benefits of gRPC are:

aspnetcore/grpc/migration.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,31 @@ For more information on configuration, see <xref:grpc/configuration>.
8686

8787
## Logging
8888

89-
C-core-based apps rely on the `GrpcEnvironment` to [configure the logger](https://grpc.io/grpc/csharp/api/Grpc.Core.GrpcEnvironment.html?q=size#Grpc_Core_GrpcEnvironment_SetLogger_Grpc_Core_Logging_ILogger_) for debugging purposes. The ASP.NET Core stack provides this functionality through the [Logging API](xref:fundamentals/logging/index). For example, a logger can be added to the gRPC service via constructor injection:
89+
C-core-based apps rely on the `GrpcEnvironment` to [configure the logger](https://grpc.io/grpc/csharp/api/Grpc.Core.GrpcEnvironment.html?q=size#Grpc_Core_GrpcEnvironment_SetLogger_Grpc_Core_Logging_ILogger_) for debugging purposes. The ASP.NET Core stack provides this functionality through the [Logging API](xref:fundamentals/logging/index). For example, a logger can be added to the gRPC service.
90+
91+
Constructor injection:
9092

9193
```csharp
9294
public class GreeterService : Greeter.GreeterBase
9395
{
96+
private readonly ILogger<GreeterService> _logger;
97+
9498
public GreeterService(ILogger<GreeterService> logger)
9599
{
100+
_logger = logger;
96101
}
97102
}
98103
```
99104

105+
Primary constructor injection (.NET 8 or later):
106+
107+
```csharp
108+
public class GreeterService(ILogger<GreeterService> logger) : Greeter.GreeterBase
109+
{
110+
...
111+
}
112+
```
113+
100114
For more information on gRPC logging and diagnostics, see <xref:grpc/diagnostics>.
101115

102116
## HTTPS

0 commit comments

Comments
 (0)