[水煮 ASP.NET Web API2 方法论](1-5)ASP.NET Web API Scaffolding(模板)
问题
我们想快速启动一个 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
1
2
3
4
5
6
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
public class TeamsController : ApiController{ private ApressRecipesWebApiContext db = new ApressRecipesWebApiContext(); // 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<#@ 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
1
2
3
4
5
|
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/
[水煮 ASP.NET Web API2 方法论](1-5)ASP.NET Web API Scaffolding(模板)的更多相关文章
- [水煮 ASP.NET Web API2 方法论](3-9)空气路由的设置
阅读导航 问题 解决方案 工作原理 代码演示 在此解释一下,空气路由,是本人臆想出来,觉着更能表达 IgnoreRoute 的意图,如果看着辣眼睛^^,请见谅. 问题 我们在之定义过集中式路由,集中式 ...
- [水煮 ASP.NET Web API2 方法论](3-1)集中式路由
问题 怎样集中的定义路由 解决方案 通过调用 HttpRouteCollectionExtension 类中的 MapHttpRoute 扩展方法在 HttpRouteCollection 中定义路由 ...
- [水煮 ASP.NET Web API2 方法论](1-1)在MVC 应用程序中添加 ASP.NET Web API
问题 怎么样将 Asp.Net Web Api 加入到现有的 Asp.Net MVC 项目中 解决方案 在 Visual Studio 2012 中就已经把 Asp.Net Web Api 自动地整合 ...
- [水煮 ASP.NET Web API2 方法论](1-3)如何接收 HTML 表单请求
问题 我们想创建一个能够处理 HTML表单的 ASP.NET Web API 应用程序(使用 application/x-www-form-urlencoded 方式提交数据). 解决方案 我们可以创 ...
- [水煮 ASP.NET Web API2 方法论](3-8)怎样给指定路由配置处理器
阅读导航 问题 解决方案 工作原理 代码演示 问题 如果仅仅针对指定的路由进行某些特定的消息处理,而不是应用于所有路由,我们应该怎么做呢? 解决方案 ASP.NET WEB API 的很多功能都内建了 ...
- [水煮 ASP.NET Web API2 方法论](3-7)默认 Action 请求方式以及 NonActionAttribute
问题 在 Controller 中有一个 public 的方法,但是又不想将这个 publlic 方法暴露成为一个 API. 解决方案 ASP.NET Web API 中,正常是通过 HTTP 谓词来 ...
- [水煮 ASP.NET Web API2 方法论](3-6)万能路由
问题 定义什么样的路由,可以不会受请求参数类型和数量的限制,而被全部捕获? 解决方案 在路由模板中,给参数添加一个"*"前缀,例如 {*param},只要请求的 URL 能够和路由 ...
- [水煮 ASP.NET Web API2 方法论](3-5)路由约束
问题 怎么样限制路由中参数的值. 解决方案 ASP.NET WEB API 允许我们通过 IHttpRouteConstraint 接口设置路由约束.集中式路由和直接式路由都可以使用 IHttpRou ...
- [水煮 ASP.NET Web API2 方法论](3-4)设置路由可选项
问题 怎么样创建一个路由,不管客户端传不传这个参数,都可以被成功匹配. 解决方案 ASP.NET WEB API 的集中式路由和属性路由都支持路由声明可选参数. 在用集中式路由中可以通过 RouteP ...
随机推荐
- Codeforces Round #342 (Div. 2) C
C. K-special Tables time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- Nginx 1 Web Server Implementation Cookbook系列--(1)debug mode
nginx debug模式 1.编译安装的话,需要添加编译参数--with-debug:大部分预编译软件包都已经包含了改参数. 2.格式: error_log LOGFILE [debug | inf ...
- Caused by: java.io.IOException: Filesystem closed的处理
org.apache.hadoop.hive.ql.metadata.HiveException: Unable to rename output from: hdfs://nameservice/u ...
- [技巧篇]13.从今天开始做一个有理想的人,放弃alter的调试,拥抱console.log
在js前端开发时,为了调试经常会加上 console.log.但是在有的浏览器(比如IE)中会报错,怎么办呢?好像10之后也开始支持了!如果以防方一,可以使用如下方式 在js文件最前面添加如下js代码 ...
- MySQL新建用户,授权
登录MySQL mysql -u root -p 添加新用户 允许本地 IP 访问 localhost, 127.0.0.1 create user 'test'@'localhost' identi ...
- 常见的Shell
上面提到过,Shell是一种脚本语言,那么,就必须有解释器来执行这些脚本. Unix/Linux上常见的Shell脚本解释器有bash.sh.csh.ksh等,习惯上把它们称作一种Shell.我们常说 ...
- 【BZOJ】4530: [Bjoi2014]大融合
[题意]给定n个点的树,从无到有加边,过程中动态询问当前图某条边两端连通点数的乘积,n<=10^5. [算法]线段树合并+并查集 (||LCT(LCT维护子树信息 LCT维护子树信息(+启发式合 ...
- 【洛谷 P5110】 块速递推(矩阵加速,分块打表)
题目链接 掌握了分块打表法了.原来以前一直想错了... 块的大小\(size=\sqrt n\),每隔\(size\)个数打一个表,还要在\(0\text{~}size-1\)每个数打一个表. 然后就 ...
- 静态资源(JS/CSS)存储在localStorage
一.简单了解SEO SEO由英文Search Engine Optimization缩写而来, 中文意译为“搜索引擎优化”.SEO是指从自然搜索结果获得网站流量的技术和过程. 搜索引擎不优化的网站分为 ...
- Bitmap算法应用实例(转)
关于数据库查询工作,例如有如下数据库表 要想统计所有90后的程序员该怎么做呢?用一条求交集的SQL语句即可: Select count(distinct Name) as 用户数 from table ...