接着上一回说,上回说到,web api有几种访问方式,具体有几种,我还真没去研究过,但是这里打算从get、post、put、delete四种请求方式分别谈谈基础类型(包括int/string/datetime等)、实体、数组等类型的参数如何传递。

在介绍之前,有个概念必须先弄清楚:出于安全考虑,浏览器会限制脚本中发起的跨站请求,浏览器要求JavaScript或Cookie只能访问同域下的内容。 

什么意思,就拿现在做的这个来说,在这里,我是把webapi项目作为一个单独的控制层来处理,而MVC项目就是表示层,model项目就是数据层了。现在我需要在表示层通过js来调用控制层的函数来获取数据层的数据,这里的调用方式就是webapi的调用方式。那么问题就来了,因为是不同的项目,表示层和控制层的端口不一样的,表示层的是7866,控制层的是6972,它们之间的请求就是跨站请求,偏偏浏览器是限制的(这里要说明一下,IE10,IE11在不作任何处理的情况下可以跨站请求,其他浏览器不行,这可能是微软开后门了),所以就有了webapi的跨域这个概念。

跨域问题的解决:

CORS全称Cross-Origin Resource Sharing,中文全称跨域资源共享。它解决跨域问题的原理是通过向http的请求报文和响应报文里面加入相应的标识告诉浏览器它能访问哪些域名的请求。比如我们向响应报文里面增加这个Access-Control-Allow-Origin:http://localhost:6972,就表示支持http://localhost:6972里面的所有请求访问系统资源。其他更多的应用我们就不一一列举,可以去网上找找。

