问题
我们想快速启动一个 ASP.NET Web API 解决方案。
解决方案
APS.NET 模板一开始就支持 ASP.NET Web API。使用模板往我们的项目中添加 Controller,在我们解决方案的 Controllers 文件夹上右键,选择“添加”->"Scaffolding"。
即用模式,可以从下面选择一个:
Web API2 Controller
Web API2 Controller with actions, using Entity Framework
Web API2 Controller with read/write actions
Web API2 OData Controller with action, using Entity Framwork
另外,带有属性路由的基架模板可以从 NuGet 中下载。Install-Package Microsoft.AspNet.WebApi.ScaffolderTemplates.AttributeRouting.CSharp
工作原理
模板功能的全名是 ASP.NET 模板(Scaffolding),他是一个基于 T4 模板的 ASP.NET 代码生成框架。T4(Text Template Transformation Toolkit),是一个代码生成器模板,从 Visual Studio 2005 开始 T4 模板就已经 Visual Studio 的一部分了。
Visual Studio 2013 开始对模板的支持更加出色,允许我们快速生成 ASP.NET 应用程序代码。在 Visual Studio 2013 更新 2 上,一些更具扩展性的功能点被添加进来,比如,模板的可定制化,这就让我们使用他生成代码的时候,更加灵活。
内建模板是被安装在 Visual Studio 安装文件夹中,我们可以在这里定制模板。例如,默认安装的情况下,模板是在
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates 中。需要注意的是,修改任何模板之后,修改变更带来的影响就是全局的。如果想在每个项目的基础上自定义模板,可以通过下面的两种方式:
安装 SideWaffle(sidewaffle.com),他是 Visual Studion 模板管理的一个扩展程序。然后,使用常规的“添加”对话框,然后选择“Web”->“SideWaffle”->“ASP.NET Scaffolding T4”。将会在解决方案的文件夹中创建一个 “CodeTempplates” 文件夹,包括所有全局模板的副本,就可以根据我们的项目需要来修改他。
手动的将所有全局模板复制到 ASP.NET 项目中“CodeTemplates”(名字很重要)文件夹中,该文件夹是在项目的根目录中的一个文件夹。这些模板的副本中包含 C# 和 VB.NET 模板,但是,我们可以根据需要进行删减。要确保文件这些文件已经包含到项目中。
代码
让我们演示一个 Web API Controller
Code-First 使用基础模板处理的例子。
模型展示如列表 1-13。
列表 1-13. EF Code-First
public class Team{ public int Id { get; set; } public string Name { get; set; } public DateTime FoundingDate { get; set; } public string LeagueName { get; set; } }
添加完模型之后,我们在处理模板对话框的时候,需要重新编译项目。EF 是依赖于我们项目应用程序 DLL 的反射。然后,选择“添加”->“Scaffolding”->“Web API”->“Web API 2 Controller with actions,using Entity Framework”。对话框如图1-3。
图 1-3. 添加模板模板对话框。
可以按照图 1-4 的对话框来处理。必须许选择一个模型,他是通过全名来限定的(这有一个可用的下拉框,会展示这个项所有的类),Entity Framework DataContext(如果有的话,会在下拉框中展示,也可以直接在这里创建) 也是通过全名来限定,并且默认的控制器名称也是和模型名称一样。我们可以检查 “Use async controller actions”选择框来强制模板引擎生成异步 action 和使用 EF DataContext 的异步方法。
生成的 Controller 如清单 1-14(为了节省空间,没并没有贴出命名空间)。这是一个完全可以访问的 HTTP url,请求会被默认路由识别匹配。这个创建的 Action(POST)将会响应 201 状态码给调用端,并包含一个指向最新创建资源定位的头。这个更新的 Action(PUT)甚至可能处理一个潜在的异常 DbUpdateConcurrencyException.
清单 1-14. 通过模板生成使用 EF Action 的一个 Web API Controller
public class TeamsController : ApiController{ private Apre***ecipesWebApiContext db = new Apre***ecipesWebApiContext(); // GET: api/Teams public IQueryable<Team> GetTeams() { return db.Teams; } // GET: api/Teams/5 [ResponseType(typeof(Team))] public async Task<IHttpActionResult> GetTeam(int id) { Team team = await db.Teams.FindAsync(id); if (team == null) { return NotFound(); } return Ok(team); } // PUT: api/Teams/5 [ResponseType(typeof(void))] public async Task<IHttpActionResult> PutTeam(int id, Team team) { if (!ModelState.IsValid) { return BadRequest(ModelState); } if (id != team.Id) { return BadRequest(); } db.Entry(team).State = EntityState.Modified; try { await db.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TeamExists(id)) { return NotFound(); } else { throw; } } return StatusCode(HttpStatusCode.NoContent); } // POST: api/Teams [ResponseType(typeof(Team))] public async Task<IHttpActionResult> PostTeam(Team team) { if (!ModelState.IsValid) { return BadRequest(ModelState); } db.Teams.Add(team); await db.SaveChangesAsync(); return CreatedAtRoute("DefaultApi", new { id = team.Id }, team); } // DELETE: api/Teams/5 [ResponseType(typeof(Team))] public async Task<IHttpActionResult> DeleteTeam(int id) { Team team = await db.Teams.FindAsync(id); if (team == null) { return NotFound(); } db.Teams.Remove(team); await db.SaveChangesAsync(); return Ok(team); } protected override void Dispose(bool disposing) { if (disposing) { db.Dispose(); } base.Dispose(disposing); } private bool TeamExists(int id) { return db.Teams.Count(e => e.Id == id) > 0; } }
现在,假设我们已经按照“工作原理”部分描述的方式,在我们的解决方案中添加了基架模板。但是,我们还是希望可以按照自己的方式定义它。例如,强制所有新建的 ASP.NET Web Api 控制器类继承一个指定的基类,如清单 1-15 所示。我们需要修改 CodeTemplates/ApiControllerEmpty 文件夹中的 Controller.cs.t4文件,以确保每一个新的 Controller 不再继承自 ApiController,而是成为 ApiBaseController 的子类,这是一个在大项目中典型的需求,因为很多 Web API 开发者喜欢采用自己的基类作为新的 Controller 的基类。
清单1-15. 通过模板强制新建的 Web API Controller 总是继承自 ApiBaseController
<#@ template language="C#" HostSpecific="True" #> <#@ output extension="cs" #> <#@ parameter type="System.String" name="ControllerName" #> <#@ parameter type="System.String" name="Namespace" #> using System;using System.Collections.Generic; using System.Linq;using System.Net; using System.Net.Http; using System.Web.Http; namespace <#= Namespace #> { public class <#= ControllerName #> : ApiBaseController { } }
如果现在来“添加”->“Scaffolding”->“Web API”->“Web API2 Controller Empty”,生成的代码如清单1-16 所示,继承自 ApiBaseController 而不是
ApiCnotroller。
清单1-16. 根据自定义模板生成的 Controller
Listing 1-16. A Controller Generated from the Customized Scaffolding Template
using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Http;using System.Web.Http;namespace Apress.Recipes.WebApi.Controllers { public class SampleController : ApiBaseController { } }
我们可以在更广泛的范围去使用这个定制化的技术,自定义命名空间,注入自己的服务,或者强制 action 是异步的。
小提示 不仅仅修改现有的,也可以添加新的,完全独立的模板。我们可以在学习更多官方的 .NET Web Development 和 Tools 小组的小组的博客,请戳这里
https://blogs.msdn.microsoft.com/webdev/2014/04/03/creating-a-custom-scaffolder-for-visual-studio/
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。