热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用ASP.NetWebAPI构建REST服务

一、创建WebAPI应用程序1、WebAPI1版本首先创建一个Asp.NetMVC4Web应用程序(我这里用的是VisualStudio2012)。在出来的模板中选择WebAPI。

一、创建WebAPI应用程序

1、Web API 1版本

首先创建一个Asp.Net MVC 4 Web应用程序(我这里用的是Visual Studio 2012)。

技术分享图片

在出来的模板中选择Web API。点击确定后,就创建了一个空的WebAPI服务。

技术分享图片

2、 Web API 2版本

技术分享图片

点击确定后,就创建了一个空的WebAPI服务。此时只有一个空项目,还没有任何功能

在进行下一步之前,首先我们来看一下REST的基本操作模型,大致可以分为如下四种:

  • POST — 创建资源
  • GET — 检索资源
  • PUT — 更新资源
  • DELETE — 删除资源

非常经典的CRUD模型。

在Web API中实现这样一个的模型是非常简单的,直接使用向导建一个Controller即可

技术分享图片

技术分享图片

在Web API中生成默认的ValuesController

技术分享图片

默认的模板内容如下:

public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
// POST api/values
public void Post([FromBody]string value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}

这其实已经帮我们实现了一个最基本的服务了,不过这个服务中只实现了Get,它支持如下两种中方式的URL访问(其它的方式也能访问,但没有具体的效果):

  • api/values        访问所有的Value列表   

  • api/values/{id}        根据ID访问Value

按Ctrl + F5中执行,在浏览器中输入相应的地址即可看到结果

技术分享图片

下面我们要做的就是完善它,实现一个简单的查询功能,这里我引用了微软官方的一个例子:

public class ProductsController : ApiController
{
Product[] products
= new Product[]
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
public IEnumerable Get()
{
return products;
}
public IHttpActionResult Get(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}

此时,我们就可以在浏览器中看到结果了(由于Controller改名字了,此时的地址就变成了api/products)

技术分享图片

到此为止,一个基于Asp.net Web API的 简单的REST Web服务就构建完成了,由于篇幅所限,这里就不做更多的介绍了,跟多信息可以参看微软官方文档:Getting Started with ASP.NET Web API 2。

备注:WebAPI升级到 WebAPI 2如下命令更新web Api:

Install-Package Microsoft.AspNet.WebApi

二、路由

REST并没有像传统的RPC服务那样显式指定了服务器函数的访问路径,而是将URL根据一定的规则映射为服务函数入口,这个规则就称之为路由。Asp.Net WebAPI的路由方式和Asp.Net MVC是相同的,它支持两种路由方式,传统的路由映射和特性路由。 路由规则WebApiConfig.cs中定义。

技术分享图片

它的默认内容如下:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name:
"DefaultApi",
routeTemplate:
"api/{controller}/{id}",
defaults:
new { id = RouteParameter.Optional }
);
}
}

它默认注册了两种路由规则,第一行注册的是特性路由,第二行注册的则是传统的映射路由。默认情况下,由于我们没有编写特性路由规则,则是按照传统的Controller方式映射路由。

关于路由规则,MSDN文档ASP.NET 路由介绍得非常详细,但由于其介绍得太详细了,反而不容易得其门而入,这里我只拿默认的路由规则来简单但的介绍一下我的理解,它的uri格式是这样的"api/{controller}/{id}",其中id是可选的。拿前文的例子来说吧,

  1. 当我们对api/products地址进行访问的时候,系统则会首先找到名为ProductsController的控制器。
  2. 然后,根据访问方式查找函数,由于这里是Get操作,则查找Get开头的函数, 这里会找到Get()和Get(int id)两个重载版本。
  3. 最后,根据参数来匹配具体的函数,因为这里没有带参数id。因此匹配到了Get()函数,返回了所有的集合。

另外,这里也有几个常用的衍生规则:

  1. 根据操作方式找函数的时候,只需要匹配首部即可,因此我们编写函数的时候写成Get()和GetProduct()都是可以的。,
  2. 根据操作方式找函数的时候查找的时候不分大小写,因此写成Get()或get()都是可以的

