一、区域—麻雀虽小,五脏俱全的迷你MVC项目

1.1 Area的兴起

为了方便大规模网站中的管理大量文件,在ASP.NET MVC 2.0版本中引入了一个新概念—区域(Area)。


在项目上右击创建新的区域,可以让我们的项目不至于太复杂而导致管理混乱。有了区域后,每个模块的页面都放入相应的区域内进行管理很方便。例如:上图中有
两个模块,一个是Admin模块,另一个是Product模块,所有关于这两个模块的控制器、Model以及视图都放入各自的模块内。可以从上图中看出,
区域的功能类似一个小的MVC项目,麻雀虽小五脏俱全,有自己的控制器、模型、视图还有路由设置
区域实际上是应用程序内部的一个 MVC 结构,一个应用程序可能包含若干个 MVC 结构(区域)。例如:一个大型电子商务应用程序可能分为若干个区域,这些区域表示店面、产品检查、用户帐户管理和采购系统。每个区域表示整个应用程序的一个独立功能。

1.2 注册区域路由

在MVC中添加一个Area区域之后,会默认帮我们注册这个区域的路由规则。例如:我们创建了一个Admin的区域,然后它帮我们生成了一个AdminAreaRegistration.cs的文件,其代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class AdminAreaRegistration : AreaRegistration
{
        public override string AreaName
        {
            get
            {
                return "Admin";
            }
        }
 
        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "Admin_default",
                "Admin/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
}

这里,RegisterArea是实现注册的关键方法,通过把另一个路由添加到区域路由集合中实现。请注意,这里的区域名Admin是以硬编码方式添加到URL中;因此,所有使用此区域名称作为前缀的请求都被进行特别路由处理。

你可能感到疑惑:为什么我们不能在主应用程序的路由定义中指定Admin部分?实际上,如果我们将它加入到标准的路由表中,而不通过区域上下文
(AreaRegistrationContext),那么我们还是把所有文件驻留到同一个项目中,从而失去了分离项目区域的好处(即区域没有起到作
用)。

二、模板页—封装页面变化点,构建快速View开发模板

在传统的WebForm开发模式中,我们使用MasterPage作为模板页。那么在MVC3 Razor视图设计中,我们怎么来使用模板页呢?

2.1 模板页的归宿—Shared文件夹

在解决方案资源管理中,我们可以看到Views文件夹下面有一个Shared文件夹。在Shared文件夹里面有一个_Layout.cshtml页面。这个就是项目中默认的模板页面,如下图所示:

在Shared中新建一个MVC布局页,取名为:_MyLayout.cshtml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        @RenderSection("Head", required: false)
        <h1>This is MyLayout Page</h1>
        <hr />
        @RenderBody()
    </div>
</body>
</html>

其中RenderSection为渲染指定区域,该区域名称为Head,但不是必须渲染(required:false)。而RenderBody则是重头戏,他就类似于MasterPage中主内容的PlaceHolder,是每个使用该模板页都需填充的内容区域。

那么,怎么来使用这个模板页呢?其实很简单,只需要在要使用模板页的View中修改Layout属性即可:

2.2 View未动,ViewStart先行

在Razor视图引擎中,所有页面启动之前,ViewStart文件会先执行。那么,这个ViewStart文件到底做了些什么事儿呢?

(1)可以看出,这个ViewStart是一个全局的页面。当我们的页面未指定Layout的时候,如果项目在全局或在同文件夹内存在
_ViewStart.cshtml时该页面的Layout会自动继承自_ViewStart.cshtml,如果不同的文件夹层级都存在
_ViewStart.cshtml,则继承离该页面最近的一个。

(2)如果我们想要所有的页面都默认使用一个指定模板页,只需将这个Layout改为新模板页即可。例如:将Layout改为我们刚刚创建的~/Views/Shared/_MyLayout.cshtml。

2.3 RenderBody与RenderSection

(1)RenderBody:

@RenderBody()在模板页中使用表示内容页在模板中的位置。当创建具有模板页的内容页的时候,内容页就呈现在模板页中@RenderBody()所在的位置,一个模板页中只能有一个@RenderBody()。

(2)RenderSection:

@RenderSection用于在模板布局中定义一个区域,在内容页可以定义一些内容来填充这个区域,例如内容页中引用的JS文件,可以填充到模板页的section位置。每个内容页的单独一些信息,可以在模板页中这个区域显示。

