近日逛招聘软件,看到部分企业都要求会编写、请求restFul的webapi。正巧这段时间较为清闲,于是乎打开vs准备开撸。

1.何为restFul?

restFul是符合rest架构风格的网络API接口。

rest是一种软件架构的编码风格,是根据网络应用而去设计和开发的一种可以降低开发复杂度的编码方式,并且可以提高程序的可伸缩性(增减问题)。

几种较为常见的操作类型:get(查询)、post(新增)、put(修改)、delete(删除)

2.restFul标准的WebApi搭建以及部署在iis上

在这里为了方便,使用的ef框架,在创建读/写控制器时直接引用了模型类

控制器直接帮我帮crud的方法都写好了,按照注释的请求规则,可直接使用。代码如下:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using webapi; namespace webapi.Controllers
{
public class ProductsController : ApiController
{
private DtoolsEntities db = new DtoolsEntities(); // GET: api/Products
[HttpGet]
public IQueryable<Product> GetProduct()
{
return db.Product.OrderByDescending(p => p.AddDate).Take();
} // GET: api/Products/5
[HttpGet]
[ResponseType(typeof(Product))]
public IHttpActionResult GetProduct(int id)
{
Product product = db.Product.Find(id);
if (product == null)
{
return NotFound();
} return Ok(product);
} // PUT: api/Products/5 update
[HttpPut]
[ResponseType(typeof(void))]
public IHttpActionResult PutProduct(int id, Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} if (id != product.Id)
{
return BadRequest();
}
product.AddDate = DateTime.Now;
db.Entry(product).State = EntityState.Modified; try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(id))
{
return NotFound();
}
else
{
throw;
}
} return StatusCode(HttpStatusCode.NoContent);
} // POST: api/Products
[HttpPost]
[ResponseType(typeof(Product))]
public IHttpActionResult PostProduct(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
product.AddDate = DateTime.Now;
db.Product.Add(product);
db.SaveChanges(); return CreatedAtRoute("DefaultApi", new { id = product.Id }, product);
} // DELETE: api/Products/5
[HttpDelete]
[ResponseType(typeof(Product))]
public IHttpActionResult DeleteProduct(int id)
{
Product product = db.Product.Find(id);
if (product == null)
{
return NotFound();
} db.Product.Remove(product);
db.SaveChanges(); return Ok(product);
} protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
} private bool ProductExists(int id)
{
return db.Product.Count(e => e.Id == id) > ;
}
}
}

每个控制器前根据类型最好指定[HttpGet]  [HttpPost]   [HttpPut]  [HttpDelete],因为服务器是根据请求类型自动映射匹配控制器名称,加上特性,避免出错。

weiapi设置中指定json格式,避免数据类型异常

webapi的搭建基本没有问题了。接下来就是部署在iis上,这里不多做描述,不懂如何部署iis可点击这里(会被揍吗?)