当我们使用带参数的版本时候,也有几个需要注意的地方:

  1. 参数名不分大小写,我们写成id或ID都是可以的
  2. 参数名要求严格匹配的,我们写成ID2是不行的,此时则会匹配到错误的结果Get()

默认的规则虽然大多数的时候还是比较方便的,但是很多时候我们需要手动指定个性化的路由规则。例如,我们可以自定义一个按名称来查询的url:api/products/name=xxx。这个时候则可以用特性路由快速的实现了:

[Route("api/{controller}/name={name}")]
public IHttpActionResult GetByName(string name)

关于特性路由,MSDN原文Attribute Routing in ASP.NET MVC 5介绍得非常详细,国内也有非常不错的译文版本Attribute Routing in ASP.NET MVC 5 翻译及补充,这里就不做多少介绍了。

三、返回值

Asp.Net WebAPI服务函数的返回值主要可以分为void、普通对象、HttpResponseMessag、IHttpActionResult e四种,本文这里简单的介绍一下它们的区别。

1、返回void

返回void一般常用于Put和Delete函数。

public void Delete(int id)
{
}

当服务函数执行完成后,服务器端并不是啥都不干直接把客户端给断掉,而是发送一个标准的204 (No Content)的Http应答给客户端。

    HTTP/1.1 204 No Content
    Cache-Control: no-cache
    Pragma: no-cache
    Expires: -1
    Server: Microsoft-IIS/8.0
    X-AspNet-Version: 4.0.30319
    X-SourceFiles: =?UTF-8?B?Zjpc5paH5qGjXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVx2YWx1ZXNcMQ==?=
    X-Powered-By: ASP.NET
    Date: Fri, 02 May 2014 13:32:07 GMT

2、返回普通对象

返回普通对象时,服务器将返回的对象序列化后(默认是json),通过Http应答返回给客户端。例如,

public class ValuesController : ApiController
{
public string Get()
{
return "hello";
}
}

此时的返回结果是:

    HTTP/1.1 200 OK
    Cache-Control: no-cache
    Pragma: no-cache
    Content-Type: application/json; charset=utf-8
    Expires: -1
    Server: Microsoft-IIS/8.0
    X-AspNet-Version: 4.0.30319
    X-SourceFiles: =?UTF-8?B?Zjpc5paH5qGjXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVx2YWx1ZXM=?=
    X-Powered-By: ASP.NET
    Date: Fri, 02 May 2014 12:54:18 GMT
    Content-Length: 7
"hello"

异步返回普通对象:

WebAPI也是支持异步返回对象的:

public async Task<string> Get()
{
await Task.Delay(100);
return "hello";
}

异步返回的时候,服务器异步等待函数执行完成后再将返回值返回给对象。由于这个过程对于客户端来说是透明的,这里就不列举报文了。

3、返回HttpResponseMessage

HttpResponseMessage是标准Http应答了,此时服务器并不做任何处理,直接将HttpResponseMessage发送给客户端。

public HttpResponseMessage Get()
{
var respOnse= Request.CreateResponse(HttpStatusCode.OK);
response.Content
= new StringContent("hello", Encoding.UTF8);

return response;
}

此时的返回结果如下:

    HTTP/1.1 200 OK
    Cache-Control: no-cache
    Pragma: no-cache
    Content-Length: 5
    Content-Type: text/plain; charset=utf-8
    Expires: -1
    Server: Microsoft-IIS/8.0
    X-AspNet-Version: 4.0.30319
    X-SourceFiles: =?UTF-8?B?Zjpc5paH5qGjXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVx2YWx1ZXM=?=
    X-Powered-By: ASP.NET
    Date: Fri, 02 May 2014 13:09:57 GMT
hello

可以看到,这里返回的content-type仍然是原始定义的text类型,而不是json。要实现想上面的例子所示的结果,则需要将Get函数改写为如下形式

