所以为什么不用ASP.NET WebApi呢(这样就不需要IIS了(
流程上是先建一个WCF服务项目,然后用WCF配置工具打开App.config。在高级-终结点行为中新建一个配置,比如说起名为restfulBehavior,然后点下面的添加,选中webHttp,添加(当然也可以修改这个子节点的属性配置,比如说修改DefaultOutgoingResponseFormat为Json)。在服务-终结点里把Binging设置从原来默认的basicHttpBing改为webHttpBing,修改BehaviorConfiguration为刚才的restfulBehavior。
这样就完成了基本配置修改。然后再在代码层修改。
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; namespace WcfServiceLibrary1 { [ServiceContract] public interface IService1 { [OperationContract] [WebGet(UriTemplate = "Data", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] FooObj GetData(); [OperationContract] [WebGet(UriTemplate = "NullData", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] FooObj GetNullData(); [OperationContract] [WebGet(UriTemplate = "Add?a={a}&b={b}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] decimal Add(decimal a, decimal b); [OperationContract] [WebInvoke(Method = "POST", UriTemplate = "Data", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] bool SetData(FooObj foo); } [DataContract] public class FooObj { [DataMember] public string FooStr { get; set; } [DataMember] public DateTime FooTime { get; set; } } }
这里的WebInvoke感觉就相当于ASP.NET中的[HttpGet] + [Route]。
关于返回值,其实也和ASP.NET一样,微软爸爸会自动帮我们把FooObj序列化成Json返回,然而基本类型就直接返回ToString()了。
//FooObj ret = new FooObj() { FooStr = "", FooTime = DateTime.Now }; { "FooStr": "", "FooTime": "/Date(1524108062758+0800)/" } //FooObj ret = null //int ret = 2 2 //bool ret = true true //string ret = "123" 123 //string ret = null
这当中我们可以观察发现Datetime类型序列化成Json后变成”/Date(1524108062758+0800)/”了,这个到前端可能就需要
var datestr = "/Date(1524108062758+0800)/"; var date = eval("new " + datestr.slice(1, -1));
当然问题的关键不在于前端转换这里,而在于序列化这里。这里有一个超巨大的坑点,这个时间包含了时区信息,假如这个datetime没有被赋值,那他就是一个默认值[0001/01/01 00:00:00],这个值在转为UNIX时间戳时会爆炸(负溢出)。
假如我们把时间设定在1970/1/1,那输出将会得到”/Date(-28800000+0800)/”。这样我们可以发现这是因为东八区+8:00引起的UTC时间减少8小时导致的负溢出。
发现原因后我们就可以这样解决这个问题。
DataContract] public class FooObj { [DataMember] public string FooStr { get; set; } [DataMember] public DateTime FooTime { get; set; } [OnSerializing] internal void OnSerializingMethod(StreamingContext context) { var propertys = this.GetType().GetProperties(); foreach (var pi in propertys.Where(e => e.PropertyType == typeof(DateTime))) { DateTime obj = (DateTime)pi.GetValue(this, null); pi.SetValue(this, obj.ToUniversalTime(), null); } } }
添加OnSerializingMethod方法在序列化前把所有Datetime类型的字段值全部去除时区。这样0001/1/1这个日期将会得到”/Date(-62135596800000)/”。
大致就是这样了。
参考:
其他:
缓存(怎么又变成ASP.NET了呢)
WCF Web HTTP 错误处理(当然大多数情况下是try{}catch{}自定义的)