ASP.NET Core updates in .NET 7 Preview 2

.NET 7 Preview 2 is now available and includes many great new improvements to ASP.NET Core.

Here’s a summary of what’s new in this preview release:

Infer API controller action parameters that come from services
Dependency injection for SignalR hub methods
Provide endpoint descriptions and summaries for minimal APIs
Binding arrays and StringValues from headers and query strings in minimal APIs
Customize the cookie consent value

For more details on the ASP.NET Core work planned for .NET 7 see the full ASP.NET Core roadmap for .NET 7 on GitHub.

Get started

To get started with ASP.NET Core in .NET 7 Preview 2, install the .NET 7 SDK.

If you’re on Windows using Visual Studio, we recommend installing the latest Visual Studio 2022 preview. Visual Studio for Mac support for .NET 7 previews isn’t available yet but is coming soon.

To install the latest .NET WebAssembly build tools, run the following command from an elevated command prompt:

dotnet workload install wasm-tools

Upgrade an existing project

To upgrade an existing ASP.NET Core app from .NET 7 Preview 1 to .NET 7 Preview 2:

Update all Microsoft.AspNetCore.* package references to 7.0.0-preview.2.*.
Update all Microsoft.Extensions.* package references to 7.0.0-preview.2.*.

See also the full list of breaking changes in ASP.NET Core for .NET 7.

Infer API controller action parameters that come from services

Parameter binding for API controller actions now binds parameters through dependency injection when the type is configured as a service. This means it’s no longer required to explicitly apply the [FromServices] attribute to a parameter.

Services.AddScoped<SomeCustomType>();

[Route(“[controller]”)]
[ApiController]
public class MyController : ControllerBase
{
// Both actions will bound the SomeCustomType from the DI container
public ActionResult GetWithAttribute([FromServices]SomeCustomType service) => Ok();
public ActionResult Get(SomeCustomType service) => Ok();
}

You can disable the feature by setting DisableImplicitFromServicesParameters:

Services.Configure<ApiBehaviorOptions>(options =>
{
options.DisableImplicitFromServicesParameters = true;
})

Dependency injection for SignalR hub methods

SignalR hub methods now support injecting services through dependency injection (DI).

Services.AddScoped<SomeCustomType>();

public class MyHub : Hub
{
// SomeCustomType comes from DI by default now
public Task Method(string text, SomeCustomType type) => Task.CompletedTask;
}

You can disable the feature by setting DisableImplicitFromServicesParameters:

services.AddSignalR(options =>
{
options.DisableImplicitFromServicesParameters = true;
});

To explicitly mark a parameter to be bound from configured services, use the [FromServices] attribute:

public class MyHub : Hub
{
public Task Method(string arguments, [FromServices] SomeCustomType type);
}

Provide endpoint descriptions and summaries for minimal APIs

Minimal APIs now support annotating operations with descriptions and summaries used for OpenAPI spec generation. You can set these descriptions and summaries for route handlers in your minimal API apps using an extension methods:

app.MapGet(“/hello”, () => …)
.WithDescription(“Sends a request to the backend HelloService to process a greeting request.”);

Or set the description or summary via attributes on the route handler delegate:

app.MapGet(“/hello”, [EndpointSummary(“Sends a Hello request to the backend”)]() => …)

Binding arrays and StringValues from headers and query strings in minimal APIs

With this release, you can now bind values from HTTPS headers and query strings to arrays of primitive types, string arrays, or StringValues:

// Bind query string values to a primitive type array
// GET /tags?q=1&q=2&q=3
app.MapGet(“/tags”, (int[] q) => $”tag1: {q[0]} , tag2: {q[1]}, tag3: {q[2]}”)

// Bind to a string array
// GET /tags?names=john&names=jack&names=jane
app.MapGet(“/tags”, (string[] names) => $”tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}”)

// Bind to StringValues
// GET /tags?names=john&names=jack&names=jane
app.MapGet(“/tags”, (StringValues names) => $”tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}”)

You can also bind query strings or header values to an array of a complex type as long as the type has TryParse implementation as demonstrated in the example below.

// Bind to aan array of a complex type
// GET /tags?tags=trendy&tags=hot&tags=spicy
app.MapGet(“/tags”, (Tag[] tags) =>
{
return Results.Ok(tags);
});

class Tag
{
public string? TagName { get; init; }

public static bool TryParse(string? tagName, out Tag tag)
{
if (tagName is null)
{
tag = default;
return false;
}

tag = new Tag { TagName = tagName };
return true;
}
}

Customize the cookie consent value

You can now specify the value used to track if the user consented to the cookie use policy using the new CookiePolicyOptions.ConsentCookieValue property.

Thank you @daviddesmet for contributing this improvement!

