WebApi接口 - 如何在应用中调用webapi接口
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebApi接口 - 如何在应用中调用webapi接口相关的知识,希望对你有一定的参考价值。
简单做个webapi(查询+添加)接口
首先,我们需要有一个webapi接口项目,我这里以前面WebApi接口 - 响应输出xml和json文章的项目来构建本篇文章的测试用例;这里新建一个 DbData 数据源类,主要用来做数据存储和提供查询列表数据及添加数据方法,具体代码如:
1 public class DbData 2 { 3 public static DbData Current 4 { 5 get 6 { 7 var key = "dbKey"; 8 var db = CallContext.GetData(key) as DbData; 9 if (db == null)10 {11 db = new DbData();12 CallContext.SetData(key, db);13 }14 return db;15 }16 }17 18 19 private static List<MoStudent> students = new List<MoStudent>(){ 20 new MoStudent{ Id =1 , Name ="小1", Sex = true, Birthday= Convert.ToDateTime("1991-05-31")},21 new MoStudent{ Id =2 , Name ="小2", Sex = false, Birthday= Convert.ToDateTime("1991-05-31")},22 new MoStudent{ Id =3 , Name ="小3", Sex = false, Birthday= Convert.ToDateTime("1991-05-31")},23 new MoStudent{ Id =4 , Name ="小4", Sex = true, Birthday= Convert.ToDateTime("1991-05-31")}24 };25 26 public List<MoStudent> GetAll()27 {28 return students;29 }30 31 public bool Save(MoStudent moStudent)32 {33 moStudent.Id = students.Max(b => b.Id) + 1;34 students.Add(moStudent);35 return true;36 }37 }
然后,需要在 ValuesController.cs 文件中增加调用数据源类 DbData ,代码: private DbData db = DbData.Current; 这里使用了 DbData 类中的Current属性来获取DbData的实例化对象,这里和大家简单说下这样做的好处在于统一管理调用类的实例,因为我们创建的某个操作类后,可能会在不同的文件或不同业务中调用,如果想调用其内部方法,那么需要用到new一个对象,如此一来多次在使用的地方都new一次感觉很繁琐,而且不容已维护;当然这里的DbData是简单的测试用例,没有用到什么工厂,抽象等设计来处理声明这类的实例(大家可以忽略哦);
好了,我们再 ValuesController 中分别创建个获取学生列表信息的方法 GetAllStudents01_2 和添加学生信息的方法 AddStudent ,然后填写内部代码如:
1 private DbData db = DbData.Current; 2 3 [Route("all01_2")] 4 [AcceptVerbs("POST","GET")] 5 public HttpResponseMessage GetAllStudents01_2() 6 { 7 var students = db.GetAll(); 8 return Request.CreateResponse(HttpStatusCode.OK, students); 9 }10 11 [Route("add")]12 [HttpPost]13 public HttpResponseMessage AddStudent(MoStudent moStudent)14 {15 var httpStatus = HttpStatusCode.OK;16 if (ModelState.IsValid)17 {18 var isfalse = db.Save(moStudent);19 }20 return Request.CreateResponse(httpStatus, moStudent);21 }
两个方法的参数或者返回信息没有做更多的处理,能够大家看就行,好了创建完api接口代码后,我们来测试访问下学生列表接口,地址如: http://localhost:1001/s/all01_2 ,得到的结果图:
返回的是json格式数据,本篇围绕的数据格式都是json,这也是很常用的返回数据格式之一;
MVC代码中如何调用api接口
首先,创建一个mvc项目,创建方式可以看这篇文章WebApi - 路由,然后再 HomeController.cs 文件中增加Index(学生列表)和Add(添加学生信息)两个Action方法,并且填写代码如:
1 public class HomeController : Controller 2 { 3 4 public async Task<ActionResult> Index() 5 { 6 7 var searchData = new MoStudent(); 8 //查询条件 9 10 var webapiUrl = "http://localhost:1001/s/all01_2";11 var httpResponseMsg = new HttpResponseMessage();12 13 using (var httpClient = new HttpClient())14 {15 httpResponseMsg = await httpClient.PostAsync(webapiUrl, searchData, new System.Net.Http.Formatting.JsonMediaTypeFormatter());16 }17 var students = httpResponseMsg.Content.ReadAsAsync<List<MoStudent>>().Result;18 19 return View(students);20 }21 22 [HttpGet]23 public ActionResult Add()24 {25 26 return View();27 }28 29 [HttpPost]30 public async Task<ActionResult> Add(MoStudent model)31 {32 if (ModelState.IsValid)33 {34 var webapiUrl = "http://localhost:1001/s/add";35 var httpResponseMsg = new HttpResponseMessage();36 37 using (var httpClient = new HttpClient())38 {39 httpResponseMsg = await httpClient.PostAsync<MoStudent>(webapiUrl, model, new System.Net.Http.Formatting.JsonMediaTypeFormatter());40 }41 model = httpResponseMsg.Content.ReadAsAsync<MoStudent>().Result;42 }43 44 ModelState.AddModelError("", model.Id > 0 ? "添加成功" : "添加失败");45 return View(model);46 }47 }
这里需要讲解几个注意的地方, HttpClient 类主要用来做接口请求的,这里我通过传递参数给她的扩展 PostAsync 方法来请求我们刚才创建的webapi地址 http://localhost:1001/s/all01_2 ,这里先来简单看下这个方法使用到的参数说明:
View Code
值得注意的是最后一个参数 new System.Net.Http.Formatting.JsonMediaTypeFormatter() , JsonMediaTypeFormatter 类是继承了 MediaTypeFormatter 类并重写了格式化的一些方法,因为我们创建的api项目要求的是json格式的参数和返回,所以这里用的是 JsonMediaTypeFormatter 类,还有其他的格式如: XmlMediaTypeFormatter 等这个也在上一篇分享文章中使用到了,各位可以看下做下了解;PostAsync方法是异步的方法,所以咋们需要在调用的时候使用 await 修饰,有了await自然要有她的配套组合 async 和 Task 因此就有了咋们的 public async Task<ActionResult> Index() 这样的代码;好了废话太多了,咋们一起来看下试图view中绑定代码和绑定学生列表后的查询结果:
View Code
执行方法这个学生列表Action的Index方法后,在浏览器的效果如:
看到结果后,咋们的mvc调用webapi的例子就成功了,下面来看下添加功能,添加方法里面的主要调用webapi代码和查询学生列表方法的代码几乎一样,只是这里调用api方法后返回的结果是单个学生对象信息不是集合了,这里只贴一下Add视图代码供大家参考:
View Code
值得注意的是这种后台请求不同域之间的api接口,不会有跨域的限制,除非接口本身有限制外,下面要讲解的ajax方式就不相同了;
ajax如何调api接口
首先,咋们需要明确一个东西,ajax调用接口不能跨域,这个是必须了解的,比如手机h5的webapp通常都是使用ajax来调用接口获取数据的,而且大部分需求都是跨域来请求的,因此本示例会在下面讲解的时候简单提及到常用的几种处理方式,并且使用其中一种来讲解,希望能给大家带来帮助;为了测试跨域访问情况,我们在上一节点的试图中增加如下布局代码:
View Code
然后,jquery绑定查询按钮事件代码如:
1 <script type="text/javascript"> 2 3 $(function () { 4 5 $("#btnSearch").on("click", function () { 6 7 var tabObj = $("#tab tbody"); 8 tabObj.html(‘tr><td colspan="4">加载中...</td></tr>‘); 9 10 $.post("http://localhost:1001/s/all01_2", {}, function (data) {11 12 var tabHtml = [];13 $.each(data, function (i, item) {14 15 tabHtml.push(‘<tr>‘);16 tabHtml.push("<td>" + item.Id + "</td>");17 tabHtml.push("<td>" + item.Name + "</td>");18 tabHtml.push("<td>" + (item.Sex ? "男" : "女") + "</td>");19 tabHtml.push("<td>" + item.Birthday + "</td>");20 tabHtml.push(‘</tr>‘);21 });22 if (tabHtml.length <= 0) { return false; }23 24 tabObj.html(tabHtml.join(‘‘));25 });26 });27 })28 </script>
然后,用iis新发布一个站点指向和上面mvc项目例子一样的磁盘目录,然后iis路由地址为: http://localhost:1002/home ,注意那我们刚才的webapi地址为 http://localhost:1001/s/all01_2 ,这两个地址区别在于,一个是1002端口一个是1001端口,这样就构建好了咋们跨域的要求了(当然有些朋友会在意在说为什么不配置个host本地域名来测试呢 ,我只能说这是一样的效果),然后我们访问 http://localhost:1002/home 路由,并且点击我们绑定好的查询事件按钮,会有这样一个ajax请求输出来的错误:
很显然这是跨域提示的错误,我们要怎么避免他呢,市面上通常的方式
1. 使用jsonp格式来处理
2. 在接口端写入接受跨域请求的设置
很显然咋们本次测试用的是第二种,方便,快速就能完成,不过这里因为是webapi,所以这里直接使用微软提供的Cors的服务,我们需要使用nuget控制台录入如下指定: Install-Package Microsoft.AspNet.WebApi.Cors -Version 5.0.0 ,目前最后更新的版本是:
能看出来,这个包现在已经停止了更新了,这里我为什么用5.0.0版本呢,因为我项目的其他包最新是5.0.0,而安装了5.2.3版本的话项目中的很多包都会升级并且有些包自动安装不上,会导致项目出问题变动很大,多方尝试后还是这个5.0.0版本的稳定(这个情况需要朋友注意下);怎么用呢,这里只需要在咋们webapi项目中的 App_Start/WebApiConfig.cs 文件中注册一下就行了,代码如: config.EnableCors(); 意思是启动Cors跨域;然后咋们在自定义 ValuesController class上方增加如下标记: [EnableCors("http://localhost:1002", "*", "*")] ,这个EnableCors第一个参数是允许跨域访问的域地址,好了咋们还是点击ajax请求接口中的查询按钮,得到效果:
能正常获取出来webapi接口数据了,好了咋们再来简单看下在Controller中 EnableCors 允许传递的参数说明:
View Code
由上的参数说明我们可以这样设置,来确保任何请求地址都能访问到我们webapi接口:
EnableCors的第一个参数如果是*,表示任何请求地址来源都运行访问该webapi;第二个参数如果是*,表示任意头部head信息都可以;第三参数为*,表示任意请求方式(如:Post,put,delete等);总结下ajax方式请求不同域名接口,需要跨域运行设置,这个也是很多互联网公司webapp应用很常见的一种方式;
只要跨域请求成功后,添加学生信息就好做了,下面直接贴出通过ajax调用添加学生信息接口代码:
1 <script type="text/javascript"> 2 3 $(function () { 4 5 $("#btnAjaxSave").on("click", function () { 6 7 var divResult = $("#divResult"); 8 divResult.html("保存中,请稍后..."); 9 10 var param = {11 Name: $("input[name=‘Name‘]").val(),12 Sex: $("input[name=‘Sex‘]").is(":checked"),13 Birthday: $("input[name=‘Birthday‘]").val()14 };15 16 $.post("http://localhost:1001/s/add", param, function (data) {17 console.log(data);18 if (data) {19 divResult.html(data.Id > 0 ? "添加成功" : "添加失败");20 } else {21 divResult.html("");22 }23 });24 });25 })26 27 </script>
对应的学生信息添加接口:
1 [Route("add")] 2 [HttpPost] 3 public HttpResponseMessage AddStudent(MoStudent moStudent) 4 { 5 var httpStatus = HttpStatusCode.OK; 6 if (ModelState.IsValid) 7 { 8 var isfalse = db.Save(moStudent); 9 }10 return Request.CreateResponse(httpStatus, moStudent);11 }
以上是关于WebApi接口 - 如何在应用中调用webapi接口的主要内容,如果未能解决你的问题,请参考以下文章