可以使用HttpClient这个调用Web API,下面是HttpClient的定义,列举了一些常用的方法,其中还有一些没有列举,包括重载的方法。

public class HttpClient : HttpMessageInvoker
{
public HttpClient();
public HttpClient(HttpMessageHandler handler); //统一资源标识符 (URI) 的基地址
public Uri BaseAddress { get; set; }
//获取或设置请求超时前等待的毫秒数
public TimeSpan Timeout { get; set; } //发送异步GET请求
public Task<HttpResponseMessage> GetAsync(Uri requestUri);
//发送异步POST请求
public Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content);
//发生异步请求,可以指定HTTP动作
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request);
}

HttpClient的使用

上面几个方法GetAsync、PostAsync、SendAsync的返回值类型都是Task<HttpResponseMessage>,可以调用Task<TResult>.Result属性获得类型为HttpResponseMessage的实例。HttpResponseMessage的Content属性有一个异步方法ReadAsStringAsync可以获得响应消息体的内容(服务端传过来的字符串),使用ReadAsAsync<T>方法已获得反序列化后的CLR类型数据。

例:读取字符串。

为了看清返回类型,客户端每个方法的调用返回值赋给一个强类型的变量,方便观察返回值和理解,也可以将返回值变量赋给一个var类型的变量。

客户端:

        public static void TestClient()
{
string url = "http://localhost/webApi_test/api/testapi";
using (HttpClient client = new HttpClient())
{
Task<HttpResponseMessage> taskResult = client.GetAsync(url);
HttpResponseMessage responseMessage = taskResult.Result;
Task<string> contentStr = responseMessage.Content.ReadAsStringAsync();
contentStr.Wait();
Console.WriteLine(contentStr.Result);
}
Console.ReadLine();
}

服务端:

public class TestApiController : ApiController
{
public IHttpActionResult Get()
{
return Ok("hello web api client");
}
}

路由配置:

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);

例:获得实体,并序列化显示

调用响应的Content.ReadAsAsync<T>方法获得实体。

客户端:

        public static void TestClient()
{
string url = "http://localhost/webApi_test/api/testapi/1";
using (HttpClient client = new HttpClient())
{
Task<HttpResponseMessage> taskResult = client.GetAsync(url);
HttpResponseMessage responseMessage = taskResult.Result;
Task<DataModel> model = responseMessage.Content.ReadAsAsync<DataModel>();
model.Wait();
Console.WriteLine(JsonConvert.SerializeObject(model.Result,Formatting.Indented));
}
Console.ReadLine();
}

服务端(路由配置同上):

        public IHttpActionResult Get(int id = )
{
DataModel model = new DataModel { Id = id, Field1Name = "f1", Field2Name = "f2", DT = DateTime.Now };
return Ok(model);
}

返回结果:

例:客户端向服务端传递复杂数据。

使用SendAsync方法,但是注意无法发送GET和HEAD请求。下面的例子向服务端发送PUT请求,并且将发送给服务端的数据放入了请求消息的消息体中,为了让服务端获取消息体内容的格式信息以便其选择多媒体格式化器绑定模型,将HttpContent.Headers.ContentType设置为application/json类型,因为向请求消息体中写入的是JSON格式的字符串。

客户端:

public static void TestClient()
{
string url = "http://localhost/webApi_test/api/testapi";
var modelRequest = new { Id = , Field1Name = "1name", Field2Name = "2name", DT = DateTime.Now };
using (HttpClient client = new HttpClient())
{
using (HttpContent content = new StringContent(JsonConvert.SerializeObject(modelRequest)))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Put, url))
{
request.Content = content;
Task<HttpResponseMessage> taskResult = client.SendAsync(request);
HttpResponseMessage responseMessage = taskResult.Result;
Task<DataModel> model = responseMessage.Content.ReadAsAsync<DataModel>();
model.Wait();
Console.WriteLine(JsonConvert.SerializeObject(model.Result, Formatting.Indented));
}
}
}
Console.ReadLine();
}

服务端:

public IHttpActionResult Put(DataModel model)
{
return Ok(model);
}

路由:

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }

例:将数据写入请求消息体的方式

有几种方式为HttpRequestMessage.Content属性赋值,可以使用FormUrlEncodedContent、StringContent,他们都派生自ByteArrayContent。FormUrlEncodedContent指定的多媒体格式为application/x-www-form-urlencoded,如果将写入请求消息体的内容格式设置为application/x-www-form-urlencoded,即HttpContent.Headers.ContentType = application/x-www-form-urlencoded,可以正常传递数据,不设置就默认指定为application/x-www-form-urlencoded类型。

客户端调用

            var list = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Field21", "f1"),
