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中添加如下代碼:
1
2
3
4
|
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。代碼如下:
1
2
3
4
5
|
namespace
CNBlogsWebApiDemo.Controllers
{
public
class
DemoController : ApiController
{
}
}
|
5. 添加ViewModels文件夾,在其中添加Site.cs,並定義Site。
1
2
3
4
5
|
namespace
CNBlogsWebApiDemo.ViewModels
{
public
class
Site
{
public
int SiteId { get; set; }
public
string Title { get; set; }
public
string Uri { get; set; }
}
}
|
6. 給DemoController添加一個方法SiteList,並寫上我們的示例代碼。代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
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:
1
2
3
4
5
6
7
8
9
|
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的感覺,代碼如下:
1
|
var
requestJson = JsonConvert.SerializeObject(
new
{ startId = 1, itemcount = 3 });
|
代碼的運行結果:{"startId":1,"itemcount":3}
然后用System.Net.Http.StringContent把它打個包:
1
|
HttpContent httpContent =
new
StringContent(requestJson);
|
然后設置一下ContentType:
1
|
httpContent.Headers.ContentType =
new
MediaTypeHeaderValue(
"application/json"
);
|
4.4 通過Http Post調用WebAPI得到返回結果
HttpClient閃亮登場,調用它的PostAsync()方法輕松搞定:
1
2
|
var
httpClient =
new
HttpClient();
var
responseJson = httpClient.PostAsync(
"http://localhost:9000/api/demo/sitelist"
, httpContent)
.Result.Content.ReadAsStringAsync().Result;
|
看一下responseJson的結果:
1
|
[{
"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又登場:
1
|
var
sites = JsonConvert.DeserializeObject<IList<Site>>(responseJson);
|
展示一下返回結果:
代碼
1
|
sites.ToList().ForEach(x => Console.WriteLine(x.Title +
":"
+ x.Uri));
|
結果
1
2
3
|
博客園首頁:www.cnblogs.com
博問:q.cnblogs.com
新聞:news.cnblogs.com
|
4.6 WebApi_SiteList_Test() 完整實現代碼
1
2
3
4
5
6
7
8
9
10
11
12
|
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<IList<Site>>(responseJson);
sites.ToList().ForEach(x => Console.WriteLine(x.Title +
":"
+ x.Uri));
}
}
|
注:運行這里的代碼之前,要先運行WebAPI項目,先把服務跑起來,客戶端才能享受到服務。
與jQuery ajax調用代碼比較一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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的實例的詳細內容,更多請關注php中文網其它相關文章!