.net和java和谐相处之安卓客户端+.net asp.net mvc webapi 2
作为没有花很多时间转java,把java当C#用的我,在做服务器端程序的时候,自然不想考虑java web,java需要学的框架太多了,看了一下Java Servlet,始终没有编码的冲动。经过几天的试验还是决定使用.net做服务器端。webservic很简单也经常用,WCF也用过,感觉还是没有web api来得轻量级,而且根据经验一般商用传统软件会有一大群小白用户和计算机能力不强的代理商,他们都要求软件要部署安装调试简便,什么装个新的Windows Server,新的MSSQL,设置IIS...最好是下一步下一步搞定这种,这就要求服务器端一般吧依赖IIS,这个要求也不过份。那么调研下来只有mvc webapi 2+.net 4.5(OWin.Net)可以自宿主host web服务。
一路趟坑下来,总算成功了。记录下来给朋友们参考一下。
1、win7 64位系统装不上vs2013,.net 4.5的限制
2、OWIN.NET + .net 4尝试
3、web api 的路由把我坑惨了,路由机制跟mvc不一样,在写api的时候传参遇到的问题
1、win7 64位系统装不上vs2013,.net 4.5的限制
安装vs2013需要IE10以上还需要安装SP1,尝试几次安装SP1都是在最后关头失败了,至今没有解决,结果在公司的win2008上安装vs2013成功。由于现在还是使用vs2010比较多,所以家里的电脑就不折腾了。还了解到.net 4.5支持的操作系统有: WIN7 SP1以上,WIN2008 SP1以上,WIN2012,Win8;后两个系统都没用过,貌似这个方案也不是很靠谱啊,客户一般XP和WIN7,服务器WIN2003或者WIN2008比较多。勉强可以吧,服务器端程序要求Win7以上供应商应该能够接受。
2、OWIN.NET + .net 4尝试
这个尝试是把.net 4.5和owin.net需要的全部dll添加到.net 4的解决方案里面,经过N次排错之后编译通过。这个比较奇怪在家里的电脑上(没有安装.net4.5)编译通过,在公司的电脑上(vs2010和vs2013共存)编译失败,多出来N多错误,排除不了。这不是天方夜谭,也不是天马行空的想法,因为之前有.net 2使用linq的经验,所以想尝试一下,结果死在了沙滩上。
owin.net依赖.net 4.5才有的一个方法,现在那个解决方案的源码找不到了,忘记什么异常了。总之一时解决不了.net 4.5的依赖,失败了。
3、web api 的路由把我坑惨了,路由机制跟mvc不一样,在写api的时候传参遇到的问题
1)web api不是我想的那样: web api就是没有view的mvc!!!
之前学过点mvc用mvc 2做过项目,于是稍微查下资料就给web api下了个结论:"web api就是没有view的mvc",就是这个结论让我趟了许多坑,在写api的时候调试遇到各种问题,比如多个参数,多种参数类型api返回json等问题,以前用mvc的JsonResult很顺手,结果非常不习惯web api返回json(这是不了解web api机制导致的),原来web api支持xml和json两种格式的返回,一番恶补之后,终于走上正途了。哎,基础啊基础,自作孽不可活啊,不要以为跟着一些简单的例子操作一遍就掌握了,没基础没有知其所以然就是不行啊。
2)web api的默认路由规则是省略了action的名称,使用默认的路由“api/{controller}/{id}"我不明觉厉,发现api传一个参数的时候可以接收到,但是多个参数不行,自定义路由参数方式好像可以,但是参数名和个数变化大,发现是没有搞明白和mvc的路由之间的差异造成的。
api/{controller}/{id}这个看了N次解释后才了解清楚 {controller}代表控制器的名称,然后自己就传参{id}了,{action}哪儿去了?读书看帖不求甚解啊,罪过,这就是自以为是的苦果,一直都是先入为主,以为是那样的,结果最基础的特性都没有了解清楚。总之将{action}加入变成“api/{controller}/{action}/{id}"之后一切都顺利了。
最终成果及关键代码分享
1)先截几个图吧
服务器端:
客户端:
2)关键代码,Win Service方式Host web api。
定制路由规则和json方式默认返回。
namespace SaunaWebApiHostService
{
public class RegisterRoutesStartup
{
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host. 默认路由
HttpConfiguration config = new HttpConfiguration();
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new { id = RouteParameter.Optional }
//); //自定义路由
config.Routes.MapHttpRoute(
name: "CustomApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
); //只响应Json请求
var jsonFormatter = new JsonMediaTypeFormatter();
config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter)); appBuilder.UseWebApi(config);
}
}
}
Windows Service
/// <summary>
/// 启动服务
/// </summary>
/// <param name="args"></param>
public new void OnStart(string[] args)
{
hostObject = WebApp.Start<RegisterRoutesStartup>(this.GetBaseAddress());
EventLog.WriteEntry("Web Api Host Success,请求基地址:" + this.GetBaseAddress() + "。", EventLogEntryType.Information);
//开始主线程
mainTaskThread = new Thread(SearchDataChangeEvent);
mainTaskThread.Start();
}
如果服务没有其他事做但是host webapp,好像要被系统认为服务没有任何事情可做会自动结束。所以开了个线程,轮询管理系统的消费清单,如果发生变化udp发送udp广播给终端和各消费点方便刷新显示。
安卓客户端:
@Override
protected Boolean doInBackground(String... params) {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("timestamp", String
.valueOf(System.currentTimeMillis())));
JSONHttpClient jsonHttpClient = new JSONHttpClient();
String strResult = jsonHttpClient.Get(ServiceUrl.getInstance("")
.get_Categary_URL(), nameValuePairs);
resultList = new GsonBuilder()
.enableComplexMapKeySerialization()
.create()
.fromJson(strResult,
new TypeToken<List<SaunaItemCategory>>() {
}.getType());
return resultList.size() > 0 ? true : false;
}
package com.aidpoint.sauna.service; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.zip.GZIPInputStream; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient; import android.util.Log; import com.aidpoint.sauna.util.ServiceUrl;
import com.google.gson.GsonBuilder; public class JSONHttpClient {
public <T> T PostObject(final String url, final T object,
final Class<T> objectClass) throws Exception {
DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
try {
String data = new GsonBuilder().create().toJson(object);
StringEntity stringEntity = new StringEntity(data);
Log.i(ServiceUrl.G_Log_Flag, "Post Request:" + data);
httpPost.setEntity(stringEntity);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("Accept-Encoding", "gzip");
HttpResponse httpResponse = defaultHttpClient.execute(httpPost);
Log.i(ServiceUrl.G_Log_Flag,
"Response Result Status:" + httpResponse.getStatusLine());
if (httpResponse.getStatusLine().getStatusCode() == 200) {
HttpEntity httpEntity = httpResponse.getEntity();
if (httpEntity != null) {
InputStream inputStream = httpEntity.getContent();
org.apache.http.Header contentEncoding = httpResponse
.getFirstHeader("Content-Encoding");
if (contentEncoding != null
&& contentEncoding.getValue().equalsIgnoreCase(
"gzip")) {
inputStream = new GZIPInputStream(inputStream);
}
String resultString = convertStreamToString(inputStream);
inputStream.close();
return new GsonBuilder().create().fromJson(resultString,
objectClass);
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw e;
} catch (ClientProtocolException e) {
e.printStackTrace();
throw e;
} catch (IOException e) {
e.printStackTrace();
throw e;
}
return null;
} public <T> T PostParams(String url, final List<NameValuePair> params,
final Class<T> objectClass) throws Exception {
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
return PostObject(url, null, objectClass);
} private String convertStreamToString(InputStream inputStream) {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
try {
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return stringBuilder.toString();
} public <T> T Get(String url, List<NameValuePair> params,
final Class<T> objectClass) {
DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
Log.i(ServiceUrl.G_Log_Flag, "Send Request:" + url);
HttpGet httpGet = new HttpGet(url);
try {
httpGet.setHeader("Accept", "application/json");
HttpResponse httpResponse = defaultHttpClient.execute(httpGet);
Log.i(ServiceUrl.G_Log_Flag, "Response Result Status:"
+ httpResponse.getStatusLine());
if (httpResponse != null
&& httpResponse.getStatusLine().getStatusCode() == 200) {
HttpEntity httpEntity = httpResponse.getEntity();
if (httpEntity != null) {
InputStream inputStream = httpEntity.getContent();
org.apache.http.Header contentEncoding = httpResponse
.getFirstHeader("Content-Encoding");
String resultString = convertStreamToString(inputStream);
inputStream.close();
return new GsonBuilder().enableComplexMapKeySerialization()
.create().fromJson(resultString, objectClass);
} else
return null;
} else
return null; } catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
} catch (ClientProtocolException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
} public String Get(String url, List<NameValuePair> params) { DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
Log.i(ServiceUrl.G_Log_Flag, "Send Request:" + url);
HttpGet httpGet = new HttpGet(url);
try {
httpGet.setHeader("Accept", "application/json");
HttpResponse httpResponse = defaultHttpClient.execute(httpGet);
Log.i(ServiceUrl.G_Log_Flag, "Response Result Status:"
+ httpResponse.getStatusLine());
if (httpResponse != null
&& httpResponse.getStatusLine().getStatusCode() == 200) {
HttpEntity httpEntity = httpResponse.getEntity();
if (httpEntity != null) {
InputStream inputStream = httpEntity.getContent();
org.apache.http.Header contentEncoding = httpResponse
.getFirstHeader("Content-Encoding");
String resultString = convertStreamToString(inputStream);
inputStream.close();
return resultString;
} else
return null;
} else
return null; } catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
} catch (ClientProtocolException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
} public boolean Delete(String url, final List<NameValuePair> params) {
DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
Log.i(ServiceUrl.G_Log_Flag, url);
HttpDelete httpDelete = new HttpDelete(url);
HttpResponse httpResponse = null;
try {
httpResponse = defaultHttpClient.execute(httpDelete);
return httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NO_CONTENT;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
.net和java和谐相处之安卓客户端+.net asp.net mvc webapi 2的更多相关文章
- ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml) 用javascript在客户端删除某一个cookie键值对 input点击链接另一个页面,各种操作。 C# 往线程里传参数的方法总结 TCP/IP 协议 用C#+Selenium+ChromeDriver 生成我的咕咚跑步路线地图 (转)值得学习百度开源70+项目
ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml) 我们都知道在使用WebApi的时候Controller会自动将Action的返回值自动进行各种序列化处理(序列化为 ...
- [ASP.NET MVC]笔记(四 UnobtruSive AJAX和客户端验证
UnobtruSive AJAX和客户端验证 ASP.NET MVC 已经默认开启非侵入试js和客户端验证,在web.config可以看到如下配置: <configuration> < ...
- [ASP.NET MVC]笔记(四) UnobtruSive AJAX和客户端验证
UnobtruSive AJAX和客户端验证 ASP.NET MVC 已经默认开启非侵入试js和客户端验证,在web.config可以看到如下配置: <configuration> < ...
- XMPP(二)-基于asmack+openfire的安卓客户端(仿QQ)的介绍以及个人心得
关于XMPP第一篇-openfire的搭建写完后,就一直在赶本篇所要介绍的这个基于asmack+openfire的安卓客户端,费了不少精力,因为有不少同学在还在焦急的等待着(自恋了呵呵),所以紧赶慢赶 ...
- 安卓客户端a标签长按弹框提示解决办法
昨天工作时候发现一个bug,是关于a标签的,在安卓客户端中,如果是a标签的话,长按会出现一个弹框,如图所示 是因为安卓客户端的长按触发机制,以后进行wap端开发的时候,如果用到跳转页面尽量不要用a标签 ...
- 【源码】c#编写的安卓客户端与Windows服务器程序进行网络通信
NetworkComms网络通信框架序言 用c#开发安卓程序 (xamarin.android)系列之三 源码(包含客户端与服务器端所有工程文件) 数据库文件 为了方便您测试,我临时搭建了一个服 ...
- Java实现UDP之Echo客户端和服务端
Java实现UDP之Echo客户端和服务端 代码内容 采用UDP协议编写服务器端代码(端口任意) 编写客户机的代码访问该端口 客户机按行输入 服务器将收到的字符流和接收到的时间输出在服务器consol ...
- Java实现TCP之Echo客户端和服务端
Java实现TCP之Echo客户端和服务端 代码内容 采用TCP协议编写服务器端代码(端口任意) 编写客户机的代码访问该端口 客户机按行输入 服务器将收到的字符流和接收到的时间输出在服务器consol ...
- “快的打车”创始人陈伟星的新项目招人啦,高薪急招Java服务端/Android/Ios 客户端研发工程师/ mysql DBA/ app市场推广专家,欢迎大家加入我们的团队! - V2EX
"快的打车"创始人陈伟星的新项目招人啦,高薪急招Java服务端/Android/Ios 客户端研发工程师/ mysql DBA/ app市场推广专家,欢迎大家加入我们的团队! - ...
随机推荐
- [WinAPI] API 2 [MessageBox API][消息框API]
/* 调用消息框 MessageBox API [peoject->set->link->project chose->subsystem:windows] */ #inclu ...
- 如何引用jQuery实现下拉列表,点击展开,点击关闭。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- paip.语义分析--单字词形容词表180个
paip.语义分析--单字词形容词表180个 INSERT INTO t (word) SELECT DISTINCT word FROM `word_main` where tsisin is ...
- 喜大普奔!Fanvas正式对外开源了,一键把Flash转为Canvas动画!移动终端动画开发不再困难。
http://code.tencent.com/ https://github.com/TencentOpen/Fanvas DEMO: http://kenkozheng.github.io/fan ...
- Leetcode 172 Factorial Trailing Zeroes
给定一个数n 求出n!的末尾0的个数. n!的末尾0产生的原因其实是n! = x * 10^m 如果能将n!是2和5相乘,那么只要统计n!约数5的个数. class Solution { public ...
- 26数据查询的各种小玩法-select 下(必学)-天轰穿sqlserver视频教程
大纲:简单查询-选择数据列,使用字符串,改变列标题,使用数据运算,使用ALL语DISTINCT关键字,使用TOP关键字,排序 优酷超清地址,为了冲优酷的访问量,所以这里只放优酷的地址了,其实其他网站还 ...
- 【转】iOS超全开源框架、项目和学习资料汇总
iOS超全开源框架.项目和学习资料汇总(1)UI篇iOS超全开源框架.项目和学习资料汇总(2)动画篇iOS超全开源框架.项目和学习资料汇总(3)网络和Model篇iOS超全开源框架.项目和学习资料汇总 ...
- mysql5.5 uuid做主键与int做主键的性能实测
数据库:mysql5.5 表类型:InnoDB 数据量:100W条 第一种情况: 主键采用uuid 32位. 运行查询语句1:SELECT COUNT(id) FROM test_varchar; 运 ...
- AppExchange Partner Keynote
Kick-off Dreamforce at the AppExchange Partner Keynote and hear from industry experts about the tren ...
- 使用LotusScript操作Lotus Notes RTF域
Lotus Notes RTF域的功能也非常强大,除了支持普通的文本以外,还支持图片.表格.嵌入对象.Http 链接.Notes 链接.附件等等众多的类型.本文将介绍如何使用这些类来灵活操作富文本域. ...