首先是在api项目中建一个类:

 public class CrossSiteAttribute : System.Web.Http.Filters.ActionFilterAttribute{private const string Origin = "Origin";/// <summary>/// Access-Control-Allow-Origin是HTML5中定义的一种服务器端返回Response header,用来解决资源(比如字体)的跨域权限问题。/// </summary>private const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";/// <summary>///  originHeaderdefault的值可以使 URL 或 *,如果是 URL 则只会允许来自该 URL 的请求,* 则允许任何域的请求/// </summary>private const string originHeaderdefault = "http://localhost:7866";/// <summary>/// 该方法允许api支持跨域调用/// </summary>/// <param name="actionExecutedContext"> 初始化 System.Web.Http.Filters.HttpActionExecutedContext 类的新实例。</param>public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext){actionExecutedContext.Response.Headers.Add(AccessControlAllowOrigin, originHeaderdefault);}}

里面的http://localhost:7866就是mvc项目的地址。

还有一只方式允许所有网站都可跨域来访问当前项目里的资源,就是在web.config中添加如下代码。

<system.webServer><validation validateIntegratedModeConfiguration="false"/><handlers><remove name="ExtensionlessUrlHandler-Integrated-4.0"/><remove name="OPTIONSVerbHandler"/><remove name="TRACEVerbHandler"/><add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/></handlers></system.webServer>

一、get请求

对于取数据,我们使用最多的应该就是get请求了吧,上回的例子中就有用到,在这里再来介绍一下

对于get请求,有前端和后端两种方式,前端就是用js来实现,后端就是上回说的那样。首先看前端请求。

1、调用无参函数,返回字符串

上面分别是视图项目和控制项目的相关代码,运行结果如下。在api项目中对两个函数添加了 [CrossSite]约束,当然也可以将这个约束添加到valuescontroller上,这样就对所有函数都约束了

2、调用有参函数,返回字符串

function btn2() {$.ajax({type: 'get',url: "http://localhost:6972/api/values/getString",data: {txt:'123456'},traditional: true,async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}

3、调用多参函数返回字符串

 function btn3() {$.ajax({type: 'get',url: "http://localhost:6972/api/values/GetAllChargingData",data: { id: 1234, name: "ffff", dt: "1988-09-11" },traditional: true,async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}public string GetAllChargingData(int id, string name,DateTime dt){return name+"-" + id+"-"+dt.ToString();}

4、将实体传入后台调用,并返回一个字符串

function btn4() {$.ajax({type: 'get',url: "http://localhost:6972/api/values/GetSiteName",contentType: "application/json",data: { query: JSON.stringify({ SiteId: 1, Title: "fwwe", Uri: "rwerwerwe" }) },//将实体序列化traditional: true,async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}public string GetSiteName(string query){Site obj = Newtonsoft.Json.JsonConvert.DeserializeObject<Site>(query);//反序列化return "名称:" + obj.Title;}

5、返回实体

function btn5() {$.ajax({type: 'get',url: "http://localhost:6972/api/values/GetSiteByID",data: { id: 2},traditional: true,async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data.Title);}else {$.ligerDialog.alert("", "操作失败", "error");}}});
}public Site GetSiteByID(int id){SiteSource ss = new SiteSource();return ss.DateSource().Where(o => o.SiteId == id).FirstOrDefault();}

后端请求:

6、返回实体

public JsonResult getSiteById(int id){HttpClient httpClient = new HttpClient();//GET方式去调用webapivar responseJson = httpClient.GetAsync("http://localhost:6972/api/values/GetSiteByID?id="+id).Result.Content.ReadAsStringAsync().Result;Site site = JsonConvert.DeserializeObject<Site>(responseJson);//允许使用GET方式获取,否则用GET获取是会报错return new JsonResult() {Data=site,JsonRequestBehavior=JsonRequestBehavior.AllowGet };}function btn6() {$.ajax({url: "Web/getSiteById/",type:"get",data: { id:3 },traditional: true,async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data.Title);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}

二、post请求

post请求的基础类型的参数和get请求有点不一样,我们知道get请求的参数是通过url来传递的,而post请求则是通过http的请求体中传过来的,WebApi的post请求也需要从http的请求体里面去取参数。

如果按照通常的情况去传参就有错,比如:

解决方法之一是用[FromBody]在SaveString函数中修饰参数:public string SaveString([FromBody]string txt),然后再ajax中:data: {“”:"ff"},但是这个方法有一个缺点就是只能适用单一参数的情况,多参数就不行了

dynamic实现多参数传递,单一参数也可以

 function ptn1() {$.ajax({type: 'post',url: "http://localhost:6972/api/values/SaveString",data: JSON.stringify({ NAME: "Jon", DES: "备注" }),traditional: true,contentType: 'application/json',async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}[HttpPost]public string SaveString(dynamic txt){return "保存:" + txt.NAME+"-"+txt.DES;}

function ptn2() {$.ajax({type: 'post',url: "http://localhost:6972/api/values/SaveSite",data: JSON.stringify({ id: 3 }),traditional: true,contentType: 'application/json',async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data.Title);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}[HttpPost]public Site SaveSite(dynamic obj){SiteSource ss = new SiteSource();string s = obj.id;//int ID = int.Parse(obj.id);   这种方式有错int ID =int.Parse(s);return ss.DateSource().Where(o => o.SiteId == ID).FirstOrDefault();}

将实体作为参数传递。这里的实体更上面post方式的第一个例子是不同的,那个例子是传递多个参数的情况

function ptn3() {$.ajax({type: 'post',url: "http://localhost:6972/api/values/UpdateName",data: { SiteId: "1", Title: "test", Uri: "www.cnblogs.cc" },traditional: true,//contentType: 'application/json',async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}[HttpPost]public string UpdateName(Site si){SiteSource ss = new SiteSource();Site s= ss.DateSource().Where(o => o.SiteId == si.SiteId).FirstOrDefault();return s.Title + "123";}

使用实体作为参数的时候,前端直接传递普通json,后台直接使用对应的类型去接收即可,不用FromBody。但是这里需要注意的一点就是,这里不能指定contentType为appplication/json,否则,参数无法传递到后台。

post请求默认是将表单里面的数据的key/value形式发送到服务,而我们的服务器只需要有对应的key/value属性值的对象就可以接收到。而如果使用application/json,则表示将前端的数据以序列化过的json传递到后端,后端要把它变成实体对象,还需要一个反序列化的过程。按照这个逻辑,那我们如果指定contentType为application/json,然后传递序列化过的对象应该也是可以的  

2、实体与基础类型同时传递

 function ptn4() {var postdata = { SiteId: "1", Title: "test", Uri: "www.cnblogs.cc" };$.ajax({type: 'post',url: "http://localhost:6972/api/values/SameName",data: JSON.stringify({ NAME: "test", o: postdata }),           traditional: true,contentType: 'application/json',async: true,success: function (data, status) {if (status == "success") {alert(data);                    }else {$.ligerDialog.alert("", "操作失败", "error");}}});}[HttpPost]public bool SameName(dynamic obj){string strName = Convert.ToString(obj.NAME);Site oCharging = Newtonsoft.Json.JsonConvert.DeserializeObject<Site>(Convert.ToString(obj.o));return strName==oCharging.Title;}

3、基础类型数组作为参数

function ptn5() {var arr = ["1", "2", "3", "4"];$.ajax({type: "post",url: "http://localhost:6972/api/values/SaveData1",contentType: 'application/json',data: JSON.stringify(arr),success: function (data, status) {if (status == "success") {alert(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});[HttpPost]public bool SaveData1(string[] ids){if (ids[0] == "1")return true;elsereturn false;}

4、实体类型数组作为参数

function ptn6() {var arr = [{ SiteId: "1",  Title : "test", Uri : "www.cnblogs.cc"  },{ SiteId: "2",Title : "博客园首页", Uri :"www.cnblogs.com"  },{ SiteId: "3", Title: "博问", Uri: "q.cnblogs.com" }];$.ajax({type: "post",url: "http://localhost:6972/api/values/SaveData2",contentType: 'application/json',data: JSON.stringify(arr),success: function (data, status) {if (status == "success") {alert(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}[HttpPost]public bool SaveData2(List<Site> lstSite){if (lstSite[0].Title == "test")return true;elsereturn false;}

5、post后台调用

function ptn7() {$.ajax({url: "Web/PostReques/",type: "post",data: {},traditional: true,async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}

mvc控制器中的相应函数

public JsonResult PostReques() {//请求路径string url = "http://localhost:6972/api/values/UpdateName";//定义request并设置request的路径WebRequest request = WebRequest.Create(url);request.Method = "post";//初始化request参数string postData = "{SiteId: \"2\",Title : \"博客园首页\", Uri :\"www.cnblogs.com\"  }";//设置参数的编码格式,解决中文乱码byte[] byteArray = Encoding.UTF8.GetBytes(postData);//设置request的MIME类型及内容长度request.ContentType = "application/json";request.ContentLength = byteArray.Length;//打开request字符流Stream dataStream = request.GetRequestStream();dataStream.Write(byteArray, 0, byteArray.Length);dataStream.Close();//定义response为前面的request响应WebResponse response = request.GetResponse();//获取相应的状态代码
            Console.WriteLine(((HttpWebResponse)response).StatusDescription);//定义response字符流dataStream = response.GetResponseStream();StreamReader reader = new StreamReader(dataStream);string responseFromServer = reader.ReadToEnd();//读取所有return new JsonResult() { Data = responseFromServer};

三、put请求

WebApi里面put请求一般用于对象的更新。它和用法和post请求基本相同。同样支持[FromBody],同样可以使用dynamic。

function puttn() {$.ajax({type: 'put',url: "http://localhost:6972/api/values/PutData",data: JSON.stringify({ txt: "Jon"}),traditional: true,contentType: 'application/json',async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}[HttpPut]public string PutData(dynamic txt){return "123" + txt;}

四、delete请求

delete请求肯定是用于删除操作的。参数传递机制和post也是基本相同。下面简单给出一个例子,其他情况参考post请求。

function deletetn() {$.ajax({type: 'delete',url: "http://localhost:6972/api/values/deleteData",data: JSON.stringify({ txt: "333333" }),traditional: true,contentType: 'application/json',async: true,success: function (data, status) {if (status == "success") {$("#div_test").html(data);}else {$.ligerDialog.alert("", "操作失败", "error");}}});}[HttpDelete]public string deleteData(dynamic txt){return "----------" + txt;}

转载于:https://www.cnblogs.com/jin-/p/6605871.html

web api 二相关推荐

  1. ASP.NET Web API 过滤器创建、执行过程(二)

    ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...

  2. 【壹刊】Azure AD(二)调用受Microsoft 标识平台保护的 ASP.NET Core Web API (上)

    ---------Grant_Allen 是一位博客园新晋博主,目前开始专注于Azure方向的学习和研究,是我认识不多的.打算长时间研究Azure的群友,因此打算帮他开个专栏,同时也希望并祝愿他能一直 ...

  3. 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(二)-- Web Api Demo

    在上一篇里,我已经建立了一个简单的Web-Demo应用程序.这一篇将记录将此Demo程序改造成一个Web Api应用程序. 一.添加ASP.NET Core MVC包 1. 在project.json ...

  4. WEB API 系列(二) Filter的使用以及执行顺序

    在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理.引入了这一机制可以更好地践行DRY(Don't Repeat Yourself)思想 ...

  5. python 收发微信之二:获取微信上行信息(利用 flask 框架实现 Web API,获取 WxPusher 上行微信)

    目 录 〇.摘要 一.前言 二.实操 1. 找一台可以给互联网提供服务的计算机 2. 实现一个 flask 最小服务并在互联网上访问到 3. 根据 WxPusher 上行信息接口实现 POST 命令的 ...

  6. web API简介(二):客户端储存之document.cookie API

    概述 前篇:web API简介(一):API,Ajax和Fetch 客户端储存从某一方面来说和动态网站差不多.动态网站是用服务端来储存数据,而客户端储存是用客户端来储存数据.document.cook ...

  7. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  8. Web APi之认证(Authentication)两种实现方式【二】(十三)

    前言 上一节我们详细讲解了认证及其基本信息,这一节我们通过两种不同方式来实现认证,并且分析如何合理的利用这两种方式,文中涉及到的基础知识,请参看上一篇文中,就不再叙述废话. 序言 对于所谓的认证说到底 ...

  9. 监控系统简介(二):使用 App Metrics 在 ASP.NET Web API 中记录指标

    回顾 在<监控系统简介:使用 Prometheus 与 Grafana>一文中,我们了解了什么是监控系统,Prometheus 这一监控工具及它提供的数据类型.PromQL 以及 Graf ...

最新文章

  1. 程序员的8年床铺变化 | 每日趣闻
  2. [YTU]_2907(类重载实现矩阵加法)
  3. 二叉树结点入度等于出度
  4. java 枚举常量_java中的枚举类和常量类区别在哪儿?
  5. RTSP再学习 -- Hi3516A RTSP实例 分析
  6. Servlet实现登录注册
  7. js正则表达exec和match的区别(转)
  8. Java实现pow共识算法_POW+POS混合共识算法
  9. Android 自定义车牌键盘
  10. Windows(11)下JDK安装与环境变量配置
  11. FlashBuild4序列号生成与使用方法
  12. easy excel 设置某一列的格式
  13. ffmpeg+mencoder环境搭建和视频处理总结(4m/1/99)
  14. 德州停电悲剧不会重演 智慧用电是新方向
  15. 一个传奇玩家的传奇故事
  16. aosp_015.配置编译文件,删除自带app
  17. 威联通nas利用calibre-web搭建个人数字图书管理系统
  18. Selenium自动化测试框架基础操作
  19. API,SDK和API之间的关系和区别
  20. python+编译器 下载、安装

热门文章

  1. android中TextView显示中文发生乱码的问题
  2. Android开发-将自定义View布局到Layout中并调用
  3. Windows环境下学习Lisp和Scheme的两大利器
  4. Android 内存溢出解决方案(OOM) 整理总结
  5. Android Memory Management
  6. Python 并发编程之使用多线程和多处理器
  7. golang中的bufio
  8. const应用和作用
  9. linux网络编程二:基础socket, bind, listen, accept, connect
  10. nc 传输文件和目录