@RenderSection有两个个参数,第一个参数用于定义section的名称,第2个参数是布尔类型,如果为TRUE,表示内容页必须定义这个section,如果为false,则表示内容页可定义section,也可以不定义。

三、WebAPI初步—构建轻量级Restful服务的利器

3.1 Restful架构是什么?

RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

这里借用阮一峰博士的总结,到底什么是Restful架构:

(1)每一个URI代表一种资源

(2)客户端和服务器之间,传递这种资源的某种表现层;

(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化“。

各位园友可以阅读阮一峰博士的这篇《理解RESTful架构》的文章来了解Restful架构的基本概念。

综上所示,REST是一种简洁的设计风格,通过URL来设计系统,以URI来抽象各种资源,以HTTP协议的PUT、DELETE、GET、POST来对应对资源的各种操作。

3.2 WCF and WebAPI

首先,ASP.NET Web API 和WCF有着千丝万缕的联系。

WCF是一个通用的服务架构平台,其设计之初在于创建一个通用的Web Service平台,可以在各种不同的协议(TCP, UDP,
HTTP)下使用,仅仅通过EndPoint的配置而不需要修改代码实现就能适应不同的工作环境。WCF也是微软以前很多服务产品的合体。

WCF 里面可以采用模板的方式来实现REST架构风格,但WCF毕竟是一个集大成的平台(或者说是:比较重量级)。WCF的野心造成了它的庞大复杂,HTTP的单纯造就了它的简单优美。于是经常自问:拿着牛刀削苹果有必要吗?废话,当然没有必要,水果刀在哪里?因此,我们所需要的仅仅是里面HTTP REST风格的部分。各种因素纠结下,微软于是便把WCF里面的这部分团队抽离出来合并到了MVC组中,才有了现在的ASP.NET Web API,并包含在MVC 4中发布。

3.3 第一个WebAPI项目

(1)新建一个ASP.NET MVC项目,取名为:MyMvcWebAPIDemo,项目类型选择WebAPI。

(2)在Models中新增一个类,取名为:Product,作为我们要测试的实体模型。

1
2
3
4
5
6
7
public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }

(3)在Controllers中新增一个控制器,并选择“空WebAPI”类型模板,取名为:ProductController。

(4)为了方便进行数据测试,这里定义一个静态的产品集合。当然,在实际应用中,我们可能会从数据库中读取数据集合,并对其进行增删查改及各种查询操作。

1
2
3
4
5
6
7
8
static List<Product> products = new List<Product>
        {
            new Product { Id = 1, Name = "Nokia Lumia 1520", Category = "移动电话", Price = 3500 },
            new Product { Id = 2, Name = "Lenovo Thinkpad T430S", Category = "便携式计算机", Price = 8000 },
            new Product { Id = 3, Name = "锤子手机", Category = "移动电话", Price = 3300 } ,
            new Product { Id = 4, Name = "Wii", Category = "电视游戏机", Price = 1000 },
            new Product { Id = 5, Name = "Xbox 360", Category = "电视游戏机", Price = 3200 }
        };

