基于Oracle的EntityFramework的WEBAPI2的实现(四)——自动生成在线帮助文档
打开我们项目中的Area文件夹,正常情况下,我们会发现已经有了一个名字叫做【HelpPage】的区域(Area),这个区域是vs帮助我们自动建立的,它是一个mvc(不是webapi),它有普通的Conroller和Action,以及View,Model等。我们可以在调试的时候输入地址:http://localhost:8080/Help,就可以看见一个页面,有没有看见自己熟悉的TestController(名字中去掉了Controller,只剩下Test了)。如果没有,那么,一定是我们的配置有问题,那么我们下面的检查一下。
首先,要达到自动生成在线帮助的页面,我们必须提示说明信息。其实我们的说明信息就是我们对我们的Controller类的注释以及每一个方法的注释。当然不是//这样的注释,而是如下的注释:
///<summary>
///这才是真的注释
///</summary>
这个注释放在我们的类和我们的Controller以及Controller下的各种Action上,然后把文字写清楚了。右击我们的项目·属性,然后设置如下:
在【生成】标签页里面设置好【XML文档文件】,在里面写好地址,应该和我们的项目的dll在一个位置(通常是主项目下的bin目录),然后全部保存。
这个时候我们所有对类和成员的注释在生成的时候都会被写入进这个xml文件中,但是,我们的在线帮助页要如何取得这些数据呢,当然,这就需要我们告诉它我们的这个xml文件在什么位置。先来看一下目录图。
我们在App_Start文件夹里面找到【HelpPageConfig.cs】文件,这个文件是整个 HelpPage的配置所在。将此文件打开,找到如下的代码,解开注释,并修改为如下内容:
config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/bin/WebApi.xml")));
此时,我们按照一开始时调试 一下,应该就可以看到在每个ApiController上的注释了。但是,我们发现,我们的Model类后面的注释都是空的,原因是我们的Model类是从数据库生成的,虽然数据库里面有注释,EF并没有帮我们把注释从数据库中取进来,有一些其它的第三方工具,可以实现此功能,但是事实上,数据库的注释是给我们看的,而我们的Model类的注释是给调用者看的,这是不一样的,比如我们的Model类型需要写明这个属性是否可以为空,而数据库中的注释有时候会泄露我们系统业务的内部秘密。所以,这个时候,我们打开我们的Model设计器(双击那个edmx文件)选择一个类的一个属性,右击,属性,就可以看见属性里面有一项叫文档,点开,在摘要里面写上我们的注释,即可。当然,详细内容也可以写(但是对HelpPage不做修改的情况下,是看不见详细内容的)。
这还不够,因为edmx只是生成映射文件,是数据库表与我们的类的映射,当然它还包含了一些我们自定义的信息(如刚刚的注释),但是,真正担任代码生成工作的是我们的.tt文件(T4代码模板?T4代码生成代码?随便你怎么叫)。我们点开edmx文件前面的三角号展开它,看见有一个与edmx文件同名但是扩展名为.tt的文件,双击打开它(等等,不要慌,这不是乱码,这是T4的代码,如果有高亮的话,你会觉得它和ASPX或者CSHTML一样让人喜爱,只是现在这个样子确实有点丑,丑得让人看不懂,不过没关系,大家通过无下划线的上下文搜索是可以搜索到相关位置的,然后加入有下划线的代码即可)。如下:
WriteHeader(codeStringGenerator, fileManager);
string summary=string.Empty;
foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
{
fileManager.StartNewFile(entity.Name + ".cs");
BeginNamespace(code);
if(entity.Documentation != null && entity.Documentation.Summary != null)
{
summary=entity.Documentation.Summary;
}else{
summary=entity.Name;
}
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
///<summary>
///<#=summary#>
///</summary>
<#=codeStringGenerator.EntityClassOpening(entity)#>
{
var simpleProperties = typeMapper.GetSimpleProperties(entity);
if (simpleProperties.Any())
{
foreach (var edmProperty in simpleProperties)
{
if(edmProperty.Documentation !=null && edmProperty.Documentation.Summary != null)
{
summary=edmProperty.Documentation.Summary;
}else
{
summary="";
}
#>
///<summary>
///<#=summary#>
///</summary>
<#=codeStringGenerator.Property(edmProperty)#>
当我们部分注释是源于其它项目时,该怎么办,比如Model是单独的项目
那么问题来了,我们刚刚只讲到让HelpPage只取一个WebApi.xml,但是,如果我们的Model在WebApi.Model这个项目中怎么办。我可以告诉你,如果在WebApi.Model中,那么你写一万行的注释,HelpPage也不会让你看见的,因为你的WebApi.Model.Xml并没有给它,它取不到里面的信息。
那么我们右击WebApi.Model这个项目,点属性,然后在【生成】中将【XML文档生成】的位置设置到我们的WebApi项目的bin目录下,与WebApi.xml在 一起。
ok,还有下面一步,就是在HelpPageConfing.cs中,告诉系统我们xml的位置。这个时候,你会发现,【XmlDocumentationProvider】这个类很贱的没有两个参数的重载~~我操!!
那我们现在有两个xml文件,该怎么办?我们在上面的那个目录结构图中,发现,这个【XmlDocumentationProvider】类的源码就在那里,是不是很兴奋,有想改这个类的冲动?别吧,留着它,万一以后用得着呢?我们照着它新建一个继承IDocumentationProvider, IModelDocumentationProvider的类,名字叫【MultiXmlDocumentationProvider】(这个类是我很久之前从网上找的,不知道作者是谁了,在此表示深深的感谢),它的实现如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Description;
using WebApi.Areas.HelpPage.ModelDescriptions; namespace WebApi.Areas.HelpPage
{
/// <summary>A custom <see cref="IDocumentationProvider"/> that reads the API documentation from a collection of XML documentation files.</summary>
public class MultiXmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
{
/*********
** Properties
*********/
/// <summary>The internal documentation providers for specific files.</summary>
private readonly XmlDocumentationProvider[] Providers; /*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="paths">The physical paths to the XML documents.</param>
public MultiXmlDocumentationProvider(params string[] paths)
{
this.Providers = paths.Select(p => new XmlDocumentationProvider(p)).ToArray();
} /// <summary>Gets the documentation for a subject.</summary>
/// <param name="subject">The subject to document.</param>
public string GetDocumentation(MemberInfo subject)
{
return this.GetFirstMatch(p => p.GetDocumentation(subject));
} /// <summary>Gets the documentation for a subject.</summary>
/// <param name="subject">The subject to document.</param>
public string GetDocumentation(Type subject)
{
return this.GetFirstMatch(p => p.GetDocumentation(subject));
} /// <summary>Gets the documentation for a subject.</summary>
/// <param name="subject">The subject to document.</param>
public string GetDocumentation(HttpControllerDescriptor subject)
{
return this.GetFirstMatch(p => p.GetDocumentation(subject));
} /// <summary>Gets the documentation for a subject.</summary>
/// <param name="subject">The subject to document.</param>
public string GetDocumentation(HttpActionDescriptor subject)
{
return this.GetFirstMatch(p => p.GetDocumentation(subject));
} /// <summary>Gets the documentation for a subject.</summary>
/// <param name="subject">The subject to document.</param>
public string GetDocumentation(HttpParameterDescriptor subject)
{
return this.GetFirstMatch(p => p.GetDocumentation(subject));
} /// <summary>Gets the documentation for a subject.</summary>
/// <param name="subject">The subject to document.</param>
public string GetResponseDocumentation(HttpActionDescriptor subject)
{
return this.GetFirstMatch(p => p.GetDocumentation(subject));
} /*********
** Private methods
*********/
/// <summary>Get the first valid result from the collection of XML documentation providers.</summary>
/// <param name="expr">The method to invoke.</param>
private string GetFirstMatch(Func<XmlDocumentationProvider, string> expr)
{
return this.Providers
.Select(expr)
.FirstOrDefault(p => !String.IsNullOrWhiteSpace(p));
}
}
}
这个时候,我们再回到HelpPageConfig.cs类中,找到刚刚那句:
config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/bin/WebApi.xml")));
将它替换为:
config.SetDocumentationProvider(new MultiXmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/bin/WebApi.xml"), HttpContext.Current.Server.MapPath("~/bin/WebApi.Model.XML")));
这时候,我们再调试一下,倍儿爽!!~~~~
基于Oracle的EntityFramework的WEBAPI2的实现(四)——自动生成在线帮助文档的更多相关文章
- [转]基于Oracle的EntityFramework的WEBAPI2的实现(一)——准备工作
基于Oracle的EntityFramework的WEBAPI2的实现(一)——准备工作 转载请注明作者及来源:张峻崎,博客园 目前在.net的范围内,好的而且方便的ORM的真的不是很多,与VS集成 ...
- 基于数据库的自动化生成工具,自动生成JavaBean、自动生成数据库文档等(v4.1.2版)
目录: 第1版:http://blog.csdn.net/vipbooks/article/details/51912143 第2版:htt ...
- 基于Oracle的EntityFramework的WEBAPI2的实现(一)——准备工作
目前在.net的范围内,好的而且方便的ORM的真的不是很多,与VS集成方便的也就当属EntityFramework(以下简称EF,不知道为什么,总EF这个缩写好不专业).但是,好多公司使用的又是ORA ...
- 基于Oracle的EntityFramework的WEBAPI2的实现(三)—— 建立APIController及设置返回类型JSON、XML等
建立普通的ApiControler 右击项目中的controller文件夹·添加·控制器·包含操作的webapi2控制器(使用entity framework),写个名字,如果:Test.然后选择类, ...
- Asp.Net MVC WebApi2 自动生成帮助文档
WebAPI Help文档配置 开发环境VS2013+mvc5+WebApi2 一.通过NuGet引用Web API Test Client 安装后会多一个Areas文件夹 二.设置xml文档项目-- ...
- 基于Oracle的EntityFramework的WEBAPI2的实现(二)——使用DbFirst
之所以使用DbFirst而没有使用CodeFirst是因为考虑到现实的情况中,我们之所以会选择oracle而不是SQL SERVER,一方面是因为之前公司已经在使用Oracle,而且有好多我们需要用到 ...
- 基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(v6.0.0版)
TableGo v6.0.0 版震撼发布,此次版本更新如下: 1.UI界面大改版,组件大调整,提升界面功能的可扩展性. 2.新增BeautyEye主题,界面更加清新美观,也可以通过配置切换到原生Jav ...
- PoiDocxDemo【Android将表单数据生成Word文档的方案之二(基于Poi4.0.0),目前只能java生成】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 这个是<PoiDemo[Android将表单数据生成Word文档的方案之二(基于Poi4.0.0)]>的扩展,上一篇是根 ...
- PoiDemo【Android将表单数据生成Word文档的方案之二(基于Poi4.0.0)】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 使用Poi实现android中根据模板文件生成Word文档的功能.这里的模板文件是doc文件.如果模板文件是docx文件的话,请阅读 ...
随机推荐
- Bootstrap 可视化布局--拖拽后弹窗进行编辑
Bootstrap 可视化布局--拖拽后弹窗进行编辑 最近后台想一个需求,使用可视化布局-中文 | en中拖拽表格后,弹窗进行编辑,保存下载后在后台生成pdf格式. 奈何各种问题不断,使用 jquer ...
- 基于vue-cli,测试非父子传值时,碰到 keep-alive的神奇
非父子传值测试 一直都很好奇非父子传值到底如何,结果入坑许久才爬出来,才知道在脚手架里测试就是坑. 问题: 测试非父子传值时,由于组件之间是通过路由进行跳转,值传过去又被刷掉 思路: 因为路由跳转,相 ...
- python 语法错误记录
1 Missing parameter end_time in docstring less... (Ctrl+F1) 参数位置错误 注意:只有在形参表末尾的那些参数可以有默认参数值,即你不能在声明 ...
- MYSQL-实现ORACLE 和SQLserver数据中- row_number() over(partition by ) 分组排序功能
网上看见了好多例子都基本上是一样的,没有过多的解释,对于一个初学MySQL来说有点难,我把部分转摘过来如下 原文:http://www.cnblogs.com/buro79xxd/archive/20 ...
- Winform 导航菜单的方法
http://blog.163.com/kunkun0921@126/blog/static/169204332201171610619611/ 第一种:使用OutlookBar第三方控件 第二种:使 ...
- ffmpeg jpeg图片播放失败之问题排查
播放jpeg时,avformat_find_stream_info出现以下问题,排查: [jpeg_pipe @ 0x146a80] Could not find codec parameters f ...
- 《Drools7.0.0.Final规则引擎教程》第4章 4.5RHS语法
RHS语法 使用说明 RHS是满足LHS条件之后进行后续处理部分的统称,该部分包含要执行的操作的列表信息.RHS主要用于处理结果,因此不建议在此部分再进行业务判断.如果必须要业务判断需要考虑规则设计的 ...
- 网页基础学习--网络结构和HTML(未完待续)
一.网络常见基本结构: 1.B/S网络结构: Browser/Server:浏览器/服务器,这是现在最流行的网络模式.平常的上网:比如新浪网.凤凰网等.我的电脑(客户端) ...
- HAWQ + MADlib 玩转数据挖掘之(五)——奇异值分解实现推荐算法
一.奇异值分解简介 奇异值分解简称SVD(singular value decomposition),可以理解为:将一个比较复杂的矩阵用更小更简单的三个子矩阵的相乘来表示,这三个小矩阵描述了大矩阵重要 ...
- 8.另类方法求1+2+...+n[AnotherMethodOfCalculateSumN]
[题目] 求1+2+…+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字以及条件判断语句(A?B:C). [分析] 这道题没有多少实际意义,因为在软件开发中不 ...