new KeyValuePair<string, string>("Field22", "f2")
};
using (HttpClient client = new HttpClient())
{
using (HttpContent content = new FormUrlEncodedContent(list))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url))
{
request.Content = content;
Task<HttpResponseMessage> taskResult = client.SendAsync(request);
HttpResponseMessage responseMessage = taskResult.Result;
Task<Model2> model = responseMessage.Content.ReadAsAsync<Model2>();
model.Wait();
Console.WriteLine(JsonConvert.SerializeObject(model.Result, Formatting.Indented));
}
}
}
Console.ReadLine();

服务器:

        public IHttpActionResult Post(Model2 model)
{
return Ok(model);
} public class Model2
{
public string Field21 { get; set; }
public string Field22 { get; set; }
}

运行结果:

如果将上述客户端代码的content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

改为:content.Headers.ContentType = new MediaTypeHeaderValue("application/json"),则服务端无法正常为操作参数赋值:

此外FormUrlEncodedContent不适合传递集合或数据模型中属性为集合类型的实体。如下面的实体类型,若服务端接收的参数类型为Model1,则不适合使用FormUrlEncodedContent。而应使用StringContent

public class Model1
{
public List<Model2> List1 { get; set; }
public string Name { get; set; }
} public class Model2
{
public string Field21{get;set;}
public string Field22{get;set;}
}

例:使用HttpClientExtensions

HttpClientExtensions提供了HttpClient的扩展方法,PostAsJsonAsync<T>可以将实体T序列化为JSON格式放入请求消息体中,同样地PutAsJsonAsync也如此,只不过前者发送POST请求后者发送PUT请求。另外,他们的重载方法可以指定多媒体格式化器。

客户端:

            string url = "http://localhost/webApi_test/api/testapi";
List<Model2> model2List = new List<Model2> { new Model2 { Field21 = "f1", Field22 = "f2" }, new Model2 { Field21 = "f21", Field22 = "f22" } };
Model1 model = new Model1 { Name = "集合", List1 = model2List }; using (HttpClient client = new HttpClient())
{
Task<HttpResponseMessage> taskResult = client.PostAsJsonAsync(url,model);
HttpResponseMessage responseMessage = taskResult.Result;
Task<Model1> models = responseMessage.Content.ReadAsAsync<Model1>();
models.Wait();
Console.WriteLine(JsonConvert.SerializeObject(models.Result, Formatting.Indented));
}
Console.ReadLine();

服务端:

        public IHttpActionResult Post(Model1 model)
{
return Ok(model);
} public class Model1
{
public List<Model2> List1 { get; set; }
public string Name { get; set; }
} public class Model2
{
public string Field21 { get; set; }
public string Field22 { get; set; }
}

结果:

指定格式化器,下面例子指定了JSON格式化器,也可以指定BSON格式化器。

            string url = "http://localhost/webApi_test/api/testapi";
List<Model2> model2List = new List<Model2> { new Model2 { Field21 = "f1", Field22 = "f2" }, new Model2 { Field21 = "f21", Field22 = "f22" } };
Model1 model = new Model1 { Name = "集合", List1 = model2List }; using (HttpClient client = new HttpClient())
{
Task<HttpResponseMessage> taskResult = client.PostAsync(url, model, new JsonMediaTypeFormatter());
HttpResponseMessage responseMessage = taskResult.Result;
Task<Model1> models = responseMessage.Content.ReadAsAsync<Model1>();
models.Wait();
Console.WriteLine(JsonConvert.SerializeObject(models.Result, Formatting.Indented));
}
Console.ReadLine();

指定BSON格式化器,并且解析响应时也要指定为BOSN格式化器,同时需要注意的是,Web API默认配置没有包含BSON格式化器,所以要在服务端添加BSON格式化器。

            string url = "http://localhost/webApi_test/api/testapi";
List<Model2> model2List = new List<Model2> { new Model2 { Field21 = "f1", Field22 = "f2" }, new Model2 { Field21 = "f21", Field22 = "f22" } };
Model1 model = new Model1 { Name = "集合", List1 = model2List }; using (HttpClient client = new HttpClient())
{
Task<HttpResponseMessage> taskResult = client.PostAsync(url, model, new BsonMediaTypeFormatter());
HttpResponseMessage responseMessage = taskResult.Result;
Task<Model1> models = responseMessage.Content.ReadAsAsync<Model1>(new List<BsonMediaTypeFormatter> { new BsonMediaTypeFormatter() });
models.Wait();
Console.WriteLine(JsonConvert.SerializeObject(models.Result, Formatting.Indented));
}
Console.ReadLine();

---------------------------------------------------------------------

转载与引用请注明出处。

时间仓促,水平有限,如有不当之处,欢迎指正。