(5)定义一些方法,用于对产品集合的各种操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
public class ProductController : ApiController
    {
        static List<Product> products = new List<Product>
        {
            new Product { Id = 1, Name = "Nokia Lumia 1520", Category = "移动电话", Price = 3500 },
            new Product { Id = 2, Name = "Lenovo Thinkpad T430S", Category = "便携式计算机", Price = 8000 },
            new Product { Id = 3, Name = "锤子手机", Category = "移动电话", Price = 3300 } ,
            new Product { Id = 4, Name = "Wii", Category = "电视游戏机", Price = 1000 },
            new Product { Id = 5, Name = "Xbox 360", Category = "电视游戏机", Price = 3200 }
        };
 
        /// <summary>
        /// GET
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Product> GetAllProducts()
        {
            return products.OrderBy(p => p.Id);
        }
 
        /// <summary>
        /// GET
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Product GetProductById(int id)
        {
            Product product = products.FirstOrDefault(p => p.Id == id);
            if (product == null)
            {
                var resp = new HttpResponseMessage(HttpStatusCode.NotFound);
                throw new HttpResponseException(resp);
            }
 
            return product;
        }
 
        /// <summary>
        /// GET
        /// </summary>
        /// <param name="productName">产品名</param>
        /// <returns></returns>
        public Product GetProductByName(string productName)
        {
            Product product = products.FirstOrDefault(p => p.Name.Contains(productName));
            if (product == null)
            {
                var resp = new HttpResponseMessage(HttpStatusCode.NotFound);
                throw new HttpResponseException(resp);
            }
 
            return product;
        }
 
        /// <summary>
        /// GET
        /// </summary>
        /// <param name="category">类型名称</param>
        /// <returns></returns>
        public IEnumerable<Product> GetAllProductsByCategory(string category)
        {
            if (category.Equals("--请选择--"))
            {
                return products;
            }
 
            IEnumerable<Product> productList = products.Where(
                p => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase));
            return productList.OrderBy(p => p.Id);
        }
 
        /// <summary>
        /// POST
        /// </summary>
        /// <returns></returns>
        public bool PostProduct(Product product)
        {
            int index = products.FindIndex(p => p.Name == product.Name);
            if (index != -1)
            {
                return false;
            }
            product.Id = products.Max(p => p.Id) + 1;
            products.Add(product);
            return true;
        }
 
        /// <summary>
        /// PUT
        /// </summary>
        /// <returns></returns>
        public bool PutProduct(int id, [FromBody]Product product)
        {
            int index = products.FindIndex(p => p.Id == id);
            if (index == -1)
            {
                return false;
            }
 
            products.RemoveAt(index);
            products.Add(product);
            return true;
        }
 
        /// <summary>
        /// DELETE
        /// </summary>
        /// <returns></returns>
        public bool DeleteProduct(int id)
        {
            Product product = products.FirstOrDefault(p => p.Id == id);
            if (product == null)
            {
                return false;
            }
 
            products.Remove(product);
            return true;
        }
    }

一般来说,Http的四种访问类型中,Get:一般用作查询,多次操作得到结果一致;Post:一般用于修改、添加多次重复操作得到结果不一致。Put:一般用于修改,多次操作得到结果一致。Delete:一般用于删除数据,多次操作得到结果一致。

现在,我们来看一下我们写的这些方法:

①用于GET方式获取的方法有:

GetAllProducts用于获取所有产品的集合;GetProductById用于返回指定Id的产品对象;

GetProductByName用户返回指定Name的产品对象;GetAllProductsByCategory则用户返回指定Category(种类)的产品集合;

②用于POST方式的方法有:

PostProduct用于增加一个产品信息;

③用于PUT方式的方法有:

PutProduct用于修改一个指定的产品信息;

④用于DELETE方式的方法有:

DeleteProduct用于删除一个选择的产品信息;

以上GET、POST、PUT、DELETE则构成了我们通过HTTP协议对资源的各种操作了。具体的代码,这里我就不过多赘述,相信大家都能看懂。

(6)此时,我们有了一个能工作的Web API了。该控制器上的每个方法都映射到一个URI,例如下表中所示的前三个方法所对应的URI:

Controller Method
控制器方法
URI
GetAllProducts /api/product
GetProductById /api/product/id
GetProductsByCategory /api/product/?category=category

客户端可以通过URI来访问我们的控制器已达到对资源的操作,那么,我们可以设计一个页面来发送AJAX请求来实践一下。

(7)在Views中的默认Home/Index这个页面中,加入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
<link href="~/Content/themes/easyui/bootstrap/easyui.css" rel="stylesheet" />
<link href="~/Content/themes/easyui/icon.css" rel="stylesheet" />
<header>
    <div class="content-wrapper">
        <div class="float-left">
            <p class="site-title">
                <a href="~/">ASP.NET Web API</a>
            </p>
        </div>
    </div>
