wcf的野心造成了它的庞大复杂,http的单纯造就了它的简单优美。为了实现分布式web应用,我们不得不将两者凑合在一起 —— wcf服务以http绑定宿主于iis。
于是有了让人晕头转向的配置、让人郁闷不已的调试,还有那servicecontract, datacontract, enummember...还有还有,不要在using语句中调用wcf服务...
于是经常自问:拿着牛刀削苹果有必要吗?废话,当然没有必要,水果刀在哪里?
微软看着这么多人拿着牛刀削苹果,自己也看不下去了,于是,一种水果刀横空出世 —— asp.net web api。
最近我们在实际开发中有个地方用wcf太麻烦,就小试了一下水果刀,感觉还不错。
下面用一个简单的示例分享一下asp.net web api水果刀的用法。
服务端asp.net web api的实现
需要准备的工具:visual studio 2010, nuget
1. 新建一个空的asp.net web application项目。
2. 通过nuget添加asp.net web api的引用,在nuget中搜索时要用“aspnetwebapi”(用“asp.net web api”是搜索不到的),然后选择asp.net web api(beta)进行安装。
3. 添加global.asax,在application_start中注册web api的路由,在global.asax.cs中添加如下代码:
protected void application_start(object sender, eventargs e)
{
routetable.routes.maphttproute(webapi, api/{controller}/{action}/{id}, new { id = routeparameter.optional });
}
4. 添加controllers文件夹,在其中添加类文件democontroller.cs,并让democontroller继承自apicontroller。代码如下:
namespace cnblogswebapidemo.controllers
{public class democontroller : apicontroller
{
}
}
5. 添加viewmodels文件夹,在其中添加site.cs,并定义site。
namespace cnblogswebapidemo.viewmodels
{public class site
{public int siteid { get; set; }public string title { get; set; }public string uri { get; set; }
}
}
6. 给democontroller添加一个方法sitelist,并写上我们的示例代码。代码如下:
public class democontroller : apicontroller
{public ilist<site> sitelist(int startid, int itemcount)
{var sites = new list<site>();
sites.add(new site { siteid = 1, title = test, uri = www.cnblogs.cc });
sites.add(new site { siteid = 2, title = 博客园首页, uri = www.cnblogs.com });
sites.add(new site { siteid = 3, title = 博问, uri = q.cnblogs.com });
sites.add(new site { siteid = 4, title = 新闻, uri = news.cnblogs.com });
sites.add(new site { siteid = 5, title = 招聘, uri = job.cnblogs.com });var result = (from site site in siteswhere site.siteid > startidselect site)
.take(itemcount)
.tolist();return result;
}
}
7. 配置一下web项目的启动设置specific page与specific port
8. ctrl+f5运行项目,结果如下:
结果是我们期望的,用浏览器直接可以查看web api的运行结果,测试时会很方便。
好了,服务端web api就这么轻松搞定了!
客户端通过httpclient调用服务端web api
1. 新建一个webapitest的类库项目。
2. 在nuget中添加system.net.http(httpclient就在这里), json.net, xunit.net。
3. 添加类文件webapiclienttest.cs,添加测试方法webapi_sitelist_test:
namespace webapiclienttest
{public class webapiclienttest
{
[fact]public void webapi_sitelist_test()
{
}
}
}
4. webapi_sitelist_test() 的代码实现
4.1 首先,要确定三个东西:
a) 客户端调用webapi的方式是http get,还http post,我们这里选用http post;
b) 客户端调用webapi时传递的参数格式,我们这里选用的是json。
c) webapi返回的数据格式,我们这里选用的也是json(这也是之前添加json.net引用的原因)。
4.2 用到的类
system.net.http.httpclient
system.net.http.httpcontent
system.net.http.stringcontent
system.net.http.headers.mediatypeheadervalue
newtonsoft.json.jsonconvert
4.3 准备需要传递给webapi的参数
需要传递的两个参数是startid ,itemcount,传递的格式是json。这里可没有javascript中的json.stringify(),但我们有json.net,再加上匿名类型,有点用js的感觉,代码如下:
var requestjson = jsonconvert.serializeobject(new { startid = 1, itemcount = 3 });
代码的运行结果:{startid:1,itemcount:3}
然后用system.net.http.stringcontent把它打个包:
httpcontent httpcontent = new stringcontent(requestjson);
然后设置一下contenttype:
httpcontent.headers.contenttype = new mediatypeheadervalue(application/json);
4.4 通过http post调用webapi得到返回结果
httpclient闪亮登场,调用它的postasync()方法轻松搞定:
var httpclient = new httpclient();var responsejson = httpclient.postasync(http://localhost:9000/api/demo/sitelist, httpcontent)
.result.content.readasstringasync().result;
看一下responsejson的结果:
[{siteid:2,title:博客园首页,uri:www.cnblogs.com},{siteid:3,title:博问,uri:q.cnblogs.com},{siteid:4,title:新闻,uri:news.cnblogs.com}]
正宗的json!你注意到没有,服务端webapi的代码未作任何修改,我们只是在http headers中将contenttype设置为了application/json,返回的就是json格式的数据。而我们通过浏览器访问,得到的还是标准的xml。这里就是asp.net web api的魅力之一 —— 一次实现,按需服务。
4.5 将json格式返回的结果反序列化为强类型
json.net又登场:
var sites = jsonconvert.deserializeobject(responsejson);
展示一下返回结果:
代码
sites.tolist().foreach(x => console.writeline(x.title + : + x.uri));
结果
博客园首页:www.cnblogs.com
博问:q.cnblogs.com
新闻:news.cnblogs.com
4.6 webapi_sitelist_test() 完整实现代码
public class webapiclienttest
{
[fact]public void webapi_sitelist_test()
{ var requestjson = jsonconvert.serializeobject(new { startid = 1, itemcount = 3 });
httpcontent httpcontent = new stringcontent(requestjson);
httpcontent.headers.contenttype = new mediatypeheadervalue(application/json);var httpclient = new httpclient();var responsejson = httpclient.postasync(http://localhost:9000/api/demo/sitelist, httpcontent)
.result.content.readasstringasync().result;var sites = jsonconvert.deserializeobject(responsejson);
sites.tolist().foreach(x => console.writeline(x.title + : + x.uri));
}
}
注:运行这里的代码之前,要先运行webapi项目,先把服务跑起来,客户端才能享受到服务。
与jquery ajax调用代码比较一下:
var requestjson = json.stringify({ startid: 1, itemcount: 3 });
$.ajax({
url: '/api/demo/sitelist',
data: requestjson,
type: post,
datatype: json,
contenttype: application/json; charset=utf8,
success: function (data) {
jquery.each(data, function (i, val) {
$(#result).append(val.title + ': ' + val.uri +'<br/>');
});
}
});
注:上面的代码是可真实运行的哦,代码在示例代码webapidemo项目的ajaxwebapi.htm文件中。这也是asp.net web api “一次实现,按需服务”的体现。
小结
水果刀(asp.net web api)用下来感觉还不错,不仅可以削苹果,还可以削梨子,切西瓜也不在话下。用不用牛刀(wcf),还得多考虑考虑。
以上就是关于操作 asp.net web api的实例的详细内容。