接上一次的:【c#/MVC】运用MVC模式,做一个增删查改简单数据库,以及涉及到的知识,本次将部分原本的业务逻辑层和数据访问层剥离出来,单独作为一个API,挂到IIS上,然后访问。
阅读帮助:
重点内容为红色加粗标记,正文为黑色字体,可以略过的解释用淡蓝色表示,自定名词为粉色。引用部分可以看也可以不看。
_____________________________________________________________________________
目录
1、IIS的正确配置,网站的挂载,挂载时的问题:IIS没有对物理路径的读取访问权限
2、WebAPI的接口返回类型:在调用post等方法时报错:405,方法不被允许。
4、在API发布后,调试时弹出“您正在调试XXX的发布版本。。。。调试体验会降级。。。例如不会命中断点。”
6、JSON保存为字符串后,出现的斜杠问题,以及该如何处理这个斜杠.
第一:推荐使用postman工具(谷歌浏览器直接由对应的插件)
第二:使用NuGet使用大佬的程序包:【WebApiTestClient 】
9、API访问时出现httpput和httpdelete的谓词问题,该如何处理。
11、此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站
——————————————————————————————————————————
前提:数据库设计
这个部分因为在之前的【c#/MVC】运用MVC模式,做一个增删查改简单数据库,以及涉及到的知识中已经写过,没有任何改动,在此不表。
——————————————————————————————————————————
创建一个新WebAPI:
新建项目:
【文件】-【新建】-【项目】-【Visual C#】-【Web】-【ASP.net Web 应用程序服务】-选择【Web API】-右侧【改变身份验证】
注1:这里我们可以看到,在下方的【为以下项添加文件夹和核心引用】中的【MVC】和【web API】已经是默认勾选的,和之前创建MVC项目并不一样。
注2:身份验证这里,一般来说肯定是需要的,要根据用户的类型开放相应的权限,不过本例中就简单的设置为不进行验证,以方便学习。
注3:选择【Web API】时,右侧说明为:用于创建可以访问范围广阔的客户端(可以访问浏览器和移动设备)的RESTful HTTP服务的项目模板。
什么是RESTful风格:
基于Rest构建的API就是RESTful风格。
什么是REST:
(Representational State Transfer):表现层状态转移,一种软件架构风格,不是标准(不一定要遵循)。总结的说就是:用URL定位资源,用HTTP动词(GET,POST,PUT,DELETE)描述操作。
使用RESTful的理由:
一是基于JSP的局限性,使前后端分离逐渐成为互联网公司开发的业界标准使用方式。关于前后端分离:有篇很好的文章。
二是目前Client层(客户端层)的类型越来越多,RESTful可以只通过一套接口为IOS、Web、安卓等提供服务。微博开放平台和微信开放平台都采用了RESTful风格。
设计这个风格的思路:
API地址以名词为主,且用复数。对资源的调用都用HTTP动作来进行。这个部分可以参考:
此时,一个新的API空项目就建立好了。
在控制器(Controler)中右键【新建控制器】-【包含读写操作的Web API 2控制器】
新建的右侧可以看到这个控制器会包含创建、读取、更新、删除、和列出条目的REST操作。
这个控制器我命名为:【Student3APIController】。
重点:在项目中的【App_Start】文件夹中,双击打开路由设置【WebAPIConfig】,将默认路由修改为:
//在routeTemplate处添加一个:{action}
//你也可以自由修改这个路由
config.Routes.MapHttpRoute(
name:"ActionAPI",
routeTemplate: "actionapi/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
然后在模型(model)中右键新建一个类,取名为【Student】作为模型,这个模型是要根据数据库来设计,代码如下:
public class Student
{
public int id { get; set; }
public string name { get; set; }
public string number { get; set; }
public string sex { get; set; }
public int age { get; set; }
public string course1 { get; set; }
public string course2 { get; set; }
}
回到新建的控制器【Student3APIController】中,可以看到和以前的MVC项目不同,它继承的是【ApiController】,同时已经在其中自动生成了get、get(id)、post、delete、put等增删查改的几个操作。
从之前的MVC项目中将有关代码拷贝回来,进行略微的修改,其中涉及到的几个问题将在下面详述:
using部分:
using system.net;
using system.web.http;
using system.net.http;
删除using system.web.mvc;
注意:system.web.mvc;会与system.web.http;中的方法同名冲突,因此要删去对MVC的引用。
。。。。。。。。。。。。。。。。。。。。。。
API部分:
/// <summary>
/// This Web API use to modify the message from studentDB
/// </summary>
public class Student3APIController : ApiController
{
private SqlCommandHelper sqlCommandHelper = new SqlCommandHelper();
private String content=null;
// GET: actionapi/Student3API/GET
/// <summary>
/// Get all records from test database student table.
/// </summary>
/// <returns>Json Array,Convert from .net List.</returns>
[HttpGet]
public JsonResult<List<Student>> Get()
{
string sqlStr = "GetAllUserDetails";
List<Student> students = new List<Models.Student>();
students = sqlCommandHelper.GETStudentMessage(sqlStr, -1);
return Json<List<Student>>(students);
}
/// <summary>
/// Get a records from test database student table due to ID
/// </summary>
/// <param name="id">Student ID</param>
/// <returns>Json Array,Convert from .net List.</returns>
// GET: actionapi/Student3API/GET/1
[HttpGet]
public JsonResult<List<Models.Student>> Get(String id)
{
string sqlStr = "AH_GetUserDetail";
List<Models.Student> students = new List<Models.Student>();
students = sqlCommandHelper.GETStudentMessage(sqlStr, Convert.ToInt16(id));
return Json<List<Models.Student>>(students);
}
// POST: actionapi/Student3API/POST/[para]
/// <summary>
/// Add a student records.
/// </summary>
/// <param name="obj"> dynamic obj,include a student model{name、number、sex、age、course1、course2},post type is [string](age should is int)</param>
/// <returns></returns>
[HttpPost]
public bool Post([FromBody]dynamic obj)
{
//Student student = JsonConvert.DeserializeObject(obj);
string sqlStr = "AddStudentDetails";
SqlParameter[] para =
{
new SqlParameter("@name",SqlDbType.VarChar),
new SqlParameter("@number",SqlDbType.VarChar),
new SqlParameter("@sex",SqlDbType.VarChar),
new SqlParameter("@age",SqlDbType.VarChar),
new SqlParameter("@course1",SqlDbType.NVarChar),
new SqlParameter("@course2",SqlDbType.NVarChar)
};
para[0].Value = obj.name;
para[1].Value = obj.number;
para[2].Value = obj.sex;
para[3].Value = Convert.ToInt16(obj.age);
para[4].Value = obj.course1;
para[5].Value = obj.course2;
//需要为空的参数可以赋值为DBNull.Value
//If need null para value,you can assign it is [DBNull.Value].
bool judgeWriteStudentMessage = sqlCommandHelper.WriteStudentMessage(sqlStr, para);
return judgeWriteStudentMessage;
}
/// <summary>
/// 测试,没有用处。
/// </summary>
/// <param name="test"></param>
/// <returns></returns>
public bool Post2([FromBody]dynamic test)
{
bool judge = false;
if (test.name != "q") judge = true;
return judge;
}
// PUT: actionapi/Student3API/PUT/5
/// <summary>
/// Use to modify student message
/// </summary>
/// <param name="obj">dynamic obj,include a student model{id,name,number,sex,age,course1,course2},post type is [string](age should is int,ID should be exist)</param>
[HttpPost]
public bool Put( [FromBody]dynamic obj)
{
string sqlStr = "ModifyStudentDetails_Id";
SqlParameter[] para =
{
new SqlParameter("@t_id",SqlDbType.Int),
new SqlParameter("@t_name",SqlDbType.VarChar),
new SqlParameter("@t_number",SqlDbType.VarChar),
new SqlParameter("@t_sex",SqlDbType.VarChar),
new SqlParameter("@t_age",SqlDbType.VarChar),
new SqlParameter("@t_course1",SqlDbType.NVarChar),
new SqlParameter("@t_course2",SqlDbType.NVarChar)
};
para[0].Value = Convert.ToInt16(obj.id);
para[1].Value = obj.name;
para[2].Value = obj.number;
para[3].Value = obj.sex;
para[4].Value = Convert.ToInt16(obj.age);
para[5].Value = obj.course1;
para[6].Value = obj.course2;
//需要为空的参数可以赋值为DBNull.Value
//If need null para value,you can assign it is [DBNull.Value].
bool judgeWriteStudentMessage = sqlCommandHelper.WriteStudentMessage(sqlStr, para);
return judgeWriteStudentMessage;
}
// DELETE: actionapi/Student3API/DELETE/5
/// <summary>
/// use to delete a student message due to ID
/// </summary>
/// <param name="id">ID,type is int</param>
[HttpPost]
public bool Delete([FromBody]int id)
{
string sqlStr = "DelStudentDetails";
SqlParameter[] para = { new SqlParameter("@id", SqlDbType.Int) };
para[0].Value =id;
bool judgeWriteStudentMessage = sqlCommandHelper.WriteStudentMessage(sqlStr, para);
return judgeWriteStudentMessage;
}
}
注:其中有一个辅助类,【SqlCommandHelper】,同样在之前的MVC项目中,点击最上方链接进行查看.
然后在右侧的解决方案资源管理器中对项目(解决方案下的父目录)右键发布,新建一个文件夹,并把内容放在其中.
在IIS(Internet信息服务管理器)中右键目录添加一个网站,网站的物理地址就是刚刚发布出的文件夹。
最后,右键浏览IIS中的网站,即可发现一个API的Helper页面。
————————————————————————————————————————————————————
调用API
首先在nuGet中添加一个包:(这个包是HTTPClient的扩展方法,不添加的话会缺少很多方法。)
PM->[Microsoft.AspNet.WebApi.Client]
这个包名,直接搜索可以搜到
在控制器中:
using System.Net.Http;
。。。。
private HttpClient actionAPI = new HttpClient();
因为我用的是HttpClient方法,所以这是一切的开始。
以下为各个api的调用:(有关视图的部分都省略了)
得到所有信息
[HttpGet]
public async System.Threading.Tasks.Task<ActionResult> ShowAllDetailes()
{
actionAPI.BaseAddress = new Uri("http://10.194.46.210/actionapi/Student3API/GET");
List<Models.Student> students = new List<Models.Student>();
string content =await actionAPI.GetStringAsync(actionAPI.BaseAddress);
students = JsonConvert.DeserializeObject<List<Models.Student>>(content);
ViewBag.listStudents = students;
return View("ShowAllDetailes");
}
新增一行信息
[HttpPost]
public async System.Threading.Tasks.Task<ActionResult> CreateNewRecord(FormCollection f)///FormCollection是MVC中表单里的一个集合,它也可以来接收前台提交过来的表单,前台提交过来的表单全都封装到这个对象中来了
{
actionAPI.BaseAddress = new Uri("http://10.194.46.210/actionapi/Student3API/POST");
MVCStudent2.Models.Student2 student2 = new Models.Student2();
student2.name = f["Name"].Trim();
student2.number = f["Number"].Trim();
student2.sex= f["Sex"].Trim();
student2.age= Convert.ToInt16(f["Age"].Trim());
student2.course1 = f["Course1"].Trim();
student2.course2= f["Course2"].Trim();
//string temp = JsonConvert.SerializeObject(student2);
//OpenReadWithHttps(actionAPI.BaseAddress.ToString(), JsonConvert.SerializeObject(student2));
var responseMessage =await actionAPI.PostAsJsonAsync(actionAPI.BaseAddress.ToString(), student2);
bool judgeWriteStudentMessage =responseMessage.IsSuccessStatusCode;
if (judgeWriteStudentMessage == false)
{ return View("FalseOperation"); }
else
{
return View("SuccessfulOperation");
}
}
根据ID得到一条信息
[HttpGet]
public async Task<JsonResult> UpdateAjax_test(string studentID)
{
string uriTemp = "http://10.194.46.210/actionapi/Student3API/GET/" + Convert.ToInt16(studentID);
actionAPI.BaseAddress = new Uri(uriTemp);
List<Models.Student> students = new List<Models.Student>();
string content = await actionAPI.GetStringAsync(actionAPI.BaseAddress);
students = JsonConvert.DeserializeObject<List<Models.Student>>(content);
MVCStudent2.Models.Student student = null;
if (students != null)
{
student= students[0];
}
else
{
return null;
}
return new JsonResult() {
Data=student,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
————————————————————————————————————————————————————
遇到的问题:
1、IIS的正确配置,网站的挂载,挂载时的问题:IIS没有对物理路径的读取访问权限
IIS:全称为Internet Information Services,即互联网信息服务,里面包含了Web服务器、FTP服务器、NNTP服务器、SMTP服务器,分别可以在网络上网页浏览、文件传输、新闻服务和邮件发送。
现在就需要使用到Web服务,因此我们最先需要完成的就是对IIS的正确配置:搭建一个本地的ASP的IIS测试环境。
正确的IIS搭建:
【控制面板】-【程序】-【程序和功能】-【打开和关闭Windows功能】-【internet信息服务】,这里展开,有多个折叠页。
对【安全性】、【常见HTTP功能】、【性能功能】三个折叠页进行全选操作(注意选中的对勾分为两种,高亮的才是全选,黯淡的并非)
对【应用程序开发功能】展开,将【ASP】和【ISAPI扩展】进行全选。
对【运行状况和诊断】展开,将【HTTP日志】【请求监视器】全选。
确定后系统会进行安装,安装后不用重启电脑。
完成上述操作后,在开始菜单的搜索框就可以搜索到IIS(internet信息服务管理器,不是IIS6.0管理器)了。
打开IIS,在左侧添加网站,添加时【网站名称】自定,【应用程序池】可以自定也可以采用IIS中已有的应用程序池,【物理路径】是你程序发布的那个文件夹,【IP地址】需要绑定,【端口】要记住你的端口号,【主机名】在没有域名的情况下不需要绑定。
网站添加之后,双击网站,然后双击中间缩略图中的【ASP】,将其中的启用父路径修改为TRUE(默认FALSE)
最后在【默认文档】中看看是否含有default.html这个选项。
此时你的IIS网站就挂载好了。
警告:IIS没有对物理路径的读取访问权限!
在添加地址时,有一个【测试设置】的按钮,点击后会有个【IIS没有对物理路径的读取访问权限】的错误,这个错误其实不影响你的网站的使用,如果想要将这个警告取消的话,在【连接为】处绑定一个你的计算机帐户密码即可。
2、WebAPI的接口返回类型:在调用post等方法时报错:405,方法不被允许。
这个问题其实是关于HTTP请求的问题。
在API处用HTTP添加相应的标记,例如【HttpPost】【HttpGet】等等,这个标记可以规定只用相应的请求方式才可以访问到对应的Action,同时也会给调用API的用户提示,该用什么方式来调用。
同时在调用API的地方,也要用相应请求方式,调用POST的api就用POST方式,注意不能用post去get一个请求。
3、Http协议和http请求中的8种请求方法
http报文的格式
上个问题说到了HTTP请求,这里就干脆将HTTP请求报文和响应报文学习一下。
请求报文是由客户端向服务端发送的报文,而响应报文则是由服务端向客户端发送的报文。
首先,HTTP的HTTP报文由:起始行(请求报文为请求行、响应报文为响应行)(start line)、首部(header)、主体(body)3个部分组成。
其中请求报文的格式:
请求行:<method><requestURL><version>
首部:<headers>
这里是空行
请求主体:<entiy-body>
响应报文的格式:
响应行:<version><status><reason-phrase>
首部:<headers>
这里是空行
响应主体:<entity-body>
黑色为二者兼具的解释,蓝色为请求报文的格式解释,紫色为响应报文解释:
method(http方式):客户端希望服务器对资源执行的操作。如get,head,post
request-URL(请求地址):所请求的资源地址
version(版本):报文所使用的HTTP版本
status-code(状态码):三个数字描述请求中所发生的情况。如404
reason-phrase(原因短语):数字状态码的可读版本,对状态码的一个简单解释。
headers(首部)可以有零个或多个首部,每个首部都包含一个名字,后面跟着一个冒号:
entiy-body(实体的主体部分):即要传输的内容,图片、视频、文字这些。
HTTP方法(method)
【安全方法】:特指GET方法和HEAD方法,这两种方法除了请求资源外不会有什么动作,也就不会对服务器产生什么结果。
【Get】:
最常见的请求方式,当用户需要从服务器读取文档时使用,请求服务器发送某个资源。
get方法要求 服务器 将URL定位的资源放到 响应报文 的数据部分,回传给客户端,请求过程中的请求数据(向服务端发送的数据)会以地址的形式表现在请求行:参数以【?】附在URL之后,并且各个参数之间要用【&】间隔。
值得注意,参数中包含空格会转换为【+】号,如何是英文字符和数字以外的字符,例如汉字,则将字符串用BACE64加密,得到%E4%BD%A0%E5%A5%BD这样的字符串,其中%XX中的XX是该符号以16进制表示的ASCLL。
特点:
- Get方法速度相对Post要快(因为:1、Get方式会少几个首部Headers的描述字段,2、post会多一个向服务器确认请求头的过程3、get会缓存静态资源,而post不会,注意如果是数据get一般也不缓存,但是浏览器是IE就会……4、涉及一个管道化链接的问题:一种持久化的TCP连接方式,get可以而post非主动开启则不可以)
- Get方法请求的数据是明文,不适合传送私密数据
- 受限于浏览器对地址栏的字符识别,也不适合传递大量数据。
- 附注:post和get请求的过程:
SYN:同步序列编号(Synchronize Sequence Numbers)
- get请求过程:(将三次握手一并写出)
- 浏览器请求tcp连接(第一次握手):客户端发送syn(syn=j)包到服务器,进入syn_send状态
- 服务器应答进行tcp连接(第二次握手):确认客户的SYN(即ACK=J+1),加上自己发送的一个syn(syn=k)包,一起发到客户端(即SYN+ACK包),此时的服务器就变成了SYN_RECV状态;
- 浏览器确认,发送get请求头和数据(第三次握手):客户端收到了服务端发来的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),发送完毕后客户端和服务端同时进入Establishid状态,完成三次握手。开始发送数据。
- 服务器发送200,响应ok。
- post请求过程:对比get发现数据发送的不同,get是在请求头发送时将数据附带在协议头<request-line>发送,而post的数据则是单另发送。
- 浏览器请求tcp连接(第一次握手):
- 服务器应答进行tcp连接(第二次握手):
- 浏览器确认,发送post请求头
- 服务器返回100,continue响应
- 浏览器开始发送数据
- 服务器返回200,响应ok。
【post】:
最常见的请求方式,允许客户端给服务端提供较多信息。POST方法将请求参数封装在HTTP请求数据中,相对get有一定安全性;以【名称/值】的形式出现,可以传输大量数据。
POST的数据放置在HTTP包的包体<entiy-body>中。
注意其实get的功能都可以由post方式来完成,因此往往各种表单提交时都会使用post,这一点就好还是根据情形来选择,可以有效提高效率。
【Head】:
这是继上面两个后常用的方法。
这是很类似于get的一个方法,安全,高效,只不过不同于get的是,服务端接受了Head请求仅仅会返回响应头,而不会返回响应内容,因此当我们需要查看某个页面的状态时,使用HEAD会非常高效,因为这个过程省略了页面内容。
【PUT】:
注:以下几个都没有用过,这里罗列资料,未来使用时将对此进行补充修改
PUT方法的语意就是让服务器用请求的主体部分,来创建一个由请求的URL命名的新文档,或者,如果那个URL已经存在的话,就用这个新主体代替它。
因为PUT允许用户对内容进行修改,所以很多WEB服务器要求执行PUT方法之前,用密码登陆。
【DELETE】:
DELETE方法所做的事情就是请服务器删除请求URL所指定的资源;但是客户端无法确保删除操作一定会被执行。
因为HTTP规范允许服务器在不通知客户端的情况下撤销请求。
【TRACE】:
客户端发起一个请求时,这个请求可能要穿过防火墙、代理、网关或其他一些应用程序。没个中间节点可能会修改原始的HTTP请求。TRACE方法允许客户端在最终将请求发送给服务器时,看看它变成了什么样子。
TRACE请求会在目的服务器端发起一个“环回”诊断。行程最后一站的服务器会弹会一条TRACE响应,并在响应主体中携带它收到的原始请求报文。
TRACE方法主要用于诊断;也就是说用于验证是否如愿穿过了请求/响应链。
TRACE请求中不能带有实体的主体部分(应该是不能带有请求主体的意思?)。
【OPTIONS】:
OPTIONS方法请求Web服务器告知其支持的各种功能。他可以访问服务器通常支持哪些方法,或者针对某些特定的资源支持哪些特定的操作。
这为客户端应用程序提供了一种手段,使其不用实际访问那些资源就可以判定访问这些资源的最优方式。
(意思是可以借助这个知道要访问的API可以使用的HTTP方法类型?)
【扩展方法】:
HTTP被设计成字段可扩展的,这样新的特性就不会使老的软件失效了。扩展方法指的是没有在HTTP/1.1规范中定义的方法,服务器会为他所管理的资源实现一些HTTP服务,这些方法为开发者提供了一些扩展HTTP服务能力的手段。
常见的扩展方法示例:(当前还没用过)
[LOCK]:允许用户锁定资源,可以在编辑某个资源的时候让资源锁定,使其他人无法修改
[MKCOL]:允许用户创建资源
[COPY]:便于在服务器上复制资源
[MOVE]:在服务器上复制资源
HTTP请求头、相应头(首部)
首先看一下首部的结构:
<headers>{
请求/响应首部字段
通用首部字段
实体首部字段
}
HTTP报文首部作用:
在客户端和服务端以HTTP协议进行通信的时候,无论是请求还是响应都会使用首部字段,起到传递额外信息的作用,包括报文主体大小,所使用语言,认证信息内容等等。
HTTP报文首段字段结构:
首部字段由字段名和字段值构成,格式:【首部字段名:字段值】
另外单个HTTP首部字段可以有多个值,值之间用逗号(,)间隔:
Keep-Alive:timeout=15,max=100
HTTP首部结构详解:
4、在API发布后,调试时弹出“您正在调试XXX的发布版本。。。。调试体验会降级。。。例如不会命中断点。”
这是一个很简单的问题。
在你把程序发布后,程序会自动把调试处的解决方案配置自动由【Debug】变更为【Release】,改回来就好了。
5、设置防火墙,实现局域网访问你的IIS。
首先要看清自己的IIS使用的是什么端口。
查看方式:打开IIS,点击对应的网站,点击高级设置,看【绑定】一栏,里面会有IP和端口的绑定,端口默认为80,这个绑定在新建网站时可以改变。
然后打开【网络和共享中心】-左下角【windows防火墙】-左侧【高级设置】,在【入站规则】和【出站规则】处新建一个对【80端口】(你设定的端口号)放行的规则即可。即可。
6、JSON保存为字符串后,出现的斜杠问题,以及该如何处理这个斜杠.
因为JSON传回来时,其中的【"】是通过转义字符【//】来处理的,如果直接将JSON字符串打印出来会有很多的斜杠,类似于:
string s1 ="[{\"ID\":\"99d2a341-ea2e-4f04-b4f4-623153d64336\",\"Name\":\"王五\",\"TotalScores\":80,\"工作效率\":\"B\".........}
这个时候固然可以直接进行反斜杠处理从而去除斜杠,但这样很费事且容易将本来具有的斜杠字符一起去除。
所以比较好的解决办法是直接反序列化处理。
比如这里在做WebAPI,比如这个方法:
// GET APITest1/Test1/Action/5
public string Get(int id)
{
string a=某个JSON字符串;
return a;
}
它的返回类型是string字符串,在调用时会自动的以xml来展示。
因此我们会看到带有斜杠的JSON文本以XML的文本形式出现。
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
"[{\"ID\":\"99d2a341-ea2e-4f04-b4f4-623153d64336\",\"Name\":\"王五\",\"TotalScores\":80,\"工作效率\":\"B\".........}
</string>
如果我们让Webapi直接用JSONResult来返回数据就是正常的JSON文本了,也不会嵌套在XML中。
[HttpGet]
public JsonResult<List<Student>> Get()
{
string sqlStr = "GetAllUserDetails";
List<Student> students = new List<Models.Student>();
students = sqlCommandHelper.GETStudentMessage(sqlStr, -1);
return Json<List<Student>>(students);
}
7、WebApi的传参数问题,如何给Webapi传递参数
首先确定的一件事:Webapi接受的参数也好,传出的数据也好,最好是JSON格式。
其次,是在api中设置好参数类型,因为我在调用时使用的是HttpClient(里面的多数请求方法要求只有一个参数),因此api只能一个参数来接收传递过来的数据。
这个时候JSON的好处就体现了,因为可以用一串JSON字符串来传递多个键值对。当然,你也可以直接传递一个类,不过这样一来API感觉就没有那么灵活。
json数据当然可以直接用【string】,也可以用【dynamic】,它可以在你运行时解析你的对象,即动态解析。
例如:
public bool Post2([FromBody]dynamic test)
{
bool judge = false;
if (test.name != "q") judge = true;
return judge;
}
这里test会被动态解析,直接读出它的属性"name"。
上面这些是API中的参数类型设置,下面将说我在调用API时的参数传递。
例:
[HttpPost]
public async System.Threading.Tasks.Task<ActionResult> DelDetaile(FormCollection f)
{
actionAPI.BaseAddress = new Uri("http://10.194.46.210/actionapi/Student3API/Delete");
var responseMessage = await actionAPI.PostAsJsonAsync(actionAPI.BaseAddress.ToString(),Convert.ToInt16(f["Id"]));
bool judgeWriteStudentMessage = responseMessage.IsSuccessStatusCode;
if (judgeWriteStudentMessage == false)
{ return View("FalseOperation"); }
else
{ return View("SuccessfulOperation"); }
调用时我使用了HttpClient,它有个好处是所有的方法都是异步的,且它所有传递的参数都会自动转换为JSON类型。
单独将这句摘出来。
actionAPI.PostAsJsonAsync(actionAPI.BaseAddress.ToString(),Convert.ToInt16(f["Id"]));
除了使用HttpClient外,还有一种方法,就是借助HttpWebRequest和HttpWebResponse。
用到时如下调用,URL是api地址,strpostdata是你要传递的数据,会在这里自动转换为JSON。
public string OpenReadWithHttps(string URL, string strPostdata)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.CookieContainer = new CookieContainer();
request.Method = "POST";
request.ContentType = "application/json";
byte[] buffer = Encoding.Default.GetBytes(strPostdata);
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
var end = reader.ReadToEnd();
return end.ToString();
}
8、如何对API进行测试?如何给POST等方式进行测试?
第一:推荐使用postman工具(谷歌浏览器直接由对应的插件)
这个小工具可以对任何api进行访问测试,具体的使用方法下载后一眼就能看明白,注意不需要注册。
第二:使用NuGet使用大佬的程序包:【WebApiTestClient 】
9、API访问时出现httpput和httpdelete的谓词问题,该如何处理。
这个问题往往是出现在需要调用httpdelete和httpput请求。
首先要知道的是,如果你用form表单传递这两种请求,默认会变成get的请求方式,这是因为老的html不支持get和post以外的请求方式,html5后才支持。目前我没找到办法,似乎添加请求头可以????
使用ajax传递这两种请求倒是可以通过。
总之,如果出现这个问题……推荐使用post方式……
如果特别想解决这个问题……看论坛似乎在IIS和api的web.config中进行修改也可以实现……参考这个
10、如何给APIhelp页面添加注释:
这个暂时先空着,遇到了问题没有解决。
11、此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站
这个问题主要出现在给前台ajax返回JsonResult时。
解决方法:返回时加上对客户端get方式的允许即可。
return new JsonResult() {
Data=student,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};