</header>
<div id="body">
    <section class="featured">
        <div class="content-wrapper">
            @*<hgroup class="title">
                <h1>欢迎使用 ASP.NET Web API!</h1>
                <h2>这是一个简单的WebAPI入门Demo.</h2>
            </hgroup>*@
            <p>
                <strong>搜索:</strong>
                ①产品类型:
                    <select id="productTypes" name="productTypes" style="width: 120px; height: 34px;">
                        <option value="-1">--请选择--</option>
                        <option value="0">移动电话</option>
                        <option value="1">便携式计算机</option>
                        <option value="2">电视游戏机</option>
                    </select>
                ②产品名称:<input id="productName" name="productName" type="text" />
                <input id="btnSearchByName" name="btnSearchByName" type="button" value="搜 索" />
                <input id="btnSearchAll" name="searchAll" type="button" value="全 部" />
            </p>
            <p>
                <strong>新增:</strong>
                 
                产品名称:<input id="newProductName" name="newProductName" type="text" />
                产品类型:<select id="newProductType" name="newProductType" style="width: 120px; height: 34px;">
                    <option value="-1">--请选择--</option>
                    <option value="0">移动电话</option>
                    <option value="1">便携式计算机</option>
                    <option value="2">电视游戏机</option>
                </select>
                 
                产品价格:<input id="newProductPrice" name="newProductPrice" type="text" />
                <input id="btnPostProduct" name="btnPostProduct" type="button" value="新 增" />
            </p>
        </div>
    </section>
    <section class="content-wrapper main-content clear-fix">
        <h3>下面是从WebAPI获取的数据集:</h3>
        <div id="result">
        </div>
        @*<ol class="round">
            <li class="one">
                <h5>开始使用</h5>
                ASP.NET Web API  是一个框架,您可以通过该框架轻松生成可访问
                多种客户端(包括浏览器和移动设备)的 HTTP 服务。ASP.NET Web API
                是一个用于在 .NET Framework 之上生成 REST 样式的应用程序的理想平台。
                <a href="http://go.microsoft.com/fwlink/?LinkId=245160">了解详细信息...</a>
            </li>
        </ol>*@
    </section>
</div>
<!-- jBox modal -->
<div id="myMsgModal" class="notshow">
</div>
<!-- jBox edit modal -->
<div id="myEditModal" class="notshow">
    <input id="hiddProductId" type="hidden" />
    <table width="100%">
        <tr>
            <td align="right">产品名称:</td>
            <td>
                <input id="editProductName" name="editProductName" type="text" /></td>
        </tr>
        <tr>
            <td align="right">产品类型:</td>
            <td>
                <select id="editProductType" name="editProductType" style="width: 120px; height: 34px;">
                    <option value="-1">--请选择--</option>
                    <option value="0">移动电话</option>
                    <option value="1">便携式计算机</option>
                    <option value="2">电视游戏机</option>
                </select>
            </td>
        </tr>
        <tr>
            <td align="right">产品价格:</td>
            <td>
                <input id="editProductPrice" name="editProductPrice" type="text" />
            </td>
        </tr>
        <tr>
            <td colspan="2" align="center">
                <a id="btnPutProduct" href="#" class="easyui-linkbutton">确定</a>
                <a id="btnCloseModal" href="#" class="easyui-linkbutton">关闭</a>
            </td>
        </tr>
    </table>
