Follow us

.NET 7 Features - Part 1

By end of this year, .Net 7 about to release and currently its under preview and there many more new features and improvements to existing features which help us in doing optimized and quality development.

 

I am going through all those existing new features and improvements and will be writing multiple articles as on I learn.

Part of this first article on .Net 7 (Part 1), refer below some of features/improvements update:

 

  • File upload(Minimal API):

Earlier with Minimal api, we do not had option to allow uploading file using api, but now IFormFile, IFormFileCollection and Stream option available with .Net 7 to allow you uploading files with Minimal API.

 

/*For single file upload*/

app.MapPost("/upload-1", async (IFormFile file) =>

{

    using var stream = System.IO.File.OpenWrite($"upload1{Guid.NewGuid()}.txt");

    await file.CopyToAsync(stream);

});

 

/*Fo Mulitple files upload*/

app.MapPost("/upload-2", async (IFormFileCollection myFiles) => {

    foreach(var file in myFiles)

    {

        using var stream = System.IO.File.OpenWrite($"upload2{Guid.NewGuid()}.txt");

        await file.CopyToAsync(stream);

    }

});

 

/*IFormFile is for uploading small files, and for large files it's better to use streaming*/

app.MapPost("upload-stream-3", async (Stream body) =>

{

    using var stream = File.OpenWrite($"stream-upload3{Guid.NewGuid()}.txt");

    await body.CopyToAsync(stream);

});

 

  • Use JSON property names in validation errors

This with mvc when you validate model state and if you have json property name defined for your model field/property, then part of error list dictionary, it use that json property name.

 

Let say your model field:

[JsonPropertyName("Api.AddData.Name")]

[Required]

public string? Name { get; set; }

 

 

To enable it in startup.cs:

services.AddControllers(options =>
{
    options.ModelMetadataDetailsProviders.Add(new SystemTextJsonValidationMetadataProvider())
});

 

 

  • Minimal API - [FromServices] attribute is optional for DI

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:

 

With below example, I am having Student class with one test method and I am calling that method with the help of Student class object.

 

app.MapGet("/test-di-1", ([FromServices] Student student) => student.TestStudentMethod());

app.MapGet("/test-di-2", (Student student) => student.TestStudentMethod());

 

public class Student

    {

        public string TestStudentMethod()

        {

            return "TestStudentMethod call is successful.";

        }

    }

 

So, with above example, both will work. Earlier it was mandatory to use like first example.

 

  • Minimal API - accept array part of api request:

This is very much useful, when you don’t know the no. of values to be send/receive part of api request, so instead of defining exact number of query string, you should define as array and then read basis the array item length/count.

 

// Bind query string values to a primitive type array

// GET  /Ids-int-array?q=101&q=102

app.MapGet("/Ids-int-array", (int[] q) => $"id1: {q[0]} , id2: {q[1]}");

 

// Bind to a string array

// GET /names-string-array?names=amit&names=sumit

app.MapGet("/names-string-array", (string[] names) => $"name1: {names[0]} , name2: {names[1]}");

 

// Bind to StringValues array

// GET /names-string-value-array?names=amit&names=sumit

app.MapGet("/names-string-value-array", (StringValues names) => $"name1: {names[0]} , name2: {names[1]}");

 

// Bind to an array of a complex type like your class

// GET /students-complex-type-array?students=amit&students=sumit&students=kumit

app.MapGet("/students-complex-type-array", (Student[] students) =>

{

    return Results.Ok(tags);

});

//Student class

class Student

{

    public string? StudentName { get; init; }

 

    public static bool TryParse(string? studentName, out Student student)

    {

        if (studentName is null)

        {

            student = default;

            return false;

        }

 

        student = new Student { StudentName = studentName };

        return true;

    }

}

 

  • Shadow Copy (IIS):

Part of .net 6, this feature was experimental feature, which help you deploy/replace/override your IIS running code-base/application without making your application shutdown and this reduce to almost zero downtime.

 

In general, when you try to deploy running IIS code base, then it give you error saying, file/folder is already open and to avoid this error either you stop the IIS pool or you put app_offline.html file inside your IIS hosted application location. But in this scenario your application goes permanently down until you start your pool or you remove app_offline.html file.

 

So Microsoft had launched "experimentalEnableShadowCopy" feature which you can enable part of your application and it help you to deploy your running code base without making app pool stop or without putting app_offline.html file. Now same feature made as production feature part of .Net 7.

 

Below is the code base, how to enable it into web.config:

 

<system.webServer>

      <handlers>

        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />

      </handlers>

      <aspNetCore processPath="dotnet" arguments=".\WebApp1.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">

<handlerSettings>

          <handlerSetting name="experimentalEnableShadowCopy" value="true" />  <!--this is with .net 6-->

<!--<handlerSetting name="enableShadowCopy" value="true" />-->  <!--this is with .net 7-->

          <handlerSetting name="shadowCopyDirectory" value="../ShadowCopy_WebApp1/"  />

           </handlerSettings>

  </aspNetCore>

    </system.webServer>

 

  • Minimal API - Filters (before and after endpoint code execution).

We all know the importance of filters to track or validate something before and after our endpoint code execution and that was missing with Minimal api but now with .net 7, this is very much possible:

 

More about filter you can learn here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/min-api-filters?view=aspnetcore-7.0

 

Here with below example, I have just created one test endpoint with two filters and each filter logging information before and after code execution:

 

 

  • Minimal Api - Swagger (WithOpenApi) improvement

This allow you to adding API summary, API description and parameters description over swagger. Earlier also you could do it with the help of (Swashbuckle.AspNetCore.Annotations) but that is not much easy work.

Now with .Net 7, you can do it by:

 

 

Categories/Tags: .net 7~dotnet 7

Recent Articles

1

AWS Saving Plan - Cost optimization tips

2
3

AWS RDS Key Concepts & Why you should use it?

4
5

Open-Search/Kibana - Multi Tenancy Setup

See All Articles