3.前台ajax请求页面的编写

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="js/jquery-3.3.1.js"></script>
<script type="text/javascript"> //部署在iis上的webapi接口具体请求路径
var httpUrl = "http://192.168.0.142:8018/api/Products"; $(function () {
$.ajax({
url: httpUrl,
type: "GET",
dataType: "json",
success: function (data) {
$.each(data, function (index, item) {
var tr = $("<tr/>");
$("<td/>").html(item["ProductName"]).appendTo(tr);
$("<td/>").html(item["Brand"]).appendTo(tr);
$("<td/>").html(item["ASIN"]).appendTo(tr);
$("<td/>").html(item["SKU"]).appendTo(tr);
$("<button id ='d' onclick='del(" + item["Id"] + ")'>").html("删除").appendTo(tr);
$("<button id ='u' onclick='update(" + item["Id"] + ")'>").html("更新").appendTo(tr);
tr.appendTo("#tab");
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest + "," + textStatus + "," + errorThrown);
}
}); }); //修改
function update(id) {
$.ajax({
url: httpUrl + "?id=" + id,
type: "Put",
data: { "id": id, "ProductName": '男士领带', "Brand": '海澜之家', "ASIN": 'SAD498AE1', "SKU": '98DA7E9QE-SDAE', "StoreName": '海澜之家京东自营店' },
dataType: "json",
success: function (data) {
location.reload();
}
})
} //新增
function add() {
$.ajax({
url: httpUrl,
type: "Post",
data: { "ProductGuid": newGuid(), "ProductName": '男士衬衫', "Brand": '海澜之家', "ASIN": 'SAD498AE1', "SKU": '98DA7E9QE-SDAE', "StoreName": '海澜之家天猫旗舰店' },
dataType: "json",
success: function (data) {
location.reload();
}
})
} //删除
function del(id) {
$.ajax({
url: httpUrl+"/" + id,
type: "Delete",
dataType: "json",
success: function (data) {
location.reload();
}
});
} //生成guid
function newGuid() {
var guid = "";
for (var i = 1; i <= 32; i++) {
var n = Math.floor(Math.random() * 16.0).toString(16);
guid += n;
if ((i == 8) || (i == 12) || (i == 16) || (i == 20))
guid += "-";
}
return guid;
}
</script>
</head>
<body>
<div>
<table id="tab">
<tr>
<th>产品名称</th>
<th>产品品牌</th>
<th>ASIN</th>
<th>SKU</th>
</tr>
</table>
<button id="add" onclick="add()">add</button>
</div> </body>
</html>

前端,后端代码都写完了。只剩测试了。想都不用想肯定会出问题的,因为涉及到了跨域请求等,接下来就为大家解决问题。

问题一:ajax请求,涉及到cors跨域,请求失败

  问题介绍及原因分析:

           CORS是一个W3C标准,全称是”跨域资源共享”。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,基本上目前所有的浏览器都实现了CORS标准,其实目前几乎所有的浏览器ajax请求都是基于CORS机制的。
         跨域问题一般发生在Javascript发起AJAX调用,因为浏览器对于这种请求,所给予的权限是较低的,通常只允许调用本域中的资源,除非目标服务器明确地告知它允许跨域调用。所以,跨域的问题虽然是由浏览器的行为产生出来的,但解决的方法却            是在服务端。因为不可能要求所有客户端降低安全性。

解决方案:

                           web.config修改配置文件,使服务端支持跨域请求

<system.webServer>
<httpProtocol>
<customHeaders>
<!--服务器端返回Response header 后接URL或* 表示允许-->
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
     <!--支持请求的类型-->
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>

问题二:get、post 可正常请求,put、delete 出现405(Method Not Allowed)  注意:我提交Put的请求,浏览器响应的是Request Method:PUT

  问题介绍及原因分析:

           有些人会问:我刚刚在服务端设置了允许put delete请求了,浏览器上服务端的响应也看到了支持put delete,为啥服务端还是拒绝呢?

           一切都是iis的WebDAV(Web Distribution Authorization Versioning) Publish惹的祸,WebDAV是基于HTTP协议的拓展,添加了很多Method用于管理服务器上的文件。若安装了WebDAV,那么iis所有的site都会默认使用WebDAV Module与WebDAV Handler。

          WebDAV Handler的默认配置是处理如下 Method:PROPFIND,PROPPATCH,MKCOL,PUT,COPY,DELETE,MOVE,LOCK,UNLOCK。所以浏览器发送的put delete请求都会被拦截并交给WebDAV Handler来处理,并且WebDAV Handler会默认拒绝请求

解决方案:

        既然我们找到了问题所在点,那么解决方案应然而生,那就是在配置文件里移除ebDAVModule和WebDAVHandler或者在系统中直接移除WebDAV

 <system.webServer>
<!--以下配置为了让IIS +支持Put/Delete方法-->
<httpProtocol>
<customHeaders>
<!--服务器端返回Response header 后接URL或* 表示允许-->
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<!--移除WebDAV协议-->
<remove name="WebDAV"/>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<!--支持所有方式的请求-->
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<!--IIS7/.5上必须加这个配置,否则访问报错-->
<modules runAllManagedModulesForAllRequests="true">
<!--移除WebDAV协议-->
<remove name="WebDAVModule"/>
<remove name="TelemetryCorrelationHttpModule" />
<add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" preCondition="integratedMode,managedHandler" />
</modules>
</system.webServer>

问题三:put delete请求,又出现了405(Method Not Allowed)

  问题介绍及原因分析:

           大家发现没有,问题二put提交,Request Method就是put,Delete提交,Request Method就是Delete。然而在这里统统都是OPTIONS。那么这个OPTIONS到底是个啥呢?

           Preflighted Requests(预检请求)
           Preflighted Requests是CORS中一种透明服务器验证机制。预检请求首先需要向另外一个域名的资源发送一个 HTTP OPTIONS 请求头,其目的就是为了判断实际发送的请求是否是安全的。
          下面的2种情况需要进行预检:
          1、简单请求,比如使用Content-Type 为 application/xml 或 text/xml 的 POST 请求;
          2、请求中设置自定义头,比如 X-JSON、X-MENGXIANHUI 等。

          原来put、delete请求如果头部设置了XMLHttpRequest.setRequestHeader("Content-Type", "application/json")之前还发送了一次预检请求。

解决方案:

          既然是多的一次请求,那我们就在服务端过滤掉就好了。

          Global.asac添加以下方法就行了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing; namespace webapi
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
} protected void Application_BeginRequest()
{
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.End();
}
}
}
}

到这里,ajax跨域实现RestFul请求,已经是能正常运行了。剩下的只是安全校验、身份认证、异常记录等,就能放到生产环境了。这里就不多做描述了,毕竟博主还是上班族...

如有错误,欢迎大家指正~