public HttpResponseMessage Get()
{
return Request.CreateResponse(HttpStatusCode.OK, "hello");
}

4、返回IHttpActionResult

IHttpActionResult是Web API 2中引入的一个接口,它的定义如下:

public interface IHttpActionResult
{
Task
ExecuteAsync(CancellationToken cancellationToken);
}

从它的定义可以看出,IHttpActionResult是HttpResponseMessage的一个工厂类,最终还是用于构建HttpResponseMessage返回,由于它可以取消,因而可以实现更为强大的返回功能(如流传输)。当服务函数返回IHttpActionResult对象时,服务器执行该对象的ExecuteAsync函数,并异步等待至函数完成后,获取其返回值HttpResponseMessage输出给客户端。

IHttpActionResult是WebAPI中推荐的标准返回值,ApiController类中也提供了不少标准的工厂函数方便我们快速构建它们,如BadRequest,Conflict,Ok,NotFound等,一个简单的示例如下:

public IHttpActionResult Get(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}


推荐阅读
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 本文介绍如何使用 NSTimer 实现倒计时功能,详细讲解了初始化方法、参数配置以及具体实现步骤。通过示例代码展示如何创建和管理定时器,确保在指定时间间隔内执行特定任务。 ... [详细]
  • Vue 2 中解决页面刷新和按钮跳转导致导航栏样式失效的问题
    本文介绍了如何通过配置路由的 meta 字段,确保 Vue 2 项目中的导航栏在页面刷新或内部按钮跳转时,始终保持正确的 active 样式。具体实现方法包括设置路由的 meta 属性,并在 HTML 模板中动态绑定类名。 ... [详细]
  • 本文探讨了如何通过最小生成树(MST)来计算严格次小生成树。在处理过程中,需特别注意所有边权重相等的情况,以避免错误。我们首先构建最小生成树,然后枚举每条非树边,检查其是否能形成更优的次小生成树。 ... [详细]
  • QUIC协议:快速UDP互联网连接
    QUIC(Quick UDP Internet Connections)是谷歌开发的一种旨在提高网络性能和安全性的传输层协议。它基于UDP,并结合了TLS级别的安全性,提供了更高效、更可靠的互联网通信方式。 ... [详细]
  • 深入理解OAuth认证机制
    本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ... [详细]
  • 2023 ARM嵌入式系统全国技术巡讲旨在分享ARM公司在半导体知识产权(IP)领域的最新进展。作为全球领先的IP提供商,ARM在嵌入式处理器市场占据主导地位,其产品广泛应用于90%以上的嵌入式设备中。此次巡讲将邀请来自ARM、飞思卡尔以及华清远见教育集团的行业专家,共同探讨当前嵌入式系统的前沿技术和应用。 ... [详细]
  • 本文详细分析了JSP(JavaServer Pages)技术的主要优点和缺点,帮助开发者更好地理解其适用场景及潜在挑战。JSP作为一种服务器端技术,广泛应用于Web开发中。 ... [详细]
  • 本文介绍了如何使用jQuery根据元素的类型(如复选框)和标签名(如段落)来获取DOM对象。这有助于更高效地操作网页中的特定元素。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 本文探讨了在不使用服务器控件的情况下,如何通过多种方法获取并修改页面中的HTML元素值。除了常见的AJAX方式,还介绍了其他可行的技术方案。 ... [详细]
  • 本文介绍如何在应用程序中使用文本输入框创建密码输入框,并通过设置掩码来隐藏用户输入的内容。我们将详细解释代码实现,并提供专业的补充说明。 ... [详细]
  • 本文介绍如何通过SQL查询从JDE(JD Edwards)系统中提取所有字典数据,涵盖关键表的关联和字段选择。具体包括F0004和F0005系列表的数据提取方法。 ... [详细]
  • 本文详细介绍了如何通过命令行启动MySQL服务,包括打开命令提示符窗口、进入MySQL的bin目录、输入正确的连接命令以及注意事项。文中还提供了更多相关命令的资源链接。 ... [详细]
author-avatar
手机用户2502881927
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有