前言 :本篇文章,我將會介紹如何在不包括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 中已經為我們做了這些工作,如果不了解的可以參考我以前的文章,也可以查看源碼。
作者:郭崢
出處:http://www.cnblogs.com/runningsmallguo/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。