从ASP.Net Core Web Api模板中移除MVC Razor依赖项

前言 :本篇文章,我将会介绍如何在不包括MVC / Razor功能和包的情况下,添加最少的依赖项到ASP.NET Core Web API项目中。

 

 

一、MVC   VS WebApi

(1)在ASP.NET的早期版本中,MVC和Web API技术栈是完全分开的。 尽管它们之间共享了许多相似的概念,但实际类型却截然不同。 这通常有点尴尬,当您意外引用错误的命名空间时,通常会导致错误。

(2)在ASP.NET Core中,这不再是个问题:MVC和Web API已统一,其中MVC中的控制器和Web API中的控制器之间基本上没有真正的区别。 您所有的控制器都可以充当MVC控制器,也可以充当Web API控制器,以返回格式化(例如JSON或XML)数据。

(3)话虽如此,如果您只需要使用Web API功能,那么您可能就不需要MVC功能。 但是,当前默认模板中却默认包含了MVC的功能。

 

二、默认模板

当您从Visual Studio中的模板或通过命令行创建新的MVC项目时,可以选择创建空的ASP.NET Core项目,Web API项目还是MVC Web应用程序项目。如果您创建一个“空”项目,那么生成的应用程序实际上是超轻量级的。 它不依赖于任何MVC构造,并且在运行时仅产生一个非常简单的“ Hello World”响应:

另一方面,如果你选择了“ MVC Web app”模板的话,该模板会为您提供了更“完善”的应用。 如果您选择了身份验证选项,除了所有MVC配置和Razor视图模板外,它还可以包括ASP.NET Core Identity,EF Core和SQL Server集成:

 

 

 如果你选择了WebApi模板的话,会创建WebApi 应用并且包含一些必须的MVC依赖项,最简单的版本就包含了一个ValuesController。

 

 但是,虽然看起来很简单,但它也添加了用于创建完整MVC应用程序所有必需依赖包,即服务器端Razor依赖包。 这是因为它包含与整个MVC Web应用程序相同的Microsoft.AspNetCore.Mvc程序包,并在Startup.ConfigureServices中调用AddMvc()。如下图所示:

 

 

 

 AddMvc()将会向服务容器中添加一堆各种服务, 其中一些是允许您使用Web API所必需的,但其中一些(尤其是与Razor相关的服务)对于Web API而言是不必要的。

在大多数情况下,使用Microsoft.AspNetCore.Mvc包是最容易的事情,但是有时您希望尽可能地减少依赖关系,并尽可能地减轻API的负担。 在这些场景下,您可能会发现仅专门添加应用程序所需的MVC软件包和服务会很有用。

 

三、添加依赖包的正确姿势

我们将从“空” Web应用程序模板开始,然后向其中添加Web API所需的包。您需要那些软件包将取决于您应用程序所需的功能。 默认情况下,Empty ASP.NET Core模板包括ApplicationInsights和Microsoft.AspNetCore元数据包,因此我将其留在项目中。

在这些之上,我将添加MVC.Core包,JSON格式化程序包和CORS包:

  •  MVC Core软件包添加了所有必需的MVC类型,例如ControllerBase和RouteAttribute,以及许多依赖项,例如Microsoft.AspNetCore.Mvc.Abstractions和Microsoft.AspNetCore.Authorization。
  • JSON格式化程序包确保我们可以实际呈现Web API操作结果
  • CORS软件包增加了跨源资源共享(CORS)支持-这是Web API常见的要求,该Web API将托管在调用它们的客户端不同的域中。

最终的.csproj文件应如下所示:

 

 为了方便我练习我贴出文字版的项目文件:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.1.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Cors" Version="2.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.1.0" />
   
  </ItemGroup>

</Project>

 

 还原完软件包后,现在我们就 可以更新Startup文件来添加我们的WebApi服务了.

四、在 Startup.cs文件中添加我们必须的服务

在大多数情况下,将Web API服务添加到项目中就像在ConfigureServices方法中调用AddMvc()一样简单。 但是,该方法增加了我们不需要的一些依赖项。 默认情况下,它将添加ApiExplorer,Razor视图引擎,Razor views,TagHelpers和DataAnnotations-目前我们都没有使用(如果后面用到了我们稍后再添加ApiExplorer和DataAnnotations都是可以的),但现在我们不需要。相反,我们只需要添加一下服务:

public void ConfigureServices(IServiceCollection services)
{
    var builder = services.AddMvcCore();
    builder.AddAuthorization();
    builder.AddFormatterMappings();
    builder.AddJsonFormatters();
    builder.AddCors();
}

 这就是我们需要的服务,好了,现在我们在添加所需要的中间件。

 

五、添加中间件

将MvcMiddleware添加到管道很简单。 我们只需要用UseMvc()替换了运行“ Hello World”中间件就行了。但是, 请注意,我们使用的是该方法的非参数化版本,该版本没有向该应用程序添加任何常规路由。 由于这是一个Web API,因此我将仅使用属性路由,因此无需设置常规路由。

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            //if (env.IsDevelopment())
            //{
            //    app.UseDeveloperExceptionPage();
            //}

            //app.Run(async (context) =>
            //{
            //    await context.Response.WriteAsync("Hello World!");
            //});

            loggerFactory.AddConsole();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
        }

 

这些就是我们所需要的MVC配置,最后,我们再来创建一个控制器,来看看是否能正确运行。

 

六、添加一个 MVC控制器

以这种方式创建Web API时需要注意的一个重要点就是:您必须使用ControllerBase类作为所有Controller的父类,而不是Controller。 后者在Microsoft.AspNetCore.Mvc程序包中已经定义但是我们没有添加。 幸运的是,它主要包含与渲染Razor有关的方法,因此这对我们来说不是问题。 ControllerBase类包含您可能会使用的所有各种StatusCodeResult帮助方法,例如下面的代码:

[Route("api/[controller]")]
    public class ValuesController:ControllerBase
    {
        // GET api/values
        [HttpGet]
        public IActionResult Get()
        {
            return Ok(new string[] { "value1", "value2" });
        }
    }

 

运行结果如下:

 

 

 瞧! 这就是精简的Web API控制器,具有最小的依赖项。

 

七、扩展:AddWebApi扩展方法

 

最后梳理一下-我们的ConfigureServices方法看起来有点乱。 在这种方法中,我们可以通过创建一个扩展方法来减少Startup.cs类中的混乱情况,代码如下:

using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Internal;

// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
{
    public static class WebApiServiceCollectionExtensions
    {
        /// <summary>
        /// Adds MVC services to the specified <see cref="IServiceCollection" /> for Web API.
        /// This is a slimmed down version of <see cref="MvcServiceCollectionExtensions.AddMvc"/>
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
        /// <returns>An <see cref="IMvcBuilder"/> that can be used to further configure the MVC services.</returns>
        public static IMvcBuilder AddWebApi(this IServiceCollection services)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));

            var builder = services.AddMvcCore();
            builder.AddAuthorization();

            builder.AddFormatterMappings();

            // +10 order
            builder.AddJsonFormatters();

            builder.AddCors();

            return new MvcBuilder(builder.Services, builder.PartManager);
        }

        /// <summary>
        /// Adds MVC services to the specified <see cref="IServiceCollection" /> for Web API.
        /// This is a slimmed down version of <see cref="MvcServiceCollectionExtensions.AddMvc"/>
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
        /// <param name="setupAction">An <see cref="Action{MvcOptions}"/> to configure the provided <see cref="MvcOptions"/>.</param>
        /// <returns>An <see cref="IMvcBuilder"/> that can be used to further configure the MVC services.</returns>
        public static IMvcBuilder AddWebApi(this IServiceCollection services, Action<MvcOptions> setupAction)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            if (setupAction == null) throw new ArgumentNullException(nameof(setupAction));

            var builder = services.AddWebApi();
            builder.Services.Configure(setupAction);

            return builder;
        }

    }
}

最后,我们可以使用此扩展方法来整理我们的ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
{
    services.AddWebApi();
}

 

这下看起来就清爽多了。

 

八、总结:

 

这篇文章展示了当您知道不需要Razor依赖时,如何从应用程序中移除它们。 这几乎使我们能在应用程序中使用的最小化的Web API。 我知道方法可能会有很多,但是,添加额外的功能(例如ApiExplorer)却很容易!好了,今天就聊到这里。幸运的是,Net Core 3.0 中已经为我们做了这些工作,如果不了解的可以参考我以前的文章,也可以查看源码。

 

 

 

 

参考文章 :https://andrewlock.net/removing-the-mvc-razor-dependencies-from-the-web-api-template-in-asp-net-core/

 

 

作者:郭峥

出处:http://www.cnblogs.com/runningsmallguo/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

posted @ 2019-10-03 19:38  菠萝吹雪—Code  阅读(1277)  评论(2编辑  收藏  举报