ASP.NET Web API编程——客户端调用的更多相关文章

  1. ASP.NET Web API编程——路由

    路由过程大致分为三个阶段: 1)请求URI匹配已存在路由模板 2)选择控制器 3)选择操作 1匹配已存在的路由模板 路由模板 在WebApiConfig.Register方法中定义路由,例如模板默认生 ...

  2. ASP.NET Web API编程——序列化与内容协商

    1 多媒体格式化器 多媒体类型又叫MIME类型,指示了数据的格式.在HTTP协议中多媒体类型描述了消息体的格式.一个多媒体类型包括两个字符串:类型和子类型. 例如: text/html.image/p ...

  3. asp.net web api 向客户端返回错误信息

    1使用Http状态码 ASP.NET Web Api框架提供了Http状态码的值,如下图所示. 虽然有这些预定义的状态码,但在实际项目中使用自定状态码结合预定义状态码更有优势. 通过在适当的位置抛出异 ...

  4. ASP.NET Web API编程——构建api帮助文档

    1 概要 创建ASP.NET Web Api 时模板自带Help Pages框架. 2 问题 1)使用VS创建Web Api项目时,模板将Help Pages框架自动集成到其中,使得Web Api项目 ...

  5. ASP.NET Web API编程——模型验证与绑定

    1.模型验证 使用特性约束模型属性 可以使用System.ComponentModel.DataAnnotations提供的特性来限制模型. 例如,Required特性表示字段值不能为空,Range特 ...

  6. ASP.NET Web API编程——文件上传

    首先分别介绍正确的做法和错误的做法,然后分析他们的不同和错误之处,以便读者在实现此功能时可避开误区 1正确的做法 public class AvaterController : BaseApiCont ...

  7. ASP.NET Web API编程——异常捕获

    1 向客户端发送错误消息 使用throw new HttpResponseException()向客户端抛出错误信息. HttpResponseException包含两个重载的构造函数,其中一个是构造 ...

  8. ASP.NET Web API编程——文件下载

    断点续传基本原理 HTTP协议中与断点续传相关的HTTP头为:Range和Content-Range标头,断点续传实现流程: 1)客户端请求下载一个文件,文件的总长度为n:已经下载了一部分文件,长度为 ...

  9. ASP.NET Web API 实现客户端Basic(基本)认证 之简单实现

    优点是逻辑简单明了.设置简单. 缺点显而易见,即使是BASE64后也是可见的明文,很容易被破解.非法利用,使用HTTPS是一个解决方案. 还有就是HTTP是无状态的,同一客户端每次都需要验证. 实现: ...

随机推荐

  1. 删除trigger 禁用触发器 启用触发器 查看触发器

    删除trigger drop trigger 触发器名 on 在那个表上 禁用触发器 Alter Table 表名 disable trigger 触发器名 启用触发器 Alter Table 表名 ...

  2. Apache Commons Email 使用网易企业邮箱发送邮件

    最近使用HtmlEmail 发送邮件,使用网易企业邮箱,发送邮件,死活发不出去!原以为是网易企业邮箱,不支持发送邮箱,后面经过研究发现,是apache htmlEmail 的协议导致,apache E ...

  3. python模块之matplotlib

    官方网址:http://matplotlib.org/tutorials/introductory/lifecycle.html#sphx-glr-tutorials-introductory-lif ...

  4. CF Dima and To-do List

    B. Dima and To-do List time limit per test 1 second memory limit per test 256 megabytes input standa ...

  5. Django之路由、模板和模型系统 (转载)

    一.路由系统 浏览器会自动给url后加一个“/” django会自动给路由的正则表达式前面加一个“/” django会给任何不带“/”结尾的url语句添加“/”(可设置) 短路路由规则:匹配到第一条就 ...

  6. react-native一些好的组件

    一.移动端路由 react-navigator 二.移动端本地储存 react-native-storage(https://github.com/sunnylqm/react-native-stor ...

  7. webpack-loader原理

    loader loader 是导出为一个函数的 node 模块.该函数在 loader 转换资源的时候调用.给定的函数将调用 loader API,并通过 this 上下文访问. loader配置 { ...

  8. 车厢调度(train.cpp)

    车厢调度(train.cpp) [问题描述]        有一个火车站,铁路如图所示,每辆火车从A驶入,再从B方向驶出,同时它的车厢可以重新组合.假设从A方向驶来的火车有n节(n<=1000) ...

  9. FCKeditor 添加行距、字体功能 (转载)

    一.首先为FCKeditor添加外部插件在fckeditor/editor/plugins文件夹下建立新文件夹lineHeight,并在其中创建fckplugin.js文件,在其文件中办輸入代码:FC ...

  10. Keras 时序模型

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Thinking_boy1992/article/details/53207177 本文翻译自 时序模 ...