Request for feedback on shadow copying for IIS

In .NET 6 we added experimental support for shadow copying app assemblies to the ASP.NET Core Module (ANCM) for IIS. When an ASP.NET Core app is running on Windows, the binaries are locked so that they cannot be modified or replaced. You can stop the app by deploying an app offline file, but sometimes doing so is inconvenient or impossible. Shadow copying enables the app assemblies to be updated while the app is running by making a copy of the assemblies.

You can enable shadow copying by customizing the ANCM handler settings in web.config:

<?xml version=”1.0″ encoding=”utf-8″?>
<configuration>
<system.webServer>
<handlers>
<remove name=”aspNetCore”/>
<add name=”aspNetCore” path=”*” verb=”*” modules=”AspNetCoreModuleV2″ resourceType=”Unspecified”/>
</handlers>
<aspNetCore processPath=”%LAUNCHER_PATH%” arguments=”%LAUNCHER_ARGS%” stdoutLogEnabled=”false” stdoutLogFile=”.logsstdout”>
<handlerSettings>
<handlerSetting name=”experimentalEnableShadowCopy” value=”true” />
<handlerSetting name=”shadowCopyDirectory” value=”../ShadowCopyDirectory/” />
</handlerSettings>
</aspNetCore>
</system.webServer>
</configuration>

We’re investigating making shadow copying in IIS a feature of ASP.NET Core in .NET 7, and we’re seeking additional feedback on whether the feature satisfies user requirements. If you deploy ASP.NET Core to IIS, please give shadow copying a try and share with us your feedback on GitHub.

Give feedback

We hope you enjoy this preview release of ASP.NET Core in .NET 7. Let us know what you think about these new improvements by filing issues on GitHub.

Thanks for trying out ASP.NET Core!

The post ASP.NET Core updates in .NET 7 Preview 2 appeared first on .NET Blog.

Flatlogic Admin Templates banner

Bringing a little slice of Developer Tools to Seq in 2022.1

If your experience is anything like mine, debugging in production is as much about organizing information – clues, leads, sometimes frustrating dead-ends – as it is about unearthing it. Working through an issue, I need pen and paper, sticky notes, whiteboards and spreadsheets as much as I depend on searching logs.

Seq is never going to replace my favorite Lamy pen (a chrome Pico I’ve hung onto for absolutely years ?), but in 2022.1 there are two small improvements coming that should help with the information overload:

Variables as an alternative to copy-and-paste for keeping track of useful values, and
A redesigned (and searchable!) history makes it easier to jump back to an earlier search or query.

Search history doesn’t need much explanation (it’s now a tool window you can pop out in the signal bar), but variables are actually pretty interesting.

When GUIDs start to look alike…

The basic scenario looks like this:

Why does request cbc6f181ba66498092c78bdd4106e3f1 time out, while request c43df41457dd443a83f1bcf94353a3c7 succeeds?

Instead of copying those values back and forth to a text editor window, inevitably forgetting which is on the clipboard at any given moment, Seq 2022.1 supports assigning them to variable names:

select ‘cbc6f181ba66498092c78bdd4106e3f1’ into $failingRequest

You can use the resulting variable names in any expression where you would otherwise use the value:

The design of variables in Seq takes inspiration from the ubiquitous browser developer tools console: variables are somewhere to stash and inspect useful pieces of information while you work on a problem.

This could be a little confusing if you were expecting variables to behave more like those in procedural languages such as Transact-SQL or PL/pgSQL. Seq doesn’t support procedural programming, so there’s no way to, say, reassign a variable on each iteration of a loop. If you’re here looking for something along those lines, check out let bindings instead.

Quick variables

The green check-mark menu beside event properties can now be used to assign the value of a property to a new variable:

Seq will generate a variable name based on the property name. Variables can’t be directly renamed, but you can give a variable a more meaningful name by selecting its value into a new one:

select $requestId0 into $slowRequest

Variables in signals, alerts, and dashboards

Variables are tracked client-side, and passed back to the server by the Seq UI whenever they appear in a search or query. The value you assign to a variable doesn’t live any longer than your browser session.

This means that variable values aren’t available when signals are indexed, when alerts are checked, or when your dashboard is rendered on an overhead display. To avoid silently failing with incorrect results, Seq will reject all variable references that appear in these places:

Wrapping up the tour

So that’s it! Variables are a simple feature, but also part of an exciting direction that we’re going to explore further.

You can find out more about variables – the scenarios we’ve thought about, and some of the implementation details – in the Variables RFC.

Or, to jump in and try them against your next production debugging puzzle, pull the datalust/seq:preview Docker image, or download the 2022.1.*-pre MSI from the Seq downloads page. We can’t wait to hear how you go!

Flatlogic Admin Templates banner