ajax请求基于restFul的WebApi(post、get、delete、put)的更多相关文章

  1. C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序

    C#中缓存的使用   缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可:  <%@ Outp ...

  2. Django框架之models和不依赖Qquery的ajax请求

    一.models表字段 1)class表字段的创建 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) ...

  3. Ajax请求数据与删除数据后刷新页面

    1.ajax异步请求数据后填入模态框 请求数据的按钮(HTML) <a class="queryA" href="javascript:void(0)" ...

  4. WebApi系列~基于RESTful标准的Web Api

    微软的web api是在vs2012上的mvc4项目绑定发行的,它提出的web api是完全基于RESTful标准的,完全不同于之前的(同是SOAP协议的)wcf和webService,它是简单,代码 ...

  5. WebApi系列~基于RESTful标准的Web Api 转载 https://www.cnblogs.com/lori/p/3555737.html

    微软的web api是在vs2012上的mvc4项目绑定发行的,它提出的web api是完全基于RESTful标准的,完全不同于之前的(同是SOAP协议的)wcf和webService,它是简单,代码 ...

  6. 让webapi只接受ajax请求

    为了测试先做一个简单的webapi,直接用新建项目时默认的就可以了.   在浏览器中测试request get,得到结果   然后再项目中新建一个AjaxOnly的类   AjaxOnly继承Acti ...

  7. 让python bottle框架支持jquery ajax的RESTful风格的PUT和DELETE等请求

    这两天在用python的bottle框架开发后台管理系统,接口约定使用RESTful风格请求,前端使用jquery ajax与接口进行交互,使用POST与GET请求时都正常,而Request Meth ...

  8. WebAPI学习日记一:Ajax请求传递参数遇到的问题

    首先,本人大学刚毕业,想把自己学习的一些东西记录下来,也是和大家分享,如有不对之处还请多加指正.声明:但凡是我博客里的文章均是本人实际操作遇到的例子,不会随便从网上拷贝或者转载,本着对自己和观众负责的 ...

  9. 基于jquery,ajax请求及自我终止的函数封装。

    场景描述: 在我们平时的开发过程中,经常会遇到这样的情况.在搜索功能中进行模糊搜索或者联想关联. 这就要我们每次对输入框中的数据进行改动时,都要发送一次请求.当在短时间内多次操作改动时,问题就出现了. ...

随机推荐

  1. JAVA多线程的问题以及处理(二)【转】

    使用互斥解决多线程问题是一种简单有效的解决办法,但是由于该方法比较简单,所以只能解决一些基本的问题,对于复杂的问题就无法解决了. 解 决多线程问题的另外一种思路是同步.同步是另外一种解决问题的思路,结 ...

  2. 确认是否是因为做了物理I/O而导致的性能不佳

    要获取语句是否进行了I/O,需要打开set statistics on 和set statistics on.

  3. 自动化测试的Selenium的python版安装与使用

    Selenium是专做网页自动化测试的,即web drive,通过百度Selenium就能找到Selenium的官网 由图可见,selenium支持相当多的编程语言进行网页自动化测试,这里我们使用py ...

  4. 将web项目部署到阿里云服务器上

    一.用eclipse将写好的项目打成war包 1.右键点击项目,选择Export 选择打包之后的路径,点击Finsh. 2.购买阿里云服务器 按下图选择 3.设置云服务器防火墙 4.远程连接云服务器 ...

  5. JavaScript -- 时光流逝(四):js中的 Math 对象的属性和方法

    JavaScript -- 知识点回顾篇(四):js中的 Math 对象的属性和方法 1. Math 对象的属性 (1) E :返回算术常量 e,即自然对数的底数(约等于2.718). (2) LN2 ...

  6. June 8. 2018 Week Week 23rd Friday

    You'll have bad times, but it'll always wake you up to the good stuff you weren't paying attention t ...

  7. Windows下mysql服务的安装与卸载

    安装 mysqld -install 也可以指定mysql安装服务的文件 my.ini文件配置好后就可以在cmd中安装mysqld服务了,在cmd中运行命令:mysqld --install MySQ ...

  8. Sublime 汉化、快捷键打开浏览器

    Sublime 是一个优秀的代码编译工具,它具有漂亮的用户界面和强大的功能,例如代码缩略图,Python 的插件,代码段等.不仅如此,它还可自定义按键绑定,菜单和工具栏.由于是歪果仁开发的,所以官方版 ...

  9. Python 进程管理工具 Supervisor 使用教程

    Supervisor 是基于 Python 的进程管理工具,只能运行在 Unix-Like 的系统上,也就是无法运行在 Windows 上.Supervisor 官方版目前只能运行在 Python 2 ...

  10. 关于HashMap的一些深入探索与理解

    在java中.大家差点儿是离不开对集合的使用的,像Map系列,List系列.Set系列.可是非常多人没有了解过或者研究过这些集合类究竟能够用在什么地方,而且有什么注意的地方.因此本文分Map系列和Li ...