</div>
@section scripts{
    <script src="~/Scripts/jquery-1.7.1.min.js"></script>
    <script src="~/Content/themes/easyui/jquery.easyui.min.js"></script>
    <script src="~/Content/themes/easyui/easyui-lang-zh_CN.js"></script>
    <script type="text/javascript">
        $(function () {
            initData();
            bindClick();
        });
 
        function initData() {
            $.getJSON("api/Product", function (data) {
                if (data != null) {
                    if ($("#resultList").length > 0) {
                        $("#resultList").remove();
                    }
 
                    var html = "<ol id='resultList' class='round'>";
                    $.each(data, function (key, value) {
                        html += "<li class='one'><h5>" + value.Name + "</h5>类型:" + value.Category
                            + " 价格:" + value.Price + "  | <a href='#' onclick='editProduct(" + value.Id + ")'>编辑</a><a href='#' onclick='deleteProduct(" + value.Id + ")'>删除</a></li>";
                    });
                    html += "</ol>";
                    $("#result").append(html);
                }
            });
        }
 
        function bindClick() {
            // 01.按产品类型搜索产品
            $("#productTypes").bind("change", function () {
                $.getJSON("api/Product", { category: $(this).find("option:selected").text() }, function (data) {
                    if (data != null) {
                        $("#resultList").remove();
                        var html = "<ol id='resultList' class='round'>";
                        $.each(data, function (key, value) {
                            html += "<li class='one'><h5>" + value.Name + "</h5>类型:" + value.Category
                                + " 价格:" + value.Price + "  | <a href='#' onclick='editProduct(" + value.Id + ")'>编辑</a><a href='#' onclick='deleteProduct(" + value.Id + ")'>删除</a></li>";
                        });
                        html += "</ol>";
                        $("#result").append(html);
                    }
                });
            });
            // 02.按产品名搜索产品
            $("#btnSearchByName").bind("click", function () {
                var searchName = $("#productName").val();
                if (searchName == "") {
                    showMsg("提示", "您还没有输入要搜索的产品名称");
                }
                $.getJSON("api/Product", { productName: searchName }, function (data) {
                    if (data != null) {
                        $("#resultList").remove();
                        var html = "<ol id='resultList' class='round'>";
                        html += "<li class='one'><h5>" + data.Name + "</h5>类型:" + data.Category
                                + " 价格:" + data.Price + "  | <a href='#' onclick='editProduct(" + data.Id + ")'>编辑</a><a href='#' onclick='deleteProduct(" + data.Id + ")'>删除</a></li>";
                        html += "</ol>";
                        $("#result").append(html);
                        clearText();
                    }
                });
            });
            // 03.搜索全部产品信息
            $("#btnSearchAll").bind("click", initData);
            // 04.新增一个产品信息
            $("#btnPostProduct").bind("click", function () {
                var productName = $("#newProductName").val();
                var productCategory = $("#newProductType").find("option:selected").text();
                var productPrice = $("#newProductPrice").val();
 
                if (productName == "") {
                    showMsg("提示", "请输入产品名称");
                }
                else if (productCategory == "" || productCategory == "--请选择--") {
                    showMsg("提示", "请选择产品类型");
                }
                else if (productPrice == "") {
                    showMsg("提示", "请输入产品价格");
                }
                else if (isNaN(productPrice)) {
                    showMsg("提示", "产品价格请输入数字类型");
                }
                else {
                    $.post("api/Product", {
                        Name: productName,
                        Category: productCategory,
                        Price: productPrice
                    }, function (data) {
                        if (data != null && data == true) {
                            initData();
                            clearText();
                            showMsg("提示", "添加新产品操作成功");
                        }
                        else {
                            showMsg("提示", "添加新产品操作失败");
                        }
                    });
                }
            });
            // 07.修改一个产品信息
            $("#btnPutProduct").bind("click", function () {
                var productId = $("#hiddProductId").val();
                $.ajax({
                    type: "PUT",
                    url: "/api/Product/" + productId,
                    data: {
                        Id: productId,
                        Name: $("#editProductName").val(),
                        Category: $("#editProductType").find("option:selected").text(),
                        Price: $("#editProductPrice").val()
                    },
                    success: function (data) {
                        if (data == true) {
                            initData();
                            $("#myEditModal").window("close");
                            showMsg("提示", "您已成功修改那玩意");
                        }
                        else {
                            showMsg("提示", "修改那玩意操作失败");
                        }
                    }
                });
            });
            // 关闭模态对话框
            $("#btnCloseModal").bind("click", function () {
                $("#myEditModal").window("close");
            });
        }
        // 05.编辑一个产品信息
        function editProduct(productId) {
            $.getJSON("api/Product", { id: productId }, function (data) {
                if (data != null) {
                    $("#hiddProductId").val(data.Id);
                    $("#editProductName").val(data.Name);
                    switch (data.Category) {
                        case "移动电话":
                            $("#editProductType").val("0");
                            break;
                        case "便携式计算机":
                            $("#editProductType").val("1");
                            break;
                        case "电视游戏机":
                            $("#editProductType").val("2");
                            break;
                    }
                    $("#editProductPrice").val(data.Price);
                }
            });
            $("#myEditModal").show();
            $("#myEditModal").window({
                title: "编辑产品信息",
                modal: true,
                collapsible: true,
                minimizable: false,
                maximizable: false,
                resizable: false,
                width: 500,
                height: 220
            });
        }
        // 06.删除一个产品信息
        function deleteProduct(productId) {
            $.messager.confirm("提示", "您确定要删除这玩意?", function (r) {
                if (r) {
                    $.ajax({
                        type: "DELETE",
                        url: "/api/Product/" + productId,
                        data: {},
                        success: function (data) {
                            if (data == true) {
                                initData();
                                showMsg("提示", "您已成功删除那玩意");
                            }
                            else {
                                showMsg("提示", "删除那玩意操作失败");
                            }
                        }
                    });
                }
            });
        }
 
        function showMsg(title, msg) {
            $.messager.alert(title, msg, "info");
        }
 
        function clearText() {
            $("input[type=text]").val("");
        }
    </script>
}

