上篇介绍了如何从输入流中获取实体对象。本篇介绍以url形式传递参数。简单的参数不再赘述,这里主要实现形如(string name,Woman woman)这样的参数传递。
本篇及后面几章均涉及js调用及C#调用,而且篇幅较长,请大家见谅。
一、js调用。
WebApi:
public class ValuesController : ApiController { [HttpPost] public string GetData(string name,Woman woman) { return "我是" + name + ",我喜欢" + woman.Name; } [HttpPost] public string GetData(Woman woman) { return woman.Age + "的" + woman.Name; } } public class Woman//仅仅为了演示方便 { public string Name{ get;set;} public string Age{ get;set;} }
JS端。JS端的obj2url(对象生成键值对)实现方法比较丑陋,如果有更好的方法请大家不吝赐教。
var woman = { Name: '刘亦菲', Age: 18 }; function obj2url(obj) { var result=''; for (var i in obj) { result += i + "=" + obj[i]+ "&"; } return result.substr(0, result.length - 1);//返回 Name=刘亦菲&Age=18 } $(function () { $('#btn').click(function () { $.ajax({ type: "post", url: "http://localhost:7601/api/values/GetData?name=楼主", data: obj2url(woman), success: function (r) { alert(r); } }); }); });
如果是执行表单提交,则可以直接利用jq的 $('#formID').serialize()直接获取键值对。
看请求数据:
执行结果:
这里有两点注意:
1、浏览器发起的请求,url中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,也就是会自动urlencode。
2、请求中的Form Data,未经编码,也能正确的传递到Api中。(如:Name:刘亦 菲?/)
这是经过试验得出来的,理论依据没找。结论是否正确?忘有那位朋友不吝赐教。
二、C#调用。这里主要涉及
服务端WebApi代码不变。给Woman类添加一个属性,public List<DateTime> ExerciseTime { get; set; },来增大难度。
客户端:
首先来个基础调用类:此类是用HttpWebRequest发起请求,是同步的,后期我们会升级到HttpClient,异步。
//PostService.cs public class PostService { public bool PostWebRequest(string postUrl, string postvalue, out string returnValue) { returnValue = string.Empty; try { byte[] byteData = Encoding.UTF8.GetBytes(postvalue); Uri uri = new Uri(postUrl); HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(uri); webReq.Method = "POST"; webReq.ContentType = "application/x-www-form-urlencoded"; webReq.ContentLength = byteData.Length; //定义Stream信息 Stream stream = webReq.GetRequestStream(); stream.Write(byteData, 0, byteData.Length); stream.Close(); //获取返回信息 HttpWebResponse response = (HttpWebResponse)webReq.GetResponse(); StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); returnValue = streamReader.ReadToEnd(); //关闭信息 streamReader.Close(); response.Close(); stream.Close(); return true; } catch (Exception ex) { returnValue = ex.Message; return false; } } }
具体调用代码:
private void btnPost_Click(object sender, EventArgs e) { NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty); queryString["Name"] = "刘亦菲"; queryString["Age"] = "18"; queryString["ExerciseTime[0]"] = DateTime.Now.ToString(); queryString["ExerciseTime[1]"] = DateTime.Now.AddHours(-12).ToString(); queryString["ExerciseTime[2]"] = "哈哈"; string postdata = queryString.ToString(); // Returns "key1=value1&key2=value2", all URL-encoded //string postdata = "Name=刘亦菲&Age=18";//string postdata = "Name=刘亦 菲?/&Age=18";也OK。 string url = "http://localhost:7601/api/values/GetData?name=楼主"; string retValue = ""; PostService service = new PostService(); service.PostWebRequest(url, postdata, out retValue); MessageBox.Show(retValue); }
调用结果:
传入的Name为编码后的值,需要解码才能获得正确的值。有点奇怪。
好吧,再做一次试验:
调用代码修改一下,不编码直接拼字符串:
string postdata = "Name=刘亦菲&Age=18";//string postdata = "Name=刘亦 菲?/&Age=18";也OK。 string url = "http://localhost:7601/api/values/GetData?name=楼主"; string retValue = ""; PostService service = new PostService(); service.PostWebRequest(url, postdata, out retValue);
结论:由客户端发起的请求数据,需要编码、解码配对使用。
基础差啊,就表现出来了。原理、原理、原理,说三遍。忘知道的员友不吝赐教。
注意1、List<T>的传参方式。2、类的属性为实体类的情况,比如:
public class Woman//仅仅为了演示方便 { public string Name{ get;set;} public string Age{ get;set;} public ListExerciseTime { get; set; } public Son Son { get; set; } } public class Son { public string Name{ get;set;} public int Age{ get;set;} }
那么猜想的传递方法为:
queryString["Son.Name"] = "儿子"; queryString["Son.Age"] = "2";
再复杂一点,有几个儿子:
public ListSon { get; set; }
那么猜想的传递方法为:
queryString["Son[0].Name"] = "儿子"; queryString["Son[0].Age"] = "2";
请员友自行验证。