【问题标题】:How to implement a "pure" ASP.NET Core Web API by using AddMvcCore()如何使用 AddMvcCore() 实现“纯”ASP.NET Core Web API
【发布时间】:2017-07-10 22:55:10
【问题描述】:

我见过很多使用默认 AddMvc() 服务的 ASP.NET Core Web API 项目,但没有意识到使用 AddMvcCore() 是一个更好的选择,因为它可以控制服务。

您究竟是如何使用AddMvcCore() 实现 ASP.NET Core Web API 的?为什么更好?

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc asp.net-core-webapi


    【解决方案1】:

    AddMvc()AddMvcCore()有什么区别?

    首先要了解的是AddMvc() 只是AddMvcCore() 的预加载版本。您可以在GitHub repository 看到AddMvc() 扩展的确切实现。

    我和其他人一样喜欢使用默认的 VS 模板,但有时您需要知道什么时候是错误的选择。我在网上看到过一些指南,它们更倾向于尝试“撤消”这些默认服务,而不是仅仅使用一开始就没有实现它们的解决方案。

    随着 ASP.NET Core 开源的出现,我们确实没有充分的理由不能剥离一层并在较低级别上工作,而不必担心失去“魔力”。


    “最小”和“纯”的定义

    注意:这些定义仅用于此答案的上下文。主要是为了清楚起见和帮助进一步理解。

    这个答案更倾向于“纯粹”而不是“最小”。我想描述一下原因,以便更清楚我在说什么。

    最小化。“最小化”解决方案是一种甚至不调用 AddMvcCore() 方法的实现。这样做的原因是,MVC 并不是组装您自己的 Web API 的真正“必需”组件,而且它肯定会通过额外的依赖项为您的代码增加一些权重。在这种情况下,由于您没有使用 AddMvcCore() 方法,因此您也不会将其注入到您的应用程序中,这里

    public void Configure(IApplicationBuilder app)
    {
        app.UseMvc(); // you don't need this
    }
    

    这意味着映射您自己的路线并以您自己的方式回复context。这真的一点都不具有挑战性,但我不想深入研究它,因为它非常离题,但这里是最小实现的一个小尝试

    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!");
        });
    }
    

    对于许多项目,“最小”方法意味着我们放弃了 MVC 中的一些功能。你真的必须权衡你的选择,看看你这个设计路径是否是正确的选择,因为在设计模式、便利性、可维护性、代码占用以及最重要的性能和延迟之间存在平衡。 简单地说:“最小”解决方案意味着最小化代码和请求之间的服务和中间件。

    纯。“纯”解决方案(就本答案的上下文而言)是通过不实施“预捆绑”AddMvc() 来避免所有默认服务和中间件首先是它。相反,我们使用AddMvcCore(),这将在下一节中进一步解释:


    AddMvcCore()实现我们自己的服务/中间件

    开始的第一件事是将ConfigureServices 设置为使用AddMvcCore()。如果您查看GitHub repository,您可以看到AddMvc() 使用一组标准的服务/中间件调用AddMvcCore()

    以下是一些突出为“不需要”的服务/中间件:

    var builder = services.AddMvcCore();
    
    builder.AddViews();
    builder.AddRazorViewEngine();
    builder.AddRazorPages();
    

    其中许多默认服务非常适合一般 Web 项目,但通常不适合“纯”Web API。

    这是一个使用 AddMvcCore() 的 Web API 实现 ConfigureServices 的示例:

    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();
    }
    

    上面的实现大部分是 AddMvc() 扩展方法的副本,但是我添加了一些新区域,以便其他人可以看到这样做的额外好处。

    • 自定义输入/输出格式化程序。您可以在此处创建自己的高度优化的序列化程序(例如 Protobuf、Thrift、Avro 等),而不是使用 JSON(或更糟糕的 XML)序列化。
    • 请求标头处理。您可以确保Accept标头被识别。
    • 授权处理。您可以实现自己的自定义授权,也可以利用内置功能。
    • ApiExplorer。对于某些项目,您可能会包含它,否则某些 WebAPI 可能不希望使用此功能。
    • 跨源请求 (CORS)。如果您需要更宽松的 WebAPI 安全性,可以启用它。

    希望通过这个“纯”解决方案的示例,您可以看到使用AddMvcCore() 的好处,并且可以轻松地使用它。

    如果您在 ASP.NET Core 的 Web 主机上工作时对性能和延迟的控制很认真,也许深入研究“最小”解决方案是您在请求管道边缘处理的地方,而不是让它陷入 MVC 中间件的困境。


    补充阅读

    中间件管道看起来如何的直观视图...根据我的定义,更少的层意味着“最小”,而“纯”只是 MVC 的干净版本。

    您可以在 Microsoft 文档中阅读更多相关信息:ASP.NET Core Middleware Fundamentals

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-18
      • 2020-11-16
      • 2021-12-17
      • 1970-01-01
      • 2022-11-18
      • 2019-07-18
      • 2019-02-19
      • 2020-11-26
      相关资源
      最近更新 更多