通过调试运行,可以看到以下页面效果,并可以看到,由于我们在页面中加入了获取产品列表的GET请求,于是产品信息被加载到了页面中:

其对应的JS语句为:可以看到,我们通过api/Product调用了API控制器中的GetAllProducts方法,获取了所有产品信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$.getJSON("api/Product", function (data) {
                if (data != null) {
                    if ($("#resultList").length > 0) {
                        $("#resultList").remove();
                    }
 
                    var html = "<ol id='resultList' class='round'>";
                    $.each(data, function (key, value) {
                        html += "<li class='one'><h5>" + value.Name + "</h5>类型:" + value.Category
                            + " 价格:" + value.Price + "  | <a href='#' onclick='editProduct(" + value.Id + ")'>编辑</a><a href='#' onclick='deleteProduct(" + value.Id + ")'>删除</a></li>";
                    });
                    html += "</ol>";
                    $("#result").append(html);
                }
});

(8)下面我们可以来试试其他的API方法:

3.4 第一个RestClient客户端项目

有了我们上面的WebAPI项目的支持,我们可以在客户端(如:WindowsForm项目、Windows
Phone项目等等)对WebAPI项目中的资源进行访问和操作,现在我们就来实现一个RestClient控制台项目模拟一个客户端对WebAPI发起
HTTP访问请求。

(1)新建一个控制台项目,取名为:MyConsoleRestClientDemo。

(2)新建一个类,取名为:RestClient.cs。它封装了我们常用的HTTP操作,如GET、POST、PUT、DELETE方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
public class RestClient
    {
        private string BaseUri;
        public RestClient(string baseUri)
        {
            this.BaseUri = baseUri;
        }
 
        #region Delete方式
        public string Delete(string data, string uri)
        {
            return CommonHttpRequest(data, uri, "DELETE");
        }
 
        public string Delete(string uri)
        {
            //Web访问对象64
            string serviceUrl = string.Format("{0}/{1}", this.BaseUri, uri);
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(serviceUrl);
            myRequest.Method = "DELETE";
            // 获得接口返回值68
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
            StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
            //string ReturnXml = HttpUtility.UrlDecode(reader.ReadToEnd());
            string ReturnXml = reader.ReadToEnd();
            reader.Close();
            myResponse.Close();
            return ReturnXml;
        }
        #endregion
 
        #region Put方式
        public string Put(string data, string uri)
        {
            return CommonHttpRequest(data, uri, "PUT");
        }
        #endregion
 
        #region POST方式实现
 
        public string Post(string data, string uri)
        {
            return CommonHttpRequest(data, uri, "POST");
        }
 
        public string CommonHttpRequest(string data, string uri, string type)
        {
            //Web访问对象,构造请求的url地址
            string serviceUrl = string.Format("{0}/{1}", this.BaseUri, uri);
 
            //构造http请求的对象
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(serviceUrl);
            //转成网络流
            byte[] buf = System.Text.Encoding.GetEncoding("UTF-8").GetBytes(data);
            //设置
            myRequest.Method = type;
            myRequest.ContentLength = buf.Length;
            myRequest.ContentType = "application/json";
            myRequest.MaximumAutomaticRedirections = 1;
            myRequest.AllowAutoRedirect = true;
            // 发送请求
            Stream newStream = myRequest.GetRequestStream();
            newStream.Write(buf, 0, buf.Length);
            newStream.Close();
            // 获得接口返回值
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
            StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
            string ReturnXml = reader.ReadToEnd();
            reader.Close();
            myResponse.Close();
            return ReturnXml;
        }
        #endregion
 
        #region GET方式实现
        public string Get(string uri)
        {
            //Web访问对象64
            string serviceUrl = string.Format("{0}/{1}", this.BaseUri, uri);
 
            //构造一个Web请求的对象
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(serviceUrl);
            // 获得接口返回值68
            //获取web请求的响应的内容
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
 
            //通过响应流构造一个StreamReader
            StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
            //string ReturnXml = HttpUtility.UrlDecode(reader.ReadToEnd());
            string ReturnXml = reader.ReadToEnd();
            reader.Close();
            myResponse.Close();
            return ReturnXml;
        }
        #endregion
    }

