(1)查询字符串参数名称和操作方法参数名称必须相同(不区分大小写)。参数的先后顺序可以不一致。
(2)Get()参数传递的本质是URL字符串拼接,但是URL字符串的长度受限制。
(3)Get()的参数支持基本数据类型,不支持实体数据类型。
(4)Get()参数的传递是在Http请求的头部传递,而不支持Request-Body传递。
(5)Get类型的方法命名,尽量采用“Get+方法名”的命名方式,在方法前面加上特性:[HttpGet]。
二、Post
1、Post参数传递是在Request-Body内传递。
2、Post参数可以传递基本数据类型,也可以传递实体数据类型。
3、Post操作方法只能包含一个实体数据类型,因为只能允许一个参数读取Request-Body中的数据。
4、Post传递参数时,无论是基本类型参数还是实体类型,均需要借助[FromBody]特性。(有些情况下不写[FromBody]特性也可以把参数传递进来,但为了规范化,最好是加上该特性)。
5、Post类型的方法命名,尽量采用“Post+方法名”的命名方式,在方法前面加上特性:[HttpPost]。
三、FromURI与FromBody
在默认情况下,Web API是从查询字符串中得到基本数据类型参数的值,从请求主体中得到复杂类型参数的值,如果想改变这种默认情况怎么办?
可以使用[FromURI]属性,是Web API从查询字符串中获取复杂类型参数的值,使用[FromBody]属性可以使Web API从请求主体中获取基本数据类型参数的值。
例如下面的Get方法
[HttpGet]
public string GetStudentById([FromUri]Student stu)
{
}
Get方法中包括复杂的类型参数,参数添加了[FromUri]属性,Web API将试图从查询字符串中得到Student类型参数的值。
同样,参考下面的Post方法:
[HttpPost]
public string Post([FromBody]string name)
{ }
Web API将从请求主体中获取基本类型参数的值,而不是从请求字符串中获取。
前言
这部分内容大致和MVC部分差不多。在学习参事绑定之前,我们肯定要知道Controller(即控制器)是啥干啥的。
>>>其实,Controller(控制器)就是一个类,我们可以将它 放到项目根目录文件夹下的任何位置,当然,我们一般将它放到Controllers文件夹下(这是一个很好的习惯,因为这样方便管理,更方便以后的学习,在MVC中,有一个重要的规则:约定大于配置)。一个控制器类是个特殊类,类名必须以"Controller"结尾,并且必须继承于System.Web.Http.ApiController类,控制器中有大量的公共方法,即操作方法(公开接口)。Web Api仅仅支持HTTP
在了解Controller后,我们就想,如何进行参数绑定呢?下面我们继续学习。关于参数绑定问题,无非就是简单类型与复杂类型,单个参数与多个参数。Web API根据URL的查询字符串或请求主体中参数类型来绑定操作方法的参数。简单类型将会从querystring中获取,复杂类型参数,则Web Api默认将试图从请求主体获取值。
HTTP方法 | Query String | Request Body |
GET | 简单类型 | 不能从请求主体中获取参数值 |
POST | 简单类型 | 复杂类型 |
PUT | 简单类型 | 复杂类型 |
PATCH | 简单类型 | 复杂类型 |
DELETE | 简单类型 | 不能从请求主体中获取参数值 |
using Newtonsoft.Json.Linq;
using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Newtonsoft.Json;
using System.Text;
using System.Web.Security;
//using System.Web.Http.Cors;//Microsoft.AspNet.WebApi.Cors
namespace SOA.Web.Controllers
{
[BasicAuthorize]
public class UsersController : ApiController
{
/// <summary>
/// User Data List
/// </summary>
private List<Users> _userList = new List<Users>
{
new Users {UserID = 1, UserName = "Superman", UserEmail = "Superman@cnblogs.com"},
new Users {UserID = 2, UserName = "Spiderman", UserEmail = "Spiderman@cnblogs.com"},
new Users {UserID = 3, UserName = "Batman", UserEmail = "Batman@cnblogs.com"}
};
#region 用户登陆
[AllowAnonymous]
[HttpGet]
public string Login(string account, string password)
{
if (account.Equals("Admin") && password.Equals("123456"))
{
FormsAuthenticationTicket ticketObject = new FormsAuthenticationTicket(0, account, DateTime.Now,
DateTime.Now.AddHours(1), true, string.Format("{0}&{1}", account, password),
FormsAuthentication.FormsCookiePath);
var result = new { Result = true, Ticket = FormsAuthentication.Encrypt(ticketObject) };
return JsonConvert.SerializeObject(result);
}
else
{
var result = new { Result = false };
return JsonConvert.SerializeObject(result);
}
}
#endregion
#region HttpGet
// GET api/Users
[HttpGet]
public IEnumerable<Users> Get()
{
return _userList;
}
// GET api/Users/5
[HttpGet]
[AllowAnonymous]
//[EnableCors(origins: "http://localhost:9008/", headers: "*", methods: "GET,POST,PUT,DELETE")]
public Users GetUserByID(int id)
{
string idParam = HttpContext.Current.Request.QueryString["id"];
var user = _userList.FirstOrDefault(users => users.UserID == id);
//传入User返回Boolean,符合条件返回true,返回User,内部循环集合每一个(项)User
var user2 = _userList.FirstOrDefault(u => u.UserID == id);
if (user == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
//throw new HttpResponseException(HttpStatusCode.NotFound);
}
return user;
}
//GET api/Users/?username=xx
[HttpGet]
public IEnumerable<Users> GetUserByName(string userName)
{
string userNameParam = HttpContext.Current.Request.QueryString["userName"];
return _userList.Where(p => string.Equals(p.UserName, userName, StringComparison.OrdinalIgnoreCase));
}
//GET api/Users/?username=xx&id=1
[HttpGet]
public IEnumerable<Users> GetUserByNameId(string userName, int id)
{
string idParam = HttpContext.Current.Request.QueryString["id"];
string userNameParam = HttpContext.Current.Request.QueryString["userName"];
return _userList.Where(p => string.Equals(p.UserName, userName, StringComparison.OrdinalIgnoreCase));
}
[HttpGet]
public IEnumerable<Users> GetUserByModel(Users user)//User数据会到请求报文体中查询(因为Get请求,查询不到)
{
string idParam = HttpContext.Current.Request.QueryString["id"];
string userNameParam = HttpContext.Current.Request.QueryString["userName"];
string emai = HttpContext.Current.Request.QueryString["email"];
return _userList;
}
[HttpGet]
public IEnumerable<Users> GetUserByModelUri([FromUri]Users user)
{
string idParam = HttpContext.Current.Request.QueryString["id"];
string userNameParam = HttpContext.Current.Request.QueryString["userName"];
string emai = HttpContext.Current.Request.QueryString["email"];
return _userList;
}
[HttpGet]
public IEnumerable<Users> GetUserByModelSerialize(string userString)
{
Users user = JsonConvert.DeserializeObject<Users>(userString);//反序列化
return _userList;
}
//[HttpGet]
public IEnumerable<Users> GetUserByModelSerializeWithoutGet(string userString)
{
Users user = JsonConvert.DeserializeObject<Users>(userString);
return _userList;
}
/// <summary>
/// 方法名以Get开头,WebApi会自动默认这个请求就是get请求,而如果你以其他名称开头而又不标注方法的请求方式,那么这个时候服务器虽然找到了这个方法,但是由于请求方式不确定,所以直接返回给你405——方法不被允许的错误。
/// 最后结论:所有的WebApi方法最好是加上请求的方式([HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]),不要偷懒,这样既能防止类似的错误,也有利于方法的维护,别人一看就知道这个方法是什么请求。
/// </summary>
/// <param name="userString"></param>
/// <returns></returns>
public IEnumerable<Users> NoGetUserByModelSerializeWithoutGet(string userString)
{
Users user = JsonConvert.DeserializeObject<Users>(userString);
return _userList;
}
#endregion HttpGet
#region HttpPost
//POST api/Users/RegisterNone
[HttpPost]
public Users RegisterNone()
{
return _userList.FirstOrDefault();
}
[HttpPost]
public Users RegisterNoKey([FromBody]int id)
{
string idParam = HttpContext.Current.Request.Form["id"];
var user = _userList.FirstOrDefault(users => users.UserID == id);
if (user == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return user;
}
//POST api/Users/register
//只接受一个参数的需要不给key才能拿到
[HttpPost]
public Users Register([FromBody]int id)//可以来自FromBody FromUri
//public Users Register(int id)//可以来自url
{
string idParam = HttpContext.Current.Request.Form["id"];
var user = _userList.FirstOrDefault(users => users.UserID == id);
if (user == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return user;
}
//POST api/Users/RegisterUser
[HttpPost]
public Users RegisterUser(Users user)//可以来自FromBody FromUri
{
string idParam = HttpContext.Current.Request.Form["UserID"];
string nameParam = HttpContext.Current.Request.Form["UserName"];
string emailParam = HttpContext.Current.Request.Form["UserEmail"];
//var userContent = base.ControllerContext.Request.Content.ReadAsFormDataAsync().Result;
var stringContent = base.ControllerContext.Request.Content.ReadAsStringAsync().Result;
return user;
}
//POST api/Users/register
[HttpPost]
public string RegisterObject(JObject jData)//可以来自FromBody FromUri
{
string idParam = HttpContext.Current.Request.Form["User[UserID]"];
string nameParam = HttpContext.Current.Request.Form["User[UserName]"];
string emailParam = HttpContext.Current.Request.Form["User[UserEmail]"];
string infoParam = HttpContext.Current.Request.Form["info"];
dynamic json = jData;
JObject jUser = json.User;
string info = json.Info;
var user = jUser.ToObject<Users>();
return string.Format("{0}_{1}_{2}_{3}", user.UserID, user.UserName, user.UserEmail, info);
}
[HttpPost]
public string RegisterObjectDynamic(dynamic dynamicData)//可以来自FromBody FromUri
{
string idParam = HttpContext.Current.Request.Form["User[UserID]"];
string nameParam = HttpContext.Current.Request.Form["User[UserName]"];
string emailParam = HttpContext.Current.Request.Form["User[UserEmail]"];
string infoParam = HttpContext.Current.Request.Form["info"];
dynamic json = dynamicData;
JObject jUser = json.User;
string info = json.Info;
var user = jUser.ToObject<Users>();
return string.Format("{0}_{1}_{2}_{3}", user.UserID, user.UserName, user.UserEmail, info);
}
#endregion HttpPost
#region HttpPut
//POST api/Users/RegisterNonePut
[HttpPut]
public Users RegisterNonePut()
{
return _userList.FirstOrDefault();
}
[HttpPut]
public Users RegisterNoKeyPut([FromBody]int id)
{
string idParam = HttpContext.Current.Request.Form["id"];
var user = _userList.FirstOrDefault(users => users.UserID == id);
if (user == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return user;
}
//POST api/Users/registerPut
//只接受一个参数的需要不给key才能拿到
[HttpPut]
public Users RegisterPut([FromBody]int id)//可以来自FromBody FromUri
//public Users Register(int id)//可以来自url
{
string idParam = HttpContext.Current.Request.Form["id"];
var user = _userList.FirstOrDefault(users => users.UserID == id);
if (user == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return user;
}
//POST api/Users/RegisterUserPut
[HttpPut]
public Users RegisterUserPut(Users user)//可以来自FromBody FromUri
{
string idParam = HttpContext.Current.Request.Form["UserID"];
string nameParam = HttpContext.Current.Request.Form["UserName"];
string emailParam = HttpContext.Current.Request.Form["UserEmail"];
//var userContent = base.ControllerContext.Request.Content.ReadAsFormDataAsync().Result;
var stringContent = base.ControllerContext.Request.Content.ReadAsStringAsync().Result;
return user;
}
//POST api/Users/registerPut
[HttpPut]
public string RegisterObjectPut(JObject jData)//可以来自FromBody FromUri
{
string idParam = HttpContext.Current.Request.Form["User[UserID]"];
string nameParam = HttpContext.Current.Request.Form["User[UserName]"];
string emailParam = HttpContext.Current.Request.Form["User[UserEmail]"];
string infoParam = HttpContext.Current.Request.Form["info"];
dynamic json = jData;
JObject jUser = json.User;
string info = json.Info;
var user = jUser.ToObject<Users>();
return string.Format("{0}_{1}_{2}_{3}", user.UserID, user.UserName, user.UserEmail, info);
}
[HttpPut]
public string RegisterObjectDynamicPut(dynamic dynamicData)//可以来自FromBody FromUri
{
string idParam = HttpContext.Current.Request.Form["User[UserID]"];
string nameParam = HttpContext.Current.Request.Form["User[UserName]"];
string emailParam = HttpContext.Current.Request.Form["User[UserEmail]"];
string infoParam = HttpContext.Current.Request.Form["info"];
dynamic json = dynamicData;
JObject jUser = json.User;
string info = json.Info;
var user = jUser.ToObject<Users>();
return string.Format("{0}_{1}_{2}_{3}", user.UserID, user.UserName, user.UserEmail, info);
}
#endregion HttpPut
#region HttpDelete
//POST api/Users/RegisterNoneDelete
[HttpDelete]
public Users RegisterNoneDelete()
{
return _userList.FirstOrDefault();
}
[HttpDelete]
public Users RegisterNoKeyDelete([FromBody]int id)
{
string idParam = HttpContext.Current.Request.Form["id"];
var user = _userList.FirstOrDefault(users => users.UserID == id);
if (user == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return user;
}
//POST api/Users/registerDelete
//只接受一个参数的需要不给key才能拿到
[HttpDelete]
public Users RegisterDelete([FromBody]int id)//可以来自FromBody FromUri
//public Users Register(int id)//可以来自url
{
string idParam = HttpContext.Current.Request.Form["id"];
var user = _userList.FirstOrDefault(users => users.UserID == id);
if (user == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return user;
}
//POST api/Users/RegisterUserDelete
[HttpDelete]
public Users RegisterUserDelete(Users user)//可以来自FromBody FromUri
{
string idParam = HttpContext.Current.Request.Form["UserID"];
string nameParam = HttpContext.Current.Request.Form["UserName"];
string emailParam = HttpContext.Current.Request.Form["UserEmail"];
//var userContent = base.ControllerContext.Request.Content.ReadAsFormDataAsync().Result;
var stringContent = base.ControllerContext.Request.Content.ReadAsStringAsync().Result;
return user;
}
//POST api/Users/registerDelete
[HttpDelete]
public string RegisterObjectDelete(JObject jData)//可以来自FromBody FromUri
{
string idParam = HttpContext.Current.Request.Form["User[UserID]"];
string nameParam = HttpContext.Current.Request.Form["User[UserName]"];
string emailParam = HttpContext.Current.Request.Form["User[UserEmail]"];
string infoParam = HttpContext.Current.Request.Form["info"];
dynamic json = jData;
JObject jUser = json.User;
string info = json.Info;
var user = jUser.ToObject<Users>();
return string.Format("{0}_{1}_{2}_{3}", user.UserID, user.UserName, user.UserEmail, info);
}
[HttpDelete]
public string RegisterObjectDynamicDelete(dynamic dynamicData)//可以来自FromBody FromUri
{
string idParam = HttpContext.Current.Request.Form["User[UserID]"];
string nameParam = HttpContext.Current.Request.Form["User[UserName]"];
string emailParam = HttpContext.Current.Request.Form["User[UserEmail]"];
string infoParam = HttpContext.Current.Request.Form["info"];
dynamic json = dynamicData;
JObject jUser = json.User;
string info = json.Info;
var user = jUser.ToObject<Users>();
return string.Format("{0}_{1}_{2}_{3}", user.UserID, user.UserName, user.UserEmail, info);
}
#endregion HttpDelete
}
#region API权限验证
/// <summary>
/// API权限验证
/// </summary>
public class BasicAuthorize : AuthorizeAttribute
{
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
var authorization = actionContext.Request.Headers.Authorization;
if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>(true).Count != 0
|| actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>(true).Count != 0)
{
base.OnAuthorization(actionContext);
}
else if (authorization != null && authorization.Parameter != null)
{
//用户验证逻辑
if (ValidateTicket(authorization.Parameter))
{
base.IsAuthorized(actionContext);
}
else
{
this.HandleUnauthorizedRequest(actionContext);
}
}
else
{
this.HandleUnauthorizedRequest(actionContext);
}
}
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);//告诉浏览器要验证
challengeMessage.Headers.Add("WWW-Authenticate", "Basic");//权限信息放在basic
//throw new System.Web.Http.HttpResponseException(challengeMessage);
base.HandleUnauthorizedRequest(actionContext);//返回没有授权
}
private bool ValidateTicket(string encryptTicket)
{
//解密Ticket
var strTicket = FormsAuthentication.Decrypt(encryptTicket).UserData;
return string.Equals(strTicket, string.Format("{0}&{1}", "Admin", "123456"));//应该分拆后去数据库验证
}
}
#endregion
public class Users
{
public int UserID { get; set; }
public string UserName { get; set; }
public string UserEmail { get; set; }
}
}
JQ-Ajax前端调用:
<script src="/Scripts/jquery-1.10.2.js"></script>
<script>
$(function () {
var user = { UserID: "11", UserName: "Eleven", UserEmail: "57265177@qq.com" };
var info = "this is muti model";
$("#btnGet1").on("click", function () {
//$.ajax({ url: "/api/users", type: "get", data: { "userName": "Superman" }, success: function (data) { alert(data); }, datatype: "json" });//指向接口,参数匹配的,大小写不区分
$.ajax({
url: "/api/users/GetUserByName", type: "get", data: { "username": "Superman" },
beforeSend: function (XHR) {
//发送ajax请求之前向http的head里面加入验证信息
XHR.setRequestHeader('Authorization', 'BasicAuth ' + ticket);
},
success: function (data) {
alert(data);
}, datatype: "json"
});
});
$("#btnGet2").on("click", function () {//单个参数
$.ajax({ url: "/api/users/GetUserByID", type: "get", data: { "id": $("#txtId").val() }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnGet3").on("click", function () {//两个参数
$.ajax({ url: "/api/users/GetUserByNameId", type: "get", data: { "userName": "Superman", "id": $("#txtId").val() }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnGet4").on("click", function () {//无参数
$.ajax({ url: "/api/users/Get", type: "get", data: "", success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnGet5").on("click", function () {//传递实体 json对象
$.ajax({ url: "/api/users/GetUserByModel", type: "get", data: user, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnGet6").on("click", function () {//传递实体
$.ajax({ url: "/api/users/GetUserByModelUri", type: "get", data: user, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnGet7").on("click", function () {//传递实体,序列化后传递
$.ajax({ url: "/api/users/GetUserByModelSerialize", type: "get", data: { userString: JSON.stringify(user) }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnGet8").on("click", function () {//传递实体,序列化后传递
$.ajax({ url: "/api/users/GetUserByModelSerializeWithoutGet", type: "get", data: { userString: JSON.stringify(user) }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnGet9").on("click", function () {//传递实体,序列化后传递 405 Method Not Allowed 不带httpget需要用get开头
$.ajax({ url: "/api/users/NoGetUserByModelSerializeWithoutGet", type: "get", data: { userString: JSON.stringify(user) }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnPost1").on("click", function () {//单个值传递,json数据不要key,这样后台才能获取
$.ajax({ url: "/api/users/RegisterNoKey", type: "post", data: { "": $("#txtId").val() }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnPost2").on("click", function () {//key-value形式后台拿不到这个参数,但是可以直接访问Querstringid
$.ajax({ url: "/api/users/Register", type: "post", data: { "id": $("#txtId").val() }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnPost3").on("click", function () {//传递json格式的,后台可以用实体接收
$.ajax({ url: "/api/users/RegisterUser", type: "post", data: user, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnPost4").on("click", function () {//传递json序列化后的格式,后台可以用实体接收,需要指定contentType
$.ajax({ url: "/api/users/RegisterUser", type: "post", data: JSON.stringify(user), success: function (data) { alert(data); }, datatype: "json", contentType: 'application/json', });
});
$("#btnPost5").on("click", function () {//JObject接收 多个参数传递
$.ajax({ url: "/api/users/RegisterObject", type: "post", data: { "User": user, "Info": info }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnPost6").on("click", function () {//Dynamic 失败了
$.ajax({ url: "/api/users/RegisterObjectDynamic", type: "post", data: { "User": user, "Info": info }, success: function (data) { alert(data); }, datatype: "json", contentType: 'application/json' });
});
$("#btnPut1").on("click", function () {//单个值传递,json数据不要key,这样后台才能获取
$.ajax({ url: "/api/users/RegisterNoKeyPut", type: "put", data: { "": $("#txtId").val() }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnPut2").on("click", function () {//key-value形式后台拿不到
$.ajax({ url: "/api/users/RegisterPut", type: "put", data: { "id": $("#txtId").val() }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnPut3").on("click", function () {//传递json格式的,后台可以用实体接收
$.ajax({ url: "/api/users/RegisterUserPut", type: "put", data: user, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnPut4").on("click", function () {//传递json序列化后的格式,后台可以用实体接收,需要指定contentType
$.ajax({ url: "/api/users/RegisterUserPut", type: "put", data: JSON.stringify(user), success: function (data) { alert(data); }, datatype: "json", contentType: 'application/json', });
});
$("#btnPut5").on("click", function () {//JObject接收
$.ajax({ url: "/api/users/RegisterObjectPut", type: "put", data: { "User": user, "Info": info }, success: function (data) { alert(data); }, datatype: "json" });
});
$("#btnPut6").on("click", function () {//Dynamic 失败了
$.ajax({ url: "/api/users/RegisterObjectDynamicPut", type: "put", data: { "User": user, "Info": info }, success: function (data) { alert(data); }, datatype: "json", contentType: 'application/json' });
});
//delete一样 type换成delete
在此,我们使用了FromUri属性,当发起HTTP GET请求http://localhost:15939/api/hello?ID=2&name=sss&age=19时,Web Api将创建一个Student对象实例,然后从query string中获取id、name和age数据并将数据复制给Student对象实例,这样Web Api将从query string中提取Student实例对象的属性值,而不用去请求主体.