FastHttpApi相对于asp.net mvc来讲有着更轻量和性能上的优点,性能上面就不在这里介绍了(具体可查看 https://github.com/IKende/FastHttpApi)。在这里主要讲解一下如何使用FastHttpApi进行网站或WebApi开发,在使用FastHttpApi以前必须了解它具有那些功能,它除了提供webapi服务的编写外还提供了静态资源的支持,简单来讲FastHttpApi除了能实现基于HTTP的服务交互外还能实现应用网站;虽然不提供视MVC那样的视图处理功能,但能够经过现有比较成熟的先后端分离技术来实现应用网站的编写。如下是简单地描述一下FastHttpApi的功能:css
- 支持以函数的方式来制定HTTP请求逻辑
- 支持使用者处理异步响应
- 支持Filter功能,以便更好地控制请求方法的处理
- 支持自定义Http Body解释器,方便制定基于json,xml,protobuf,msgpack等数据格式的传输
- 支持QueryString参数和Cookies
- 支持外置或内嵌到DLL的静态资源输出(默认对html,js,css资源进行GZIP处理)
- 支持SSL
(在后续版升级主要功能:同一服务端口的控制器逻辑会同时兼容http和websocket两种协议请求)html
经过以上功能彻底能够用来构建高效全安的应用网站。如下经过一些例子详细讲述如何使用FastHttpApi。git
定义HTTP请求的方法
在FastHttpApi定义HTTP请求的方法和asp.net webapi差很少,都是经过定义一个控制器而后定义相关请求方法便可,固然使用起来会简单一些。如下以Northwind的数据做为基础制定了一个简单的数据访问控制器github
[FastHttpApi.Controller] public class Controller { public Controller() { mEmployees = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Employee>>(Datas.Employees); mCustomers = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Customer>>(Datas.Customers); mOrders = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Order>>(Datas.Orders); } private List<Employee> mEmployees; private List<Customer> mCustomers; private List<Order> mOrders; public Employee GetEmployee(int id) { Employee result = mEmployees.Find(e => e.EmployeeID == id); if (result == null) result = new Employee(); return result; } public bool EditEmployee(int id, [BodyParameter]Employee emp, FastHttpApi.HttpResponse response) { Employee record = mEmployees.Find(e => e.EmployeeID == id); if (record != null) { record.City = emp.City; record.Address = emp.Address; record.Title = emp.Title; record.HomePhone = emp.HomePhone; return true; } return false; } public object ListEmployees() { return mEmployees; } public object GetEmployeesName() { return from e in mEmployees select new { ID = e.EmployeeID, Name = e.FirstName + " " + e.LastName }; } public object GetCustomersName() { return from c in mCustomers select new { ID = c.CustomerID, Name = c.CompanyName }; } public object ListOrders(int employeeid, string customerid) { return mOrders.Where(o => (employeeid == 0 || o.EmployeeID == employeeid) && (string.IsNullOrEmpty(customerid) || o.CustomerID == customerid)); } }
相对于asp.net webapi来讲,组件中会把全部控制器Public方法注册为URL,方法是不区分GET或POST,若是有须要能够经过HttpRequest中获取;参数根据本身须要来定义,参数有两种来源一种是经过QueryString获取而另外一种则经过HttpBody获取;对于HttpResponse和HttpRequest则看状况须要,若是有须要直接在方法中定义相关类型参数便可获取。当控制器编写完成后,须要给类写上[Controller]标签告诉组件这是一个api控制器接收HTTP请求。web
异步应答处理
对于HTTP来讲,一个请求就必需要应答,由于这是HTTP协议规范;在实际业务中每每方法处理完成就进行应答,但有些状况下须要异步应答;当一个业务须要处理大量IO的业务时那就会把线程处于等待状态,为了更好地处理这种状况组件提供了异步应答处理;经过异步应答能够在大量IO处理异步回调后再进行应答处理。json
public void asyncHello(string name, HttpResponse response) { response.Async(); Task.Run(() => { Console.WriteLine("sleep ..."); System.Threading.Thread.Sleep(5000); response.Result(string.Format("[{0}] hello {1}", DateTime.Now, name)); }); }
经过HttpResponse.Async方法告诉组件是异步应答,组件在这个方法执行完成后不会进行HTTP响应。实际响应是使用者须要显式地调用HttpResponse.Result方法来进行应答。后端
filter的应用
相信写过asp.net mvc的朋友对filter并不陌生,它的主要工做就是对请求方法进行拦截控制。FastHttpApi支持使用都定义任意功能的Filter,用来记录日志、控制权限等等。编写好的控制器能够标记在Controller上,生效于全部相关主求方法;也能够针对个别方法标记上。组件除了提供Filter外还提供了SkipFilter,它的主要做用是移走某些不须要的Filter拦截器。api
public class GlobalFilter : FilterAttribute { public override void Execute(ActionContext context) { Console.WriteLine(DateTime.Now + " globalFilter execting..."); context.Execute(); Console.WriteLine(DateTime.Now + " globalFilter executed"); } }
以上是标记一个全局的Filter,用于记录方法执行前和执行后的时候,context.Execute()是告诉组件往下执行;若是判断权限,则在这里能够依据HttpRequest的信息状况来决定是否执行context.Execute(),这样就起到了权限控制的做用。当但愿某个方法不通过这个Filter的状况下能够这样作:缓存
[SkipFilter(typeof(GlobalFilter))] [CustomFilter] public string Hello(string name) { return DateTime.Now + " hello " + name; }
HTTP消息体解释器
组件经过IBodySerializer接口来规范HTTP消息体的解释和一些错误状态返回的数据websocket
public interface IBodySerializer { int Serialize(PipeStream stream, object data); bool TryDeserialize(PipeStream stream, int length, Type type, out object data); object GetNotFoundData(HttpResponse response); object GetInnerError(Exception e, HttpResponse response, bool outputStackTrace); object GetNotSupport(HttpResponse response); string ContentType { get; set; } }
接口提供的功能比较少,主要包括消息的序列化、反序列化和一些HTTP状态的处理,随便着功能的完善后期这接口可能会添加更多的方法。如下是针对Json实现的一个解释器,毕竟在WEB通信中json是最经常使用的(若是是网内服务交互为了提升效率能够实现protobuf,msgpack等二进制序列化)。
public virtual int Serialize(PipeStream stream, object data) { int length = stream.CacheLength; string value = Newtonsoft.Json.JsonConvert.SerializeObject(data); stream.Write(value); return stream.CacheLength - length; } public virtual bool TryDeserialize(PipeStream stream, int length, Type type, out object data) { data = null; if (stream.Length >= length) { string value = stream.ReadString(length); if (type != null) { data = Newtonsoft.Json.JsonConvert.DeserializeObject(value,type); } else { data = Newtonsoft.Json.JsonConvert.DeserializeObject(value); } return true; } return false; }
可能经过如下方式'mApiServer.ServerConfig.BodySerializer = new JsonBodySerializer();'来设置相应HTTP服务的消息转换器。
Cookies处理
FastHttpApi和asp.net mvc处理的方式差很少,经过HttpResponse进行Cookie的写入,由HttpRequest来获取Cookie值。
public bool setCookie(string name, string value, HttpResponse response) { response.SetCookie(name, value); return true; } public void getCookie(string name, HttpRequest request, HttpResponse response) { string value = request.Cookies[name]; response.Result(value); }
网页资源处理
组件处理的网页资源须要存放在当前项目的views目录下,views目录能够说是网页资源的根目录。网页资源有两种打包方式,一种是编译复制到发布目录下,而另外一种则是嵌入到编译资源中;建议选择嵌入资源的发布方式,这样最终发布的时候就只须要复制一个DLL便可,不过这种方式发布须要修改网页资源都须要从新发布。对于编译复制发布的好处是能够直接修改,组件会检则修改状况从新刷新资源缓存。 组件处理网页资源有两种方式,对于image的资源组件是在头上标识为客户端缓存,在没过时的状况客户端不会二次请求图片资源。那对于HTML,CSS,JS这些文件组件会加个缓存标签,当文件发生变化会从新响应给客户端,不然响应304给客户端。
开发阶段调试简化
因为网页资源须要编译才会被从新复制或嵌入的到程序中,这样每修改一次都要编译查看结果那是很麻烦的事情,也浪费大量工做时间。因此在启动服务的时候执行一下HttpApiServer.Debug方法,经过这个方法能够把网页资源目录指向项目中网页资源的目录,这样修改网页也不须要从新编译便可查看。 HttpApiServer.Debug只有在Debug模式下才能生效。 (提示FastHttpApi的url不区分大小写)
如下是NorthWind数据订单查询的页面代码
<script> $(document).ready(function () { $.get("/GetEmployeesName", function (items) { items.forEach(function (v, i) { $('#lstEmployees').append(' <option value="' + v.ID + '">' + v.Name + '</option>') }); }); $.get("/GetCustomersName", function (items) { items.forEach(function (v, i) { $('#lstCustomers').append(' <option value="' + v.ID + '">' + v.Name + '</option>') }); }); search(); }); function search() { $.get('/listorders?employeeid=' + $('#lstEmployees').val() + "&customerid=" + $('#lstCustomers').val(), function (items) { $("#lstbody").empty(); items.forEach(function (v, i) { $("#lstbody").append('<tr><td>' + i + '</td><td>' + v.OrderID + '</td><td>' + v.ShipName + '</td><td>' + v.ShipAddress + '</td><td>' + v.ShipCity + '</td><td>' + v.OrderDate + '</td></tr>') }); }); } </script>
运行服务
FastHttpApi启动Http服务很是简单,并不须要作太多的配置便可运行
private static HttpApiServer mApiServer; static void Main(string[] args) { mApiServer = new HttpApiServer(); mApiServer.ServerConfig.BodySerializer = new JsonBodySerializer(); mApiServer.Register(typeof(Program).Assembly); //config.SSL = true; //mApiServer.ServerConfig.CertificateFile = @"c:\ssltest.pfx"; //mApiServer.ServerConfig.CertificatePassword = "123456"; mApiServer.Debug(); mApiServer.Open(); Console.Write(mApiServer.BaseServer); Console.Read(); }
若是但愿修改一些基础配置信息,如服务IP和端等能够经过HttpApiServer.ServerConfig来修改;也能够经过HttpConfig.json来配置相应信息.
(具体代码查看:https://github.com/IKende/FastHttpApi/tree/master/samples)