Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the use of .NET 6 Minimal API?

2025-04-10 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "what is the use of .NET 6 Minimal API". In daily operation, I believe many people have doubts about the use of .NET 6 Minimal API. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts about "what is the use of .NET 6 Minimal API?" Next, please follow the editor to study!

Mode of use

Now that it is very simple, what is the simple method? I believe that students who have downloaded Visual Studio 2022 have used it to create a new ASP.NET Core 6 project, and the default mode is Minimal API mode, which makes the structure of the entire Web program look simpler. In addition, Microsoft's improvements to Lambda enable it to Attribute the Lambda parameters, and some scenarios can even give up defining Controller classes.

Build a Web program with a few lines of code

The easiest way to use Minimal API is to build a WebApi program with three lines of code, as follows

Var app = WebApplication.Create (args); app.MapGet ("/", () = > "Hello World"); app.Run ()

Yes, you read it correctly, just run it this way, the default listening http://localhost:5000 and https://localhost:5001, so you can directly enter the http://localhost:5000 address in the browser to see the browser output Hello World.

Change the listening address

If you want to change the service port it listens on, you can change it in the following way

Var app = WebApplication.Create (args); app.MapGet ("/", () = > "Hello World"); app.Run ("http://localhost:6666");"

If you want to listen to multiple ports at the same time, you can use the following methods

Var app = WebApplication.Create (args); app.Urls.Add ("http://localhost:6666");app.Urls.Add("http://localhost:8888");app.MapGet("/", () = >" Hello World "); app.Run ()

Or set the listening information directly through the environment variable, and set the value of the environment variable ASPNETCORE_URLS to the complete listening URL address, so that you can directly omit the configuration information in the program.

ASPNETCORE_URLS= http://localhost:6666

If you set multiple listening URL addresses, you can use semicolons between multiple addresses; separate multiple values

ASPNETCORE_URLS= http://localhost:6666;https://localhost:8888

If you want to listen to all local Ip addresses, you can use the following methods

Var app = WebApplication.Create (args); app.Urls.Add ("http://*:6666");app.Urls.Add("http://+:8888");app.Urls.Add("http://0.0.0.0:9999");app.MapGet("/", () = >" Hello World "); app.Run ()

Similarly, you can add a listening address by adding an environment variable

ASPNETCORE_URLS= http://*:6666;https://+:8888;http://0.0.0.0:9999 log operation

Log operation is also a common operation. Microsoft simply proposed it in Minimal API, simplifying the operation directly, as shown below.

Var builder = WebApplication.CreateBuilder (args); builder.Logging.AddJsonConsole (); var app = builder.Build (); app.Logger.LogInformation ("read configuration information: {content}", builder.Configuration.GetSection ("consul"). Get ()); app.Run (); basic environment configuration

Whether we are in the previous. Net Core development or the current. Net6 development, there is the configuration of the basic environment, including ApplicationName, ContentRootPath, EnvironmentName, but in Minimal API, it can be configured in a unified way.

Var builder = WebApplication.CreateBuilder (new WebApplicationOptions {ApplicationName = typeof (Program). Assembly.FullName, ContentRootPath = Directory.GetCurrentDirectory (), EnvironmentName = Environments.Staging}); Console.WriteLine ($"Application name: {builder.Environment.ApplicationName}"); Console.WriteLine ($"Environment variable: {builder.Environment.EnvironmentName}"); Console.WriteLine ($"ContentRoot Directory: {builder.Environment.ContentRootPath}"); var app = builder.Build ()

Or it can be configured by the way of environment variables, and the final effect is the same.

ASPNETCORE_ENVIRONMENT

ASPNETCORE_CONTENTROOT

ASPNETCORE_APPLICATIONNAME

Host related settin

In the previous Net Core development mode, programs are basically started by building hosts, such as the previous Web host or the later generic host, which can also be done in Minimal API, for example, we simulate the way the previous generic host configures the Web program

Var builder = WebApplication.CreateBuilder (args); builder.Host.ConfigureDefaults (args) .ConfigureWebHostDefaults (webBuilder = > {webBuilder.UseStartup ();}); var app = builder.Build ()

