在Core环境下用WebRequest连接上远程的web Api 实现数据的简单CRUD(续)
这篇博客是上篇博客的续写,上篇博客用的是HttpClient取远程数据,用WebRequest提交,更新,删除数据。
今天进行了一下修改,全程用的都是HttpClient
说一下实现过程吧。
在实现的过程中,我发现了PostAsync和PutAsync需要的参数都是一个类型的,DeleteAsyc和GetAsync需要的参数都是一个类型的。那么这就省很多事了只用一个方法+反射,里边再加一个if{...}else{...}就可解决四个问题了。
主要就是添加了HandleDataFactoryAsync这个方法里边注释写的很详细。
1 /// <summary> 2 /// 这是用HttpClient调用Web Api实现CRUD到数据库中 3 /// </summary> 4 /// <param name="u">数据</param> 5 /// <param name="url">请求的url</param> 6 /// <param name="RequestType">请求的类型</param> 7 /// <returns></returns> 8 private async Task<string> HandleDataFactoryAsync(Users u, string url, string RequestType) 9 { 10 //声明一个HttpClient类 11 HttpClient client = new HttpClient(); 12 //将Users转化为JSon字符串 13 string jsonString = UsersConvertToJson(u); 14 //声明一个String类型的Context在提交数据时需要用到这个参数 15 var context = new StringContent(jsonString, Encoding.UTF8, "application/json"); 16 //设置反射需要获取的方法名称 17 string method = RequestType + "Async"; 18 19 //我这里将两步写在了一起 20 //1.通过获取所有的方法 21 //2.通过linq语句查询我需要的方法 22 //当然也可以直接GetMethod(MethodName) 23 //我感觉那样的话可能会抛“方法找不到”的异常 24 //我用Linq查询避免了 25 MethodInfo info = client.GetType().GetMethods().FirstOrDefault(m => m.Name == method); 26 if (info != null) 27 { 28 HttpResponseMessage result; 29 30 //由于put和post需要的参数类型和数目一致所以放在一块处理了 31 //get和delete也一样 32 if (method == "PutAsync" || method == "PostAsync") 33 { 34 //激活这个方法并且传递所需要的参数 35 result= await (Task<HttpResponseMessage>)info.Invoke(client, new Object[] { url, context }); 36 } 37 else 38 { 39 result = await (Task<HttpResponseMessage>)info.Invoke(client, new Object[] { url }); 40 } 41 //将响应内容返回 42 return await result.Content.ReadAsStringAsync(); 43 44 } 45 46 return ""; 47 48 }
修改用法
/// <summary> /// 传递数据到远程API的数据库中 /// </summary> /// <param name="u"></param> /// <returns></returns> private async Task<string> CreateAsync(Users u) { string url = baseURL; string requestMethod = "Post"; //return await HandleDataAsync(u, url, requestMethod); return await HandleDataFactoryAsync(u, url, requestMethod); } private async Task<string> UpdateAsync(Users u) { string url = baseURL + @"/" + u.ID; string requestMethod = "Put"; // return await HandleDataAsync(u, url, requestMethod); return await HandleDataFactoryAsync(u, url, requestMethod); } private async Task<string> DeleteAsync(Users u) { string url = baseURL + @"/" + u.ID; string requestMethod = "Delete"; //return await HandleDataAsync(u, url, requestMethod); return await HandleDataFactoryAsync(u, url, requestMethod); }
注释掉的那行是原来调用WebRequest的方法,别的都没有改变。
这是整个类
1 using Microsoft.AspNetCore.Mvc; 2 using Newtonsoft.Json; 3 using Newtonsoft.Json.Linq; 4 using System; 5 using System.Collections.Generic; 6 using System.IO; 7 using System.Linq; 8 using System.Net; 9 using System.Net.Http; 10 using System.Reflection; 11 using System.Text; 12 using System.Threading.Tasks; 13 using TestAPI.Models; 14 15 namespace TestAPI.Controllers 16 { 17 public class UsersController : Controller 18 { 19 #region 成员变量 20 //这个baseURL是我的webApi的地址 21 private static string baseURL = "http://localhost:56853/api/users"; 22 //用于存放所有的用户 23 private static IList<Users> _context; 24 25 #endregion 26 27 #region 构造函数 28 public UsersController() 29 { 30 //实例化对象 31 _context = new List<Users>(); 32 //获取所有的用户的信息 33 _context = GetAllUserList(); 34 35 } 36 37 #endregion 38 39 #region 类内方法 40 41 /// <summary> 42 /// 通过api获取所有的用户的信息 43 /// </summary> 44 /// <returns>JSON String</returns> 45 private string GetALLUserInfoFromAPI() 46 { 47 HttpClient client = new HttpClient(); 48 var con = client.GetStringAsync(baseURL); 49 return con.Result; 50 51 } 52 53 private string UsersConvertToJson(Users u) 54 { 55 return JsonConvert.SerializeObject(u); 56 } 57 /// <summary> 58 /// 传递数据到远程API的数据库中 59 /// </summary> 60 /// <param name="u"></param> 61 /// <returns></returns> 62 private async Task<string> CreateAsync(Users u) 63 { 64 string url = baseURL; 65 string requestMethod = "Post"; 66 //return await HandleDataAsync(u, url, requestMethod); 67 return await HandleDataFactoryAsync(u, url, requestMethod); 68 } 69 70 private async Task<string> UpdateAsync(Users u) 71 { 72 string url = baseURL + @"/" + u.ID; 73 string requestMethod = "Put"; 74 // return await HandleDataAsync(u, url, requestMethod); 75 return await HandleDataFactoryAsync(u, url, requestMethod); 76 } 77 private async Task<string> DeleteAsync(Users u) 78 { 79 string url = baseURL + @"/" + u.ID; 80 string requestMethod = "Delete"; 81 //return await HandleDataAsync(u, url, requestMethod); 82 return await HandleDataFactoryAsync(u, url, requestMethod); 83 84 } 85 private bool UsersExist(int iD) 86 { 87 return _context.Any(u => u.ID == iD); 88 } 89 /// <summary> 90 /// 用WebRequest处理数据 91 /// </summary> 92 /// <param name="Data">User实体类</param> 93 /// <param name="Url">远程API的URL</param> 94 /// <param name="RequestMethod">请求的方法</param> 95 /// <returns></returns> 96 private async Task<string> HandleDataAsync(Users Data, string Url, string RequestMethod) 97 { 98 string UsersJson = UsersConvertToJson(Data); 99 var request = WebRequest.CreateHttp(Url); 100 request.Accept = "application/json"; 101 //下边这行不设置会出现无法识别mediaType 415 这个错误 102 request.ContentType = "application/json"; 103 request.Method = RequestMethod; 104 //向request提交数据 105 using (StreamWriter writer = new StreamWriter(await request.GetRequestStreamAsync())) 106 { 107 writer.Write(UsersJson); 108 } 109 //获取响应 110 var reponse = await request.GetResponseAsync(); 111 //返回响应数据 112 using (StreamReader reader = new StreamReader(reponse.GetResponseStream())) 113 { 114 return reader.ReadToEnd(); 115 } 116 } 117 118 /// <summary> 119 /// 这是用HttpClient调用Web Api实现CRUD到数据库中 120 /// </summary> 121 /// <param name="u">数据</param> 122 /// <param name="url">请求的url</param> 123 /// <param name="RequestType">请求的类型</param> 124 /// <returns></returns> 125 private async Task<string> HandleDataFactoryAsync(Users u, string url, string RequestType) 126 { 127 //声明一个HttpClient类 128 HttpClient client = new HttpClient(); 129 //将Users转化为JSon字符串 130 string jsonString = UsersConvertToJson(u); 131 //声明一个String类型的Context在提交数据时需要用到这个参数 132 var context = new StringContent(jsonString, Encoding.UTF8, "application/json"); 133 //设置反射需要获取的方法名称 134 string method = RequestType + "Async"; 135 136 //我这里将两步写在了一起 137 //1.通过获取所有的方法 138 //2.通过linq语句查询我需要的方法 139 //当然也可以直接GetMethod(MethodName) 140 //我感觉那样的话可能会抛“方法找不到”的异常 141 //我用Linq查询避免了 142 MethodInfo info = client.GetType().GetMethods().FirstOrDefault(m => m.Name == method); 143 if (info != null) 144 { 145 HttpResponseMessage result; 146 147 //由于put和post需要的参数类型和数目一致所以放在一块处理了 148 //get和delete也一样 149 if (method == "PutAsync" || method == "PostAsync") 150 { 151 //激活这个方法并且传递所需要的参数 152 result= await (Task<HttpResponseMessage>)info.Invoke(client, new Object[] { url, context }); 153 } 154 else 155 { 156 result = await (Task<HttpResponseMessage>)info.Invoke(client, new Object[] { url }); 157 } 158 //将响应内容返回 159 return await result.Content.ReadAsStringAsync(); 160 161 } 162 163 return ""; 164 165 } 166 /// <summary> 167 /// 获取所有用户的List 168 /// </summary> 169 private IList<Users> GetAllUserList() 170 { 171 IList<Users> userslist = new List<Users>(); 172 var JsonString = GetALLUserInfoFromAPI(); 173 JArray UsersArray = JArray.Parse(JsonString); 174 for (int i = 0; i < UsersArray.Count; i++) 175 { 176 userslist.Add(StringConvertToUser(UsersArray[i].ToString())); 177 } 178 return userslist; 179 } 180 /// <summary> 181 /// 将Json对象的字符串转化为users对象 182 /// </summary> 183 /// <param name="JsonString">json对象的字符串</param> 184 /// <returns>Users对象</returns> 185 private Users StringConvertToUser(string JsonString) 186 { 187 return JsonConvert.DeserializeObject<Users>(JsonString); 188 } 189 #endregion 190 191 #region Index 192 // GET: Users 193 public async Task<IActionResult> Index() 194 { 195 return View(_context); 196 } 197 198 199 200 #endregion 201 202 #region Details 203 204 // GET: Users/Details/5 205 public async Task<IActionResult> Details(int? id) 206 { 207 if (id == null) 208 { 209 return BadRequest(); 210 } 211 var users = _context.FirstOrDefault(u => u.ID == id); 212 if (users == null) 213 { 214 return NotFound(); 215 } 216 return View(users); 217 } 218 219 #endregion 220 221 #region Create 222 223 // GET: Users/Create 224 public IActionResult Create() 225 { 226 return View(); 227 } 228 229 // POST: Users/Create 230 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 231 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 232 [HttpPost] 233 [ValidateAntiForgeryToken] 234 public async Task<IActionResult> Create([Bind("ID,name,pwd")] Users users) 235 { 236 if (ModelState.IsValid) 237 { 238 239 await CreateAsync(users); 240 return RedirectToAction("Index"); 241 } 242 return View(); 243 } 244 245 #endregion 246 247 #region Edit 248 249 // GET: Users/Edit/5 250 public async Task<IActionResult> Edit(int? id) 251 { 252 if (id == null) 253 { 254 return BadRequest(); 255 } 256 var users = _context.FirstOrDefault(u => u.ID == id); 257 if (users == null) 258 { 259 return NotFound(); 260 } 261 return View(users); 262 } 263 264 // POST: Users/Edit/5 265 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 266 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 267 [HttpPost] 268 [ValidateAntiForgeryToken] 269 public async Task<IActionResult> Edit(int id, [Bind("ID,name,pwd")] Users users) 270 { 271 272 if (ModelState.IsValid) 273 { 274 if (id != users.ID) 275 { 276 return BadRequest(); 277 } 278 try 279 { 280 await UpdateAsync(users); 281 return RedirectToAction("Index"); 282 } 283 catch 284 { 285 if (UsersExist(users.ID)) 286 { 287 return NotFound(); 288 } 289 throw; 290 } 291 292 } 293 return View(); 294 } 295 296 297 #endregion 298 299 #region Delete 300 301 302 // GET: Users/Delete/5 303 public async Task<IActionResult> Delete(int? id) 304 { 305 if (id == null) 306 { 307 return BadRequest(); 308 } 309 var users = _context.FirstOrDefault(u => u.ID == id); 310 if (users == null) 311 { 312 return NotFound(); 313 } 314 315 return View(users); 316 } 317 318 // POST: Users/Delete/5 319 [HttpPost, ActionName("Delete")] 320 [ValidateAntiForgeryToken] 321 public async Task<IActionResult> DeleteConfirmed(int id) 322 { 323 var users = _context.SingleOrDefault(u => u.ID == id); 324 await DeleteAsync(users); 325 return RedirectToAction("Index"); 326 } 327 #endregion 328 329 } 330 }
感觉HttpClient比WebRequest好用一点。毕竟都差不多吧,只不过是是现的方式不一样,用法不一样。又让我体验了一把反射的魅力。
这个是连接Web Api的git地址 https://github.com/1483523635/dotNetCoreAPIDemoTest
这个是用到的Web Api的git地址https://github.com/1483523635/dotNetCoreAPIDemo