最近新公司用了特别老的技术【Web 服务 .asmx文件 做WebService服务】,而WebApi早就流行四五年了;
实在太过于简陋,关键其他系统对接的同事,经常说对接不上,如果接口过多确实不方便接口管理,所以最终决定重新搭建wepai 方便后续接口开发和管理。
一、创建ASP.NET WEB 应用程序 选择空的模板
二、在项目中添加文件夹 App_Start (wepapi 启动项配置文件)
三、在项目中添加文件夹 Controller (用来编写Controller 也就接口)
四、在项目中添加文件夹 Script (用来做文档SwaggerUI的汉化版处理)
App_Start文件夹
配置 WebApiConfig
using FIS.WebService.App_Start;
using Newtonsoft.Json.Converters;
using Swashbuckle.Application;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;namespace FIS.WebService
{public static class WebApiConfig{public static void Register(HttpConfiguration config){config.MapHttpAttributeRoutes();//路由:匹配到actionconfig.Routes.MapHttpRoute(name: "FisApi",routeTemplate: "{controller}/{action}",defaults: new { id = RouteParameter.Optional });config.Routes.MapHttpRoute(name: "swagger_root",routeTemplate: "",defaults: null,constraints: null,handler: new RedirectHandler((message => message.RequestUri.ToString()), "swagger"));//移除XML格式,采用Json进行数据交互config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();//处理DateTime类型序列化后含有T的问题config.Formatters.JsonFormatter.SerializerSettings.Converters.Insert(0, new IsoDateTimeConverter());//config.Filters.Add(new ModeActionFilter());//添加全局异常处理器//config.Filters.Add(new MyAttribute());}}
}
添加 SwaggerConfig
using System.Web.Http;
using WebActivatorEx;
using FIS.WebService;
using Swashbuckle.Application;
using FIS.WebService.App_Start;
using Swashbuckle.Swagger;
using System.Linq;[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]namespace FIS.WebService
{public class SwaggerConfig{public static void Register(){var thisAssembly = typeof(SwaggerConfig).Assembly;GlobalConfiguration.Configuration.EnableSwagger(c =>{c.SingleApiVersion("v1", "Fis WebApi");//显示api接口注释 var xmlFile = string.Format(@"{0}\bin\FIS.WebService.xml", System.AppDomain.CurrentDomain.BaseDirectory);if (System.IO.File.Exists(xmlFile)){c.IncludeXmlComments(xmlFile);}c.CustomProvider((defaultProvider) => new SwaggerControllerDescProvider(defaultProvider, xmlFile));//设置分组名字c.GroupActionsBy(apiDesc =>apiDesc.GetControllerAndActionAttributes().Any() ?apiDesc.GetControllerAndActionAttributes().First().GroupName + " - " +apiDesc.GetControllerAndActionAttributes().First().Useage : "暂未设置ControllGroup");}).EnableSwaggerUi(c =>{c.DocumentTitle("Swagger UI");//加载汉化的js文件c.InjectJavaScript(System.Reflection.Assembly.GetExecutingAssembly(), "FIS.WebService.Script.swagger.js");});}}
}
显示swagger控制器的描述
using Swashbuckle.Swagger;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml;namespace FIS.WebService.App_Start
{/// /// 显示swagger控制器的描述/// public class SwaggerControllerDescProvider : ISwaggerProvider{private readonly ISwaggerProvider _swaggerProvider;private static ConcurrentDictionary _cache = new ConcurrentDictionary();private readonly string _xml;/// /// /// /// /// xml文档路径public SwaggerControllerDescProvider(ISwaggerProvider swaggerProvider, string xml){_swaggerProvider = swaggerProvider;_xml = xml;}public SwaggerDocument GetSwagger(string rootUrl, string apiVersion){var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);SwaggerDocument srcDoc = null;//只读取一次if (!_cache.TryGetValue(cacheKey, out srcDoc)){srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);srcDoc.vendorExtensions = new Dictionary { { "ControllerDesc", GetControllerDesc() } };_cache.TryAdd(cacheKey, srcDoc);}return srcDoc;}/// /// 从API文档中读取控制器描述/// /// 所有控制器描述 public ConcurrentDictionary GetControllerDesc(){string xmlpath = _xml;ConcurrentDictionary controllerDescDict = new ConcurrentDictionary();if (File.Exists(xmlpath)){XmlDocument xmldoc = new XmlDocument();xmldoc.Load(xmlpath);string type = string.Empty, path = string.Empty, controllerName = string.Empty;string[] arrPath;int length = -1, cCount = "Controller".Length;XmlNode summaryNode = null;foreach (XmlNode node in xmldoc.SelectNodes("//member")){type = node.Attributes["name"].Value;if (type.StartsWith("T:")){//控制器arrPath = type.Split('.');length = arrPath.Length;controllerName = arrPath[length - 1];if (controllerName.EndsWith("Controller")){//获取控制器注释summaryNode = node.SelectSingleNode("summary");string key = controllerName.Remove(controllerName.Length - cCount, cCount);if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key)){controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());}}}}}return controllerDescDict;}}
}
Controller描述信息
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;namespace FIS.WebService.App_Start
{/// /// Controller描述信息/// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]public class ControllerGroupAttribute : Attribute{/// /// 当前Controller所属模块 请用中文/// public string GroupName { get; private set; }/// /// 当前controller用途 请用中文/// public string Useage { get; private set; }/// /// Controller描述信息 构造/// /// 模块名称/// 当前controller用途public ControllerGroupAttribute(string groupName, string useage){if (string.IsNullOrEmpty(groupName) || string.IsNullOrEmpty(useage)){throw new ArgumentNullException("groupName||useage");}GroupName = groupName;Useage = useage;}}
}
红框类的是配置文件,其他的是自定义过滤器
Controller 文件夹
添加Controller控制器
using FIS.DAL;
using FIS.Model;
using FIS.WebService.App_Start;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Http;
using System.Web.Http.Description;namespace FIS.WebService.Controller
{[ControllerGroup(groupName: "Process", useage: "工序")]public class ProcessController : ApiController{/* body 获取 string tokenString = HttpContext.Current.Request.Form.Get("tokendata");[ActionName("GetAllPerson")] 指定action[AcceptVerbs("GET", "POST")] 即支持get也支持post[HttpPost] post[HttpGet] get[NonAction] 不被外部应用程序调用[Route("api/[controller]")] 指定路由[AllowAnonymous] 所有访问[MyAttribute.MyException] 自定义错误日志过滤器*//// /// 成品出货/// /// [ActionName("SynProductShipment")][HttpPost]public string SynProductShipment(){MessageObj message = new MessageObj();try{string pamet = Request();List productShipments = JsonConvert.DeserializeObject>(pamet.Trim());if (new ProductShipmentDAO().SynProductShipment(productShipments)){message.Status = 1;message.ReturnMessage = "提交成功";}}catch (Exception ex){message.Status = 0;message.ReturnMessage = $"FIS系统内部错误:{ex.Message.ToString()}";}return JsonConvert.SerializeObject(message);}/// /// 获取所有工序/// /// [ActionName("GetAllProces")][AcceptVerbs("GET", "POST")]public string GetAllProces(){return JsonConvert.SerializeObject(new ProcessFlowDAO().GetProcessName());}/// /// 测试验证参数/// /// /// [ModeActionFilter][HttpPost]public string Test([FromBody] List entity){return "成功!";}[NonAction]public string Request(){string pamet = HttpUtility.UrlDecode(HttpContext.Current.Request.QueryString.ToString(), Encoding.UTF8);if (string.IsNullOrEmpty(pamet)){pamet = HttpContext.Current.Request["inParamJson"];}if (string.IsNullOrEmpty(pamet)){pamet = HttpContext.Current.Request["parm"];}if (string.IsNullOrEmpty(pamet)){Stream reqStream = HttpContext.Current.Request.InputStream;reqStream.Seek(0, SeekOrigin.Begin);byte[] buffer = new byte[(int)reqStream.Length];reqStream.Read(buffer, 0, (int)reqStream.Length);string json = string.Empty;foreach (char a in buffer) { json = json + a.ToString(); }pamet = HttpUtility.UrlDecode(json.ToString(), Encoding.UTF8);}return pamet;}}
}
Script 文件夹
配置SwaggerUI汉化
'use strict';
window.SwaggerTranslator = {_words: [],translate: function () {var $this = this;$('[data-sw-translate]').each(function () {$(this).html($this._tryTranslate($(this).html()));$(this).val($this._tryTranslate($(this).val()));$(this).attr('title', $this._tryTranslate($(this).attr('title')));});},setControllerSummary: function () {try {console.log($("#input_baseUrl").val());$.ajax({type: "get",async: true,url: $("#input_baseUrl").val(),dataType: "json",success: function (data) {var summaryDict = data.ControllerDesc;console.log(summaryDict);var id, controllerName, strSummary;$("#resources_container .resource").each(function (i, item) {id = $(item).attr("id");if (id) {controllerName = id.substring(9);try {strSummary = summaryDict[controllerName];if (strSummary) {$(item).children(".heading").children(".options").first().prepend('' + strSummary + ' ');}} catch (e) {console.log(e);}}});}});} catch (e) {console.log(e);}},_tryTranslate: function (word) {return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;},learn: function (wordsMap) {this._words = wordsMap;}
};/* jshint quotmark: double */
window.SwaggerTranslator.learn({"Warning: Deprecated": "警告:已过时","Implementation Notes": "实现备注","Response Class": "响应类","Status": "状态","Parameters": "参数","Parameter": "参数","Value": "值","Description": "描述","Parameter Type": "参数类型","Data Type": "数据类型","Response Messages": "响应消息","HTTP Status Code": "HTTP状态码","Reason": "原因","Response Model": "响应模型","Request URL": "请求URL","Response Body": "响应体","Response Code": "响应码","Response Headers": "响应头","Hide Response": "隐藏响应","Headers": "头","Try it out!": "试一下!","Show/Hide": "显示/隐藏","List Operations": "显示操作","Expand Operations": "展开操作","Raw": "原始","can't parse JSON. Raw result": "无法解析JSON. 原始结果","Model Schema": "模型架构","Model": "模型","apply": "应用","Username": "用户名","Password": "密码","Terms of service": "服务条款","Created by": "创建者","See more at": "查看更多:","Contact the developer": "联系开发者","api version": "api版本","Response Content Type": "响应Content Type","fetching resource": "正在获取资源","fetching resource list": "正在获取资源列表","Explore": "浏览","Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis","Can't read from server. It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置access-control-origin。","Please specify the protocol for": "请指定协议:","Can't read swagger JSON from": "无法读取swagger JSON于","Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染Swagger UI","Unable to read api": "无法读取api","from path": "从路径","server returned": "服务器返回"
});
$(function () {window.SwaggerTranslator.translate();window.SwaggerTranslator.setControllerSummary();
});
最后添加全局配置Global文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;namespace FIS.WebService
{public class Global : System.Web.HttpApplication{protected void Application_Start(){AreaRegistration.RegisterAllAreas();GlobalConfiguration.Configure(WebApiConfig.Register);//取消xmlGlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();}protected void Session_Start(object sender, EventArgs e){}protected void Application_BeginRequest(object sender, EventArgs e){}protected void Application_AuthenticateRequest(object sender, EventArgs e){}protected void Application_Error(object sender, EventArgs e){}protected void Session_End(object sender, EventArgs e){}protected void Application_End(object sender, EventArgs e){}}
}
运行效果