问题描述
我见过很多使用默认 AddMvc()
服务的 ASP.NET Core Web API 项目,却没有意识到使用 AddMvcCore()
是一种优越的服务由于对服务的控制而选择.
究竟如何使用 AddMvcCore()
实现 ASP.NET Core Web API 以及为什么更好?
AddMvc()
和AddMvcCore()
有什么区别?
首先要了解的是AddMvc()
只是AddMvcCore()
的预加载版本.您可以在
您可以在 Microsoft 文档中了解更多信息:ASP.NET核心中间件基础知识
I've seen a lot of ASP.NET Core Web API projects that use the default AddMvc()
service without the realizing that using AddMvcCore()
is a superior option due to the control over services.
How exactly do you implement an ASP.NET Core Web API by using AddMvcCore()
and why is it better?
What is the difference between AddMvc()
and AddMvcCore()
?
The first thing key thing to understand is that AddMvc()
is just a pre-loaded version of AddMvcCore()
. You can see the exact implementation of the AddMvc()
extension at the GitHub repository.
I like using default VS templates as much as the next guy, but sometimes you need to know when it's the wrong choice. I have seen several guides online that lean more towards an attempt to "undo" these default services rather than just going with a solution that just does not implement them in the first place.
With the advent of ASP.NET Core being open source, there really isn't a good reason why we can't peel back a layer and work at a lower level without fear of losing "magic".
Definition of "minimal" and "pure"
Note: The definitions are intended for the context of this answer only. Mostly for the sake of clarity and assisting in further understanding.
This answer leans more towards "pure" and not "minimal". I'd like to describe why, so it's clearer what I'm talking about.
Minimal. A "minimal" solution would be an implementation that does not even call upon the AddMvcCore()
method at all. The reason for this, is that MVC is not really a "required" component to assembling you own Web API, and it certainly adds some weight to your code with the additional dependencies. In this scenario, since you're not using the AddMvcCore()
method, you also would not inject it into your application, here
public void Configure(IApplicationBuilder app)
{
app.UseMvc(); // you don't need this
}
This would mean mapping your own routes and responding to the context
in your own way. This really isn't challenging at all, but I don't want to dive into it, because it's quite off-topic, but here is a tiny taste of a minimal implementation:
public void Configure(IApplicationBuilder app)
{
app.Map("/api", HandleMapApi);
// notice how we don't have app.UseMvc()?
}
private static void HandleMapApi(IApplicationBuilder app)
{
app.Run(async context =>
{
// implement your own response
await context.Response.WriteAsync("Hello WebAPI!");
});
}
For many projects, a "minimal" approach means we are giving up some of the features found in MVC. You would really have to weigh your options and see if you this design path is the right choice, as there is a balance between design pattern, convenience, maintainability, code footprint, and most importantly performance and latency. Simply put: a "minimal" solution would mean minimizing the services and middleware between your code and the request.
Pure. A "pure" solution (as far as the context of this answer) is to avoid all the default services and middleware that come "pre-bundled" with AddMvc()
by not implementing it in the first place. Instead, we use AddMvcCore()
, which is explained further in the next section:
Implementing our own services / middleware with AddMvcCore()
The first thing to get started is to setup ConfigureServices
to using AddMvcCore()
. If you look at the GitHub repository, you can see that AddMvc()
calls AddMvcCore()
with a standard set of services / middleware:
Here are some of the services / middleware that stands out as "unneeded":
var builder = services.AddMvcCore(); builder.AddViews(); builder.AddRazorViewEngine(); builder.AddRazorPages();
Many of these default services are great for a general web project, but are usually undesirable for a "pure" Web API.
Here is a sample implementation of ConfigureServices
using AddMvcCore()
for a Web API:
public void ConfigureServices(IServiceCollection services)
{
// Build a customized MVC implementation, without using the default AddMvc(),
// instead use AddMvcCore(). The repository link is below:
// https://github.com/aspnet/Mvc/blob/release/2.2/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs
services
.AddMvcCore(options =>
{
options.RequireHttpsPermanent = true; // this does not affect api requests
options.RespectBrowserAcceptHeader = true; // false by default
//options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
// these two are here to show you where to include custom formatters
options.OutputFormatters.Add(new CustomOutputFormatter());
options.InputFormatters.Add(new CustomInputFormatter());
})
//.AddApiExplorer()
//.AddAuthorization()
.AddFormatterMappings()
//.AddCacheTagHelper()
//.AddDataAnnotations()
//.AddCors()
.AddJsonFormatters();
}
The implementation above is mostly a duplicate of the AddMvc()
extension method, however I have added a few new areas so that others can see the added benefits of doing this.
- Custom Input/Output Formatters. This is where you can do your own highly optimized serializers (such as Protobuf, Thrift, Avro, Etc) instead of using JSON (or worse XML) serialization.
- Request Header Handling. You can make sure that the
Accept
header is recognized, or not. - Authorization Handling. You can implement your own custom authorization or can take advantage of the built-in features.
- ApiExplorer. For some projects, you may likely include it, otherwise some WebAPI's may not want to this feature.
- Cross-Origin Requests (CORS). If you need a more relaxed security on your WebAPI, you could enable it.
Hopefully with this example of a "pure" solution, you can see the benefits of using AddMvcCore()
and be comfortable with using it.
If you're serious about control over performance and latency while working on top of ASP.NET Core's web host maybe a deep dive into a "minimal" solution is where you're dealing right at the edge of the request pipeline, rather than letting it get bogged down by the MVC middleware.
Additional Reading
A visual look at how the middleware pipeline looks like... As per my definitions, less layers means "minimal", whereas "pure" is just a clean version of MVC.
You can read more about it on the Microsoft Documents: ASP.NET Core Middleware Fundamentals
这篇关于如何实现“纯"ASP.NET Core Web API 使用 AddMvcCore()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!