Minimal API also provides a more direct way to configure Web hosts, as shown below

Var builder = WebApplication.CreateBuilder (args); builder.WebHost.UseStartup (); builder.WebHost.UseWebRoot ("webroot"); var app = builder.Build (); default container replacement

Many times when we use IOC, we will use other three-party IOC frameworks, such as Autofac, which we are familiar with. We have previously introduced that its essential way is to use the registration of replacement containers and the provision of services in UseServiceProviderFactory. In Minimal API, you can use the following ways to operate

Var builder = WebApplication.CreateBuilder (args); builder.Host.UseServiceProviderFactory (new AutofacServiceProviderFactory ()); / / you can configure ConfigureContainer in Startup in the following ways: builder.Host.ConfigureContainer (builder = > builder.RegisterModule (new MyApplicationModule (); var app = builder.Build (); middleware related

I'm sure you've all taken a closer look at WebApplication.CreateBuilder (args). Build () builds an instance of the WebApplication class in this way, and WebApplication implements the IApplicationBuilder interface. So its essence is the same as the way we used the Configure method in Startup before, for example, we configure a Swagger program as an example.

Var builder = WebApplication.CreateBuilder (args); builder.Services.AddControllers (); builder.Services.AddEndpointsApiExplorer (); builder.Services.AddSwaggerGen (); var app = builder.Build (); / / determine the environment variable if (app.Environment.IsDevelopment ()) {/ / exception handling middleware app.UseDeveloperExceptionPage (); app.UseSwagger (); app.UseSwaggerUI ();} / enable static file app.UseStaticFiles (); app.UseAuthorization (); app.MapControllers (); app.Run ()

The commonly used middleware configuration is the same as before, because it is essentially an extension method of IApplicationBuilder, so let's briefly list it here.

Middleware name describes APIAuthentication authentication middleware app.UseAuthentication () Authorization authorization middleware .app.UseAuthorization () CORS cross-domain middleware .app.UseCors () ExceptionHandler global exception handling middleware .app.UseExceptionHandler () ForwardedHeaders proxy header message forwarding middleware. App.UseForwardedHeaders () HTTPS RedirectionHttps redirection middleware .app.UseHttpsRedirection () HTTP Strict Transport Security (HSTS) security enhancement middleware for special response headers. App.UseHsts () Request LoggingHTTP please Sum response log middleware .app.UseHttpLogging () ResponseCaching output cache middleware .app.UseResponseCaching () ResponseCompression response compression middleware .app.UseResponseCompression () SessionSession middleware app.UseSession () StaticFiles static file middleware .app.UseStatic Files () App.UseFileServer () WebSocketsWebSocket supports middleware .app.UseWebSockets () request processing

We can use Map {HTTPMethod}-related extension methods in WebApplication to handle different Http requests, such as Get, Post, Put, Delete-related requests in the following example

App.MapGet ("/", () = > "Hello GET"); app.MapPost ("/", () = > "Hello POST"); app.MapPut ("/", () = > "Hello PUT"); app.MapDelete ("/", () = > "Hello DELETE")

If you want a routed address to handle requests with multiple Http methods, you can use the MapMethods method, as follows

App.MapMethods ("/ multiple", new [] {"GET", "POST", "PUT", "DELETE"}, (HttpRequest req) = > $"Current Http Method Is {req.Method}")

From the above example, we not only see how to handle different Http requests, but also see that Minimal Api can infer how to handle requests according to the type of delegate. For example, in the above example, we do not write Response Write-related code, but the output is the content of the delegate. Because all the delegates in our above example are in the form of Func, Minimal Api automatically processes and outputs the returned information. In fact, as long as it satisfies the delegate type, it can be dealt with. Let's make it simple. First of all, it is the form of the local function.

Static string LocalFunction () = > "This is local function"; app.MapGet ("/ local-fun", LocalFunction)

It can also be an instance method of a class

HelloHandler helloHandler = new HelloHandler (); app.MapGet ("/ instance-method", helloHandler.Hello); class HelloHandler {public string Hello () {return "Hello World";}}

Or the static method of the class

App.MapGet ("/ static-method", HelloHandler.SayHello); class HelloHandler {public static string SayHello (string name) {return $"Hello {name}";}}

In fact, the essence is the same, that is to convert them into executable delegates, no matter what kind of form, can meet the conditions of the commission.

Routing constraint

Minimal Api also supports constraints on routing rules, which is similar to the way we used UseEndpoints before. For example, I restrict that routing parameters can only be integers, and return 404 if not satisfied.

App.MapGet ("/ users/ {userId:int}", (int userId) = > $"user id is {userId}"); app.MapGet ("/ user/ {name:length (20)}", (string name) = > $"user name is {name}")

There are several other routing constraints that are often used, but not many of them are as follows. Simply list the table.

Limit example matching example shows that int {id:int} 123456789,-123456789 matches any integer bool {active:bool} true, and false matches true or false. Ignore case datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm match values of type DateTime decimal {price:decimal} 49.99,-1000.01 match values of type decimal double {height:double} 1.234,-100.101 billion match values of type double float {height:float} 1.234 -100.101 billion match values of type float guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638 match values of type Guid long {ticks:long} 123456789 -123456789 match values of type long minlength (value) {username:minlength (4)} KOBE string length must be 4 characters maxlength (value) {filename:maxlength (8)} CURRY string length cannot exceed 8 characters length (length) {filename:length (12)} somefile.txt string character length must be 12 characters length (min Max) {filename:length (8p16)} somefile.txt string must be between 8 and L6 min (value) {age:min (18)} 20 integer value must be greater than 18max (value) {age:max (120)} 119integer value must be less than 120range (min,max) {age:range (18120)} 100integer value must be between 18 and 120.The alpha {name:alpha} Rick string must consist of one or more alphabetic characters of axiz. And case-insensitive. Regex (expression) {ssn:regex (^\\ d {{3}} -\ d {{2}} -\ d {4}} $)} 123-45-6789 string must match the specified regular expression. The required {name:required} JAMES request information must contain the parameter model binding

Before we used ASP.NET Core Controller development, model binding will certainly be used, its purpose is to simplify our parsing Http request information is also the core function of the MVC framework, it can directly map the request information to the simple type of c # or POCO above. Rich model binding operations can also be performed in Minimal Api's Map {HTTPMethod} related methods. At present, several binding sources can be supported.

Route (routing parameters)

QueryString

Header

Body (such as JSON)

Services (that is, types registered through IServiceCollection)

Custom binding

Binding example

Next, let's first take a look at the binding routing parameters.

App.MapGet ("/ sayhello/ {name}", (string name) = > $"Hello {name}")

You can also use a mix of routing and querystring

App.MapGet ("/ sayhello/ {name}", (string name,int? Age) = > $"my name is {name}, age {age}")

It should be noted here that my age parameter is marked with a nullable flag. If it is not added, the age parameter must be passed in the request parameter of url, otherwise an error will be reported, which is different from our previous operation.

Specific classes can also be bound to the model. For example, we define a POCO named Goods here for demonstration.

App.MapPost ("/ goods", (Goods goods) = > $"goods {goods.GName} added successfully"); class Goods {public int GId {get; set;} public string GName {get; set;} public decimal Price {get; set;}}

It is important to note that the HTTP methods GET, HEAD, OPTIONS, DELETE will not bind the model from body, and if you need to get the Body information in the Get request, you can read it directly from the HttpRequest.

If we need to use a concrete instance registered through IServiceCollection, we can operate through model binding (many people like to call it method injection, but strictly speaking, it is achieved by defining the related operations of model binding), and it also simplifies the specific operation, we do not need to do FromServicesAttribute tags on specific parameters.

Var builder = WebApplication.CreateBuilder (args); builder.Services.AddScoped (provider = > new () {Id = 1, Name = "between yi", Sex = "Man"}); var app = builder.Build (); app.MapGet ("/", (Person person) = > $"Hello {person.Name}!"); app.Run ()

If it is mixed, you can also mark it without specifying a specific BindSource, as long as the names of these values are unique among different binding sources, which reminds me of the arbitrariness of model binding when I first started learning MVC4.0, such as the following example

App.MapGet ("/ sayhello/ {name}", (string name,int? Age,Person person) = > $"my name is {name}, age {age}, sex {person.Sex}")

The source of the model binding parameters for the above example can be

Parameter binding source name routing parameter agequerystringperson dependency injection

Not only that, it also supports more complex ways, which makes model binding more flexible, such as the following example

App.MapPost ("/ goods", (Goods goods, Person person) = > $"{person.Name} added goods {goods.GName} successfully")

The value source of its model binding can be

Jsonperson dependency injection in the parameter binding source goodsbody

Of course, if you want to make the source of the model binding clearer, or if you just want to specify the binding source of specific parameters, it's fine, anyway, it's flexible, such as the example above, so that the declaration can be displayed.

App.MapPost ("/ goods", ([FromBody] Goods goods, [FromServices] Person person) = > $"{person.Name} added goods {goods.GName} successfully")

In many cases, we may declare the execution delegation of Map-related methods by defining classes and methods. At this time, we can still perform flexible model binding, and you may have found that although nullable types are supported directly through lambda expressions, it does not support default parameters, that is, the form of method default parameters, such as

App.MapPost ("/ goods", GoodsHandler.AddGoods); class GoodsHandler {public static string AddGoods (Goods goods, Person person, int age = 20) = > $"{person.Name} added goods {goods.GName} succeeded";}

Of course, you can also display the model binding of the parameters of the AddGoods method, which is really very flexible

Public static string AddGoods ([FromBody] Goods goods, [FromServices] Person person, [FromQuery] int age = 20) = > $"{person.Name} added goods {goods.GName} successfully"

When using Map-related methods, because the relevant logic is written directly in the Program entry program or other POCO, it is impossible to operate directly when you need to use the relevant instances of HttpContext, HttpRequest and HttpResponse. At this time, you also need to obtain the corresponding instances through model binding.

App.MapGet ("/ getcontext", (HttpContext context,HttpRequest request,HttpResponse response) = > response.WriteAsync ($"IP: {context.Connection.RemoteIpAddress}, Request Method: {request.Method}")); Custom binding

Minimal Api uses a new way to customize model bindings, which is a convention-based approach without registering in advance, integrating classes or implementing interfaces, but only needs to have TryParse and BindAsync methods in the custom class. the difference between the two methods is

The TryParse method converts and binds routing parameters, url parameters, and header-related information.

BindAsync can transform and bind any requested information, which is more powerful than TryParse.

Next, let's demonstrate the use of these two methods, first of all, the TryParse method.

App.MapGet ("/ address/getarray", (Address address) = > address.Addresses); public class Address {public List? Addresses {get; set;} public static bool TryParse (string? AddressStr, IFormatProvider? Provider, out Address? Address) {var addresses = addressStr?.Split (',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); if (addresses! = null & & addresses.Any ()) {address = new Address {Addresses = addresses.ToList ()}; return true;} address = new Address (); return false;}}

In this way, we can complete the simple conversion binding operation. From the writing, we can see that the TryParse method does have some limitations, but it is relatively simple to operate. At this time, we simulate the request.

Http://localhost:5036/address/getarray?address= Shandong, Shanxi, Henan, Hebei

When the request is completed, you will get the following result

["Shandong", "Shanxi", "Henan", "Hebei"]

Then let's modify the above example to convert the results using BindAsync to see how they operate differently.

App.MapGet ("/ address/getarray", (Address address) = > address.Addresses); public class Address {public List? Addresses {get; set;} public static ValueTask BindAsync (HttpContext context, ParameterInfo parameter) {string addressStr = context.Request.Query ["address"]; var addresses = addressStr?.Split (',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); Address address = new (); if (addresses! = null & & addresses.Any ()) {address.Addresses = addresses.ToList (); return ValueTask.FromResult (address) } return ValueTask.FromResult (address);}}

The same request http://localhost:5036/address/getarray?address= Shandong, Shanxi, Henan, Hebei address will get the same results as above, in the end how to choose students can be used on demand, the results are all the same. If both TryParse and BindAsync methods exist in the class, only the BindAsync method is executed.

Output result

I believe that through the other examples above, we have probably seen some of the result output in Minimal Api, which can be divided into three situations.

IResult result output, which can contain any worthy output, including asynchronous tasks

Task and ValueTaskstring text type output, including asynchronous tasks

Output of Task and ValueTaskT object types, such as custom entities, anonymous objects, etc., including asynchronous tasks Task and ValueTask

Next, we will briefly demonstrate a few examples to take a brief look at how it works. First of all, the simplest one is to output text types.

App.MapGet ("/ hello", () = > "Hello World")

Then output an object type, which can contain objects or collections or even anonymous objects, or the HttpResponse object we demonstrated above, where the object can be understood as an object-oriented object that meets the Response output requirements.

App.MapGet ("/ simple", () = > new {Message = "Hello World"}); / / or app.MapGet ("/ array", () = > new string [] {"Hello", "World"}); / / or the returned result app.Map of EF ("/ student", (SchoolContext dbContext,int classId) = > dbContext.Student.Where (I = > i.ClassId==classId))

There is also a form that Microsoft encapsulates for us, that is, it returns the result of IResult type. Microsoft is also very sweet to encapsulate a static Results class for us, which is convenient for us to use and briefly demonstrate this operation.

/ / success result app.MapGet ("/ success", () = > Results.Ok ("Success")); / / failure result app.MapGet ("/ fail", () = > Results.BadRequest ("fail")); / / 404 result app.MapGet ("/ 404", () = > Results.NotFound ()); / / return app.Map according to logical judgment ("/ student", (SchoolContext dbContext, int classId) = > {var classStudents = dbContext.Student.Where (I = > i.ClassId = = classId) Return classStudents.Any ()? Results.Ok (classStudents): Results.NotFound ()})

We also mentioned above that the results class is actually an extra layer encapsulated by Microsoft. All the static methods in it are interface instances that return IResult. This interface has many implemented classes that satisfy different output results. For example, the essence of the Results.File ("foo.text") method is to return an instance of type FileContentResult.

Public static IResult File (byte [] fileContents,string? ContentType = null,string? FileDownloadName = null,bool enableRangeProcessing = false,DateTimeOffset? LastModified = null,EntityTagHeaderValue? EntityTag = null) = > new FileContentResult (fileContents, contentType) {FileDownloadName = fileDownloadName, EnableRangeProcessing = enableRangeProcessing, LastModified = lastModified, EntityTag = entityTag,}

Or Results.Json (new {Message= "Hello World"}) essentially returns an instance of type JsonResult

Public static IResult Json (object? Data, JsonSerializerOptions? Options = null, string? ContentType = null, int? StatusCode = null) = > new JsonResult {Value = data, JsonSerializerOptions = options, ContentType = contentType, StatusCode = statusCode,}

Of course, we can also customize the instance of IResult, for example, we want to output a piece of html code. Microsoft is very sweet to provide us with an extension class IResultExtensions that specifically extends Results. Based on this class, we can complete the extension of IResult.

Static class ResultsExtensions {/ / write extension method public static IResult Html (this IResultExtensions resultExtensions, string html) {ArgumentNullException.ThrowIfNull (resultExtensions, nameof (resultExtensions)) based on IResultExtensions; / / Custom HtmlResult is the implementation class return new HtmlResult (html) of IResult;}} class HtmlResult:IResult {/ / is used to receive the html string private readonly string _ html; public HtmlResult (string html) {_ html = html } / public Task ExecuteAsync (HttpContext httpContext) {httpContext.Response.ContentType = MediaTypeNames.Text.Html; httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount (_ html); return httpContext.Response.WriteAsync (_ html);}}

After defining these, we can use the extension methods we defined directly in the Results class, as follows

App.MapGet ("/ hello/ {name}", (string name) = > Results.Extensions.Html (@ $"Index Hello {name}"))

It is important to note that our custom extension method must be based on the IResultExtensions extension, and then pay attention to the use of the Results.Extensions attribute, because this property is of type IResultExtensions, and then our own extended Results.Extensions.Html method.

At this point, the study on "what is the use of .NET 6 Minimal API" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report