由于项目需要通过使用客户提供的DLL来获取数据,但是没有Java的接口,DLL动态库是64位的,项目使用的JDK是32位的(好像32位的JDK只能访问32位的DLL,但是有没有其他的方法,那就不得知了)。开始想用WebService的,但是WebService有点繁琐,也比较重,最近在了解Restful,想来想去用这个来试试,下面来说说开发过程中遇到的问题和需要注意的地方。
一,服务端
开发环境:VS2013,.Net Framework 4.5.1,MVC5.2,Nuget
使用VS2013新建一个项目,点击获取联机模板
找到图片中选中的模板,点击确定,使用模板会少一些繁杂的设置
项目已经创建完成,把客户提供的DLL引导项目中,因为DLL只能在64位平台运行,而且这个动态库还调用C++编写的动态库,C++的动态库还是32位的,这个时候需要修改两个地方,要不会报错。
1、右键“解决方案”-- “配置管理器“ 将平台从”Any Cpu“改成”x64“
2、在菜单中选择”工具“ -- ”选项“ -- ”项目与解决方案“ -- ”Web项目“将”对网站和项目使用IIS Express的64位版“选中
接着更新项目中使用的插件,Nuget类似Java中的Maven,使用命令就可以更行相关插件,非常方便
右键项目--”管理Nuget程序包“--”更新“在此处可以更新相关的程序包,还可以用命令来更新程序包
准备阶段完成,现在进入实际开发,先创建一个控制器,右键”Controllers“-- 添加”控制器“,选择”包含读/写操作的控制器“
控制器创建好以后,可以做以下修改,做个一个简单的例子,将第一个方法添加两个参数,并传回去。如果是创建Bean的话,需要注意变量的首字母一定要小写,要么在Jersey转换的时候得不到值。
public class demoController : ApiController { // GET api/demo public IEnumerable<string> Get(string p1,string p2) { return new string[] { p1, p2 }; } // GET api/demo/5 public string Get(int id) { return "value"; } // POST api/demo public void Post([FromBody]string value) { } // PUT api/demo/5 public void Put(int id, [FromBody]string value) { } // DELETE api/demo/5 public void Delete(int id) { } }
Asp.net MVC默认没有提供对异步跨域请求的处理,项目以外访问数据不会合理的取到,需要稍微修改些东西。
在Models中新建一个类(JsonpFormatter.cs),将向下面的代码进去。
public class JsonpFormatter : JsonMediaTypeFormatter { public JsonpFormatter() { SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json")); SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript")); JsonpParameterName = "callback"; } /// <summary> /// Name of the query string parameter to look for /// the jsonp function name /// </summary> public string JsonpParameterName { get; set; } /// <summary> /// Captured name of the Jsonp function that the JSON call /// is wrapped in. Set in GetPerRequestFormatter Instance /// </summary> private string JsonpCallbackFunction; public override bool CanWriteType(Type type) { return true; } /// <summary> /// Override this method to capture the Request object /// </summary> /// <param name="type"></param> /// <param name="request"></param> /// <param name="mediaType"></param> /// <returns></returns> public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, System.Net.Http.HttpRequestMessage request, MediaTypeHeaderValue mediaType) { var formatter = new JsonpFormatter() { JsonpCallbackFunction = GetJsonCallbackFunction(request) }; // this doesn't work unfortunately //formatter.SerializerSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings; // You have to reapply any JSON.NET default serializer Customizations here formatter.SerializerSettings.Converters.Add(new StringEnumConverter()); formatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; return formatter; } public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext) { if (string.IsNullOrEmpty(JsonpCallbackFunction)) return base.WriteToStreamAsync(type, value, stream, content, transportContext); StreamWriter writer = null; // write the pre-amble try { writer = new StreamWriter(stream); writer.Write(JsonpCallbackFunction + "("); writer.Flush(); } catch (Exception ex) { try { if (writer != null) writer.Dispose(); } catch { } var tcs = new TaskCompletionSource<object>(); tcs.SetException(ex); return tcs.Task; } return base.WriteToStreamAsync(type, value, stream, content, transportContext) .ContinueWith(innerTask => { if (innerTask.Status == TaskStatus.RanToCompletion) { writer.Write(")"); writer.Flush(); } }, TaskContinuationOptions.ExecuteSynchronously) .ContinueWith(innerTask => { writer.Dispose(); return innerTask; }, TaskContinuationOptions.ExecuteSynchronously) .Unwrap(); } /// <summary> /// Retrieves the Jsonp Callback function /// from the query string /// </summary> /// <returns></returns> private string GetJsonCallbackFunction(HttpRequestMessage request) { if (request.Method != HttpMethod.Get) return null; var query = HttpUtility.ParseQueryString(request.RequestUri.Query); var queryVal = query[this.JsonpParameterName]; if (string.IsNullOrEmpty(queryVal)) return null; return queryVal; } }
然后找到<Global.asax>文件,在文件中添加以下内容
GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpFormatter());
经过以上的操作,Asp.net将会对跨域请求进行处理,在网页客户端请求以后会得到正确数据。
$.ajax({ type: "get", url: "http://10.140.45.238/api/HistoryDataList?p1=1&p2=2", dataType: "jsonp", success:function(data){ $.each(data,function(i,v){ }); } });
服务端基本完成,具体的增删改查可以对Restful进行了解,网页客户端可以对服务访问并得到数据信息,下一步会说明使用Jersey来作为客户端访问。