(3)在Program.cs中的Main方法中,调用RestClient类为我们提供的方法对WebAPI服务器(这里是本机:http://localhost:8080/)发起访问:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class Program
    {
        static string restfulServiceUri = "http://localhost:8080/";
 
        static void Main(string[] args)
        {
            RestClient restClient = new RestClient(restfulServiceUri);
 
            #region 01.Get方式无参数请求
            Console.WriteLine("----------------------获取所有产品列表-----------------------");
            string getResult = restClient.Get("api/Product");
            Console.WriteLine(getResult);
            Console.WriteLine();
            #endregion
 
            #region 02.Get方式带参数请求
            Console.WriteLine("----------------------获取Id=1的产品信息-----------------------");
            string getByIdResult = restClient.Get("api/Product/1");
            Console.WriteLine(getByIdResult);
            Console.WriteLine();
            Console.WriteLine("----------------------获取Name=锤子手机的产品信息-----------------------");
            string getByNameResult = restClient.Get("api/Product/?productName=锤子手机");
            Console.WriteLine(getByNameResult);
            Console.WriteLine();
            Console.WriteLine("----------------------获取Category=移动电话的产品信息-----------------------");
            string getByTypeResult = restClient.Get("api/Product/?category=移动电话");
            Console.WriteLine(getByTypeResult);
            Console.WriteLine();
            #endregion
 
            #region 03.Post方式请求结果
            //Console.WriteLine("----------------------新增一个产品信息-----------------------");
            //string jsonParam = @"{Id:""250"",Name:""小米2S"",Category:""移动电话"",Price:""1800""}";
            //string postResult = restClient.Post(jsonParam, "api/Product");
            //Console.WriteLine(postResult);
            //getResult = restClient.Get("api/Product");
            //Console.WriteLine(getResult);
            //Console.WriteLine();
            #endregion
 
            #region 04.Delete方式请求结果
            //Console.WriteLine("----------------------删除一个产品信息-----------------------");
            //string deleteId = "6";
            //string deleteResult = restClient.Delete("api/Product/" + deleteId);
            //Console.WriteLine(deleteResult);
            //getResult = restClient.Get("api/Product");
            //Console.WriteLine(getResult);
            //Console.WriteLine();
            #endregion
 
            #region 05.Put方式请求结果
            Console.WriteLine("----------------------修改一个产品信息-----------------------");
            string jsonParam = @"{Id:""5"",Name:""PlayStation 3"",Category:""电视游戏机"",Price:""3200""}";
            string putResult = restClient.Put(jsonParam, "api/Product/5");
            Console.WriteLine(putResult);
            getResult = restClient.Get("api/Product");
            Console.WriteLine(getResult);
            Console.WriteLine();
            #endregion
 
            Console.ReadKey();
        }
    }

(4)调试运行,查看访问结果如下:可以看出,返回的均为JSON格式的数据,和我们在浏览器中访问指定URI的结果一致。

3.5 初探小结

ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务。 ASP.NET Web API 是一种用于在 .NET Framework 上构建 RESTful 应用程序的理想平台。

参考文章

(1)搏击的小船,《ASP.NET MVC2 Areas区域新概念》,http://www.cnblogs.com/guanjie20/archive/2010/09/09/1822175.html

(2)游响云停,《ASP.NET MVC3细嚼慢咽-(2)模板页 》,http://blog.csdn.net/zx13525079024/article/details/8301943

(3)李林峰,《无废话MVC入门教程四[视图中的Layout使用]》,http://www.cnblogs.com/iamlilinfeng/archive/2013/02/28/2934397.html

(4)阮一峰,《理解Restful架构》,http://www.ruanyifeng.com/blog/2011/09/restful.html

(5)便当之神,《ASP.Net WebAPI》,http://www.cnblogs.com/bnbqian/archive/2012/06/28/2565417.html

(6)dudu,《HttpClient + ASP.NET Web API, WCF之外的另一个选择》,http://www.cnblogs.com/dudu/archive/2012/05/11/asp_net_webapi_httpclient.html

附件下载

(1)MyWebAPIDemo:http://pan.baidu.com/s/1hqzgwb6

ASP.Net MVC开发基础学习笔记(5):区域、模板页与WebAPI初步的更多相关文章

  1. ASP.Net MVC开发基础学习笔记:一、走向MVC模式

    一.ASP.Net的两种开发模式 1.1 ASP.Net WebForm的开发模式 (1)处理流程 在传统的WebForm模式下,我们请求一个例如http://www.aspnetmvc.com/bl ...

  2. ASP.Net MVC开发基础学习笔记(1):走向MVC模式

    一.ASP.Net的两种开发模式 1.1 ASP.Net WebForm的开发模式 (1)处理流程 在传统的WebForm模式下,我们请求一个例如http://www.aspnetmvc.com/bl ...

  3. ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法

    一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归. ...

  4. ASP.Net MVC开发基础学习笔记:三、Razor视图引擎、控制器与路由机制学习

    一.天降神器“剃须刀” — Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留 ...

  5. ASP.Net MVC开发基础学习笔记:四、校验、AJAX与过滤器

    一.校验 — 表单不是你想提想提就能提 1.1 DataAnnotations(数据注解) 位于 System.ComponentModel.DataAnnotations 命名空间中的特性指定对数据 ...

  6. ASP.Net MVC开发基础学习笔记:五、区域、模板页与WebAPI初步

    一.区域—麻雀虽小,五脏俱全的迷你MVC项目 1.1 Area的兴起 为了方便大规模网站中的管理大量文件,在ASP.NET MVC 2.0版本中引入了一个新概念—区域(Area). 在项目上右击创建新 ...

  7. ASP.Net MVC开发基础学习笔记(4):校验、AJAX与过滤器

    一.校验 — 表单不是你想提想提就能提 1.1 DataAnnotations(数据注解) 位于 System.ComponentModel.DataAnnotations 命名空间中的特性指定对数据 ...

  8. ASP.Net MVC开发基础学习笔记(3):Razor视图引擎、控制器与路由机制学习

    一.天降神器“剃须刀” — Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留 ...

  9. ASP.Net MVC开发基础学习笔记(2):HtmlHelper与扩展方法

    一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归. ...

随机推荐

  1. oracle触发器加条件判断、dblink

    --新增基站同步给电池组信息 create or replace trigger a_b_test after insert or update or delete on BJLT.BASESTATI ...

  2. jquery.validate ajax提交

    页面引入jquery.validate.min.js <style> //引入错误格式     label.error {        display: block;        ma ...

  3. linux下mysql开启关和重启

    开启: /etc/init.d/mysql start关闭: /etc/init.d/mysql stop重启: /etc/init.d/mysql restart 查看字符集show variabl ...

  4. LeetCode 217 Contains Duplicate

    Problem: Given an array of integers, find if the array contains any duplicates. Your function should ...

  5. supersr--addSubview和 insertSubView 区别

    A addSubview B  是将B直接覆盖在A的最上层  例子: [self.view addSubview:scrollView]; A insertSubView B AtIndex:2 是将 ...

  6. LTS学习

    下载 例子 安装部署zookeeper 运行根目录下的sh build.sh或build.cmd脚本 --> 会在dist目录下生成lts-{version}-bin文件夹(bin里有启动命令) ...

  7. IOS开发之实现App消息推送

    转自:http://blog.csdn.net/shenjie12345678/article/details/41120637 第一部分 首先第一步当然是介绍一下苹果的推送机制(APNS)咯(ps: ...

  8. Mac系统下使用VirtualBox虚拟机安装win7--第一步 安装vbox虚拟机

    Mac系统下使用VirtualBox虚拟机安装win7操作步骤: 第一步 安装vbox虚拟机 1.先下载vbox,下载地址:: https://www.virtualbox.org/wiki/Down ...

  9. Java -- 找不到或无法加载主类

    原文:http://wenku.baidu.com/link?url=5nS1GEaePn-hmtAg6xXdJvtt9Z89JQsakhqSv8fambaJY2t9nKPtf3hXFpjW-BtD9 ...

  10. ASP.NET MVCでResponse Headerのサーバーバージョンをどうやって隠しますか?

    本来是发布在客户的Wiki上的,所以用日语写. ---------------------------------------------------------------------------- ...