web api 二
接着上一回说,上回说到,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:''},
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: , 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: , 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: },
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方式去调用webapi
var 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: },
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: }),
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: "", 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 + "";
}

使用实体作为参数的时候,前端直接传递普通json,后台直接使用对应的类型去接收即可,不用FromBody。但是这里需要注意的一点就是,这里不能指定contentType为appplication/json,否则,参数无法传递到后台。
post请求默认是将表单里面的数据的key/value形式发送到服务,而我们的服务器只需要有对应的key/value属性值的对象就可以接收到。而如果使用application/json,则表示将前端的数据以序列化过的json传递到后端,后端要把它变成实体对象,还需要一个反序列化的过程。按照这个逻辑,那我们如果指定contentType为application/json,然后传递序列化过的对象应该也是可以的
2、实体与基础类型同时传递
function ptn4() {
var postdata = { SiteId: "", 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 = ["", "", "", ""];
$.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[] == "")
return true;
else
return false;
}
4、实体类型数组作为参数
function ptn6() {
var arr = [
{ SiteId: "", Title : "test", Uri : "www.cnblogs.cc" },
{ SiteId: "",Title : "博客园首页", Uri :"www.cnblogs.com" },
{ SiteId: "", 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[].Title == "test")
return true;
else
return 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, , 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 "" + txt;
}

四、delete请求
delete请求肯定是用于删除操作的。参数传递机制和post也是基本相同。下面简单给出一个例子,其他情况参考post请求。
function deletetn() {
$.ajax({
type: 'delete',
url: "http://localhost:6972/api/values/deleteData",
data: JSON.stringify({ txt: "" }),
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;
}

web api 二的更多相关文章
- 创建支持CRUD(增删改查)操作的Web API(二)
一:准备工作 你可以直接下载源码查看 Download the completed project. 下载完整的项目 CRUD是指“创建(C).读取(R).更新(U)和删除(D)”,它们是四个 ...
- 我这么玩Web Api(二):数据验证,全局数据验证与单元测试
目录 一.模型状态 - ModelState 二.数据注解 - Data Annotations 三.自定义数据注解 四.全局数据验证 五.单元测试 一.模型状态 - ModelState 我理解 ...
- ASP.NET Web API 过滤器创建、执行过程(二)
ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...
- ASP.NET Web API 控制器创建过程(二)
ASP.NET Web API 控制器创建过程(二) 前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病 ...
- YbSoftwareFactory 代码生成插件【二十一】:Web Api及MVC性能提升的几个小技巧
最近在进行 YbSoftwareFactory 的流程功能升级,目前已经基本完成,现将用到的一些关于 Web Api 及 MVC 性能提升的一些小技巧进行了总结,这些技巧在使用.配置上也相当的简单,但 ...
- ODATA WEB API(二)----ODATA服务与客户端
一.概述 ODATA不经可以作为WebAPI建立相应的WEBAPI控制器,还可以建立ODataControl控制器,能够通过插件建立第三方ODataClinet类库:调用和使用数据变得简单可行. 二. ...
- MVC4 WebAPI(二)——Web API工作方式
http://www.cnblogs.com/wk1234/archive/2012/05/07/2486872.html 在上篇文章中和大家一起学习了建立基本的WebAPI应用,立刻就有人想到了一些 ...
- android移动开发学习笔记(二)神奇的Web API
本次分两个大方向去讲解Web Api,1.如何实现Web Api?2.如何Android端如何调用Web Api?对于Web Api是什么?有什么优缺点?为什么用WebApi而不用Webservice ...
- WEB API 系列(二) Filter的使用以及执行顺序
在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理.引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想 ...
随机推荐
- Quartz进一步学习与使用
一.再思考 了解Quartz.NET的基本使用方法了.但如果想方便的知道某个作业执行情况,需要暂停,启动等操作行为,这时候就需要个Job管理的界面,如何才能达到我们想到的效果,查看相关Quartz.n ...
- Linux下汇编语言学习笔记55 ---
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...
- hdu - 2266 How Many Equations Can You Find (简单dfs)
http://acm.hdu.edu.cn/showproblem.php?pid=2266 给一个字符串和一个数n,在字符串中间可以插入+或者 -,问有多少种等于n的情况. 要注意任意两个数之间都可 ...
- 1017 乘积最大 2000年NOIP全国联赛普及组NOIP全国联赛提高组
1017 乘积最大 2000年NOIP全国联赛普及组NOIP全国联赛提高组 #include <iostream> #include <string> #include & ...
- Ajax核心知识(2)
对于Ajax核心的东西需要在进行总结提炼一下: xmlHttp对象. 方法:xml.responseText获取后台传递到前台的数据,经常性的使用var object=xml.responseText ...
- Evaluate Reverse Polish Notation(逆波兰式)
Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...
- linux 实现VLAN
本文将在一台linux机器上,利用linuxbridge 等技术模拟创建VLAN 环境. 首先,创建vlan interface ip link add link ens33 name ens33.8 ...
- 004 ospf
r0(config)#router ospf 1 OSPF process 1 cannot start. There must be at least one "up" IP i ...
- AutoCAD如何设置线宽
一般要求粗实线粗实线0.4,细实线0.2mm. 1 先打开图层特性管理器,新建一个图层,专门放粗实线(我起名叫"我的粗实线",颜色设置为紫色,线宽为0.4mm),此前的乱七八糟的图 ...
- 华为OJ2011-最长公共子串
一.题目描述 描述: 计算两个字符串的最大公共子串(Longest Common Substring)的长度,字符区分大小写. 输入: 输入两个字符串 输出: 输出一个整数 样例输入: asdfas ...