在Core环境下用WebRequest连接上远程的web Api 实现数据的简单CRUD(附Git地址)
本文所有的东西都是在dot Net Core 1.1环境+VS2017保证测试通过。
本文接着上次文章接着写的,不了解上篇文章的可能看着有点吃力。我尽量让大家都能看懂。这是上篇文章的连接http://www.cnblogs.com/qulianqing/p/6745409.html。请大家先看一下,心里大致有个了解,然后看这篇博客就容易了。
这里说一下实现的步骤:1. 新建一个ASP dot Net MVC项目,在这里我的项目名为TestAPI
2. 在项目的根目录下添加一个文件夹 名字为Models
3. 在Models文件夹下添加一个Users.cs 类 下面是代码 和上篇博客的Users.cs一样 (主要是为了传输数据方便)
1 public class Users 2 { 3 [Key] 4 public int ID { get; set; } 5 public string name { get; set; } 6 public string pwd { get; set; } 7 }
4.在右键点击controllers文件夹 选择添加-->控制器 在弹出的对话框中选择 mimial Dependencies 之后等待完成。(这里说一下上篇博客有朋友说
选择 mimial Dependencies会出现错误,我今天又试了一遍,还是没有问题,如果说你的也有问题的话那就选择full Dependencies)
mini)
5.再次右键点击Controllers文件夹 选择添加 ->控制器 在弹出的对话框中选择 第三个,也就是下边高亮的那一个 点击添加按钮
6.点击添加按钮之后,又会出现一个对话框,在对话框中选择点击模型的下拉框,选择Uses.cs 。在数据上下文项点击右边的那个加号,在弹出的对话框中,选将名称更改为Users,最后记得视图的三个选项都要勾选。点击添加 就完成了。
7.删除不必要的东西 (1)删除Views下边的整个Home文件夹里边的东西,(2)删除整个Data文件夹,及内部东西,(3)删除Controllers文 件夹下的HomeController.cs (4) 打开appsettings.json文件夹 ,删除ConnectionStrings项及其内容,
(5)打开Startup.cs文件 删除EF框架自动添加的服务 在ConfigureServices这个方法里边, 这个字符串 services.AddDbContext<UsesContext>options=>options.UseSqlServer(Configuration.GetConnectionString("*****")));
(6)打开Contollers文件夹下的UserController.cs文件,删除下边的系统为我们生成的大部分代码,删除完之后就剩下这些
1 public class UsersController : Controller 2 { 3 // GET: Users 4 public async Task<IActionResult> Index() 5 { 6 7 } 8 // GET: Users/Details/5 9 public async Task<IActionResult> Details(int? id) 10 { 11 12 } 13 // GET: Users/Create 14 public IActionResult Create() 15 { 16 17 } 18 // POST: Users/Create 19 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 20 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 21 [HttpPost] 22 [ValidateAntiForgeryToken] 23 public async Task<IActionResult> Create([Bind("ID,name,pwd")] Users users) 24 { 25 26 } 27 // GET: Users/Edit/5 28 public async Task<IActionResult> Edit(int? id) 29 { 30 31 } 32 // POST: Users/Edit/5 33 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 34 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 35 [HttpPost] 36 [ValidateAntiForgeryToken] 37 public async Task<IActionResult> Edit(int id, [Bind("ID,name,pwd")] Users users) 38 { 39 40 } 41 // GET: Users/Delete/5 42 public async Task<IActionResult> Delete(int? id) 43 { 44 45 } 46 47 // POST: Users/Delete/5 48 [HttpPost, ActionName("Delete")] 49 [ValidateAntiForgeryToken] 50 public async Task<IActionResult> DeleteConfirmed(int id) 51 { 52 53 } 54 55 }
进行到这里我们的基础环境就搭建完毕了,我们这里只用系统为我们生成的View 其他的都不用要,在这里我们的Views文件夹下的Users文件夹的东西我们没有动
二、接下来重点来了
我们要在Controllers调用我们上次写的WebAPI
首先我们依次从index到Create到Update 到Delete依次为大家详解(最后附完整的代码,如果代码阅读能力强的同学,可以直接跳到最后阅读全部的代码)
准备工作,首先我们声明两个全局变量,具体用途在注释中已经说明
1 //这个baseURL是我的webApi的地址 2 private static string baseURL = "http://localhost:56853/api/users"; 3 //用于存放所有的用户 4 private static IList<Users> _context;
构造函数 获取所有的用户信息就是把数据存在 _context 中 方便查找
1 public UsersController() 2 { 3 //实例化对象 4 _context = new List<Users>(); 5 //获取所有的用户的信息 6 _context = GetAllUserList(); 7 8 }
在这里我取数据的使用用的是HttpClient取的远程的API数据,由于取的是JSon字符串数组,我要把它转化为JSon数组,然后再通过JSonConvert进行每一个对象的转化
1 /// <summary> 2 /// 获取所有用户的List 3 /// </summary> 4 private IList<Users> GetAllUserList() 5 { 6 IList<Users> userslist = new List<Users>(); 7 var JsonString = GetALLUserInfoFromAPI(); 8 JArray UsersArray = JArray.Parse(JsonString); 9 for (int i = 0; i < UsersArray.Count; i++) 10 { 11 userslist.Add(StringConvertToUser(UsersArray[i].ToString())); 12 } 13 return userslist; 14 }
1 /// <summary> 2 /// 通过api获取所有的用户的信息 3 /// </summary> 4 /// <returns>JSON String</returns> 5 private string GetALLUserInfoFromAPI() 6 { 7 HttpClient client = new HttpClient(); 8 var con = client.GetStringAsync(baseURL); 9 return con.Result; 10 }
1 /// <summary> 2 /// 将Json对象的字符串转化为users对象 3 /// </summary> 4 /// <param name="JsonString">json对象的字符串</param> 5 /// <returns>Users对象</returns> 6 private Users StringConvertToUser(string JsonString) 7 { 8 return JsonConvert.DeserializeObject<Users>(JsonString); 9 }
1.index 界面是用来显示数据的。通过上边的操作,我们已经把所有的数据存到 _context 变量中去了,所以在Index中我们只需要调用就可以了。
1 public async Task<IActionResult> Index() 2 { 3 return View(_context); 4 }
运行结果:
2.接下来我们接着说Create和Rdit和Delete 由于Create和Edit都是向服务器提交数据的,Delete向远程API路由一个ID就结束了。这里我原本准备全文都用HttpClient的可是HttpClient的PostAsync方法实在是不会用,昨天搞了一天都没有结果,于是下边的我换成了WebRequest,我把他们提取到一个方法里了,具体看下边的代码。尤其是我下边注释的行代码,不然浏览器会报415让你摸不着头脑,这个是我自己试出来的,可能会有更好的方法吧。只是我还不知道。
1 /// <summary> 2 /// 处理数据 3 /// </summary> 4 /// <param name="Data">User实体类</param> 5 /// <param name="Url">远程API的URL</param> 6 /// <param name="RequestMethod">请求的方法</param> 7 /// <returns></returns> 8 private async Task<string> HandleData(Users Data, string Url, string RequestMethod) 9 { 10 string UsersJson = UsersConvertToJson(Data); 11 var request = WebRequest.CreateHttp(Url); 12 request.Accept = "application/json"; 13 //下边这行不设置会出现无法识别mediaType 415 这个错误 14 request.ContentType = "application/json"; 15 request.Method = RequestMethod; 16 //向request提交数据 17 using (StreamWriter writer = new StreamWriter(await request.GetRequestStreamAsync())) 18 { 19 writer.Write(UsersJson); 20 } 21 //获取响应 22 var reponse = await request.GetResponseAsync(); 23 //返回响应数据 24 using (StreamReader reader = new StreamReader(reponse.GetResponseStream())) 25 { 26 return reader.ReadToEnd(); 27 } 28 }
1 private string UsersConvertToJson(Users u) 2 { 3 return JsonConvert.SerializeObject(u); 4 }
具体用法 Create
1 /// <summary> 2 /// 传递数据到远程API的数据库中 3 /// </summary> 4 /// <param name="u"></param> 5 /// <returns></returns> 6 private async Task<string> CreateAsync(Users u) 7 { 8 string url = baseURL; 9 string requestMethod = "post"; 10 return await HandleData(u, url, requestMethod); 11 } 12 13 14 15 // GET: Users/Create 16 public IActionResult Create() 17 { 18 return View(); 19 } 20 21 // POST: Users/Create 22 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 23 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 24 [HttpPost] 25 [ValidateAntiForgeryToken] 26 public async Task<IActionResult> Create([Bind("ID,name,pwd")] Users users) 27 { 28 if (ModelState.IsValid) 29 { 30 31 await CreateAsync(users); 32 return RedirectToAction("Index"); 33 } 34 return View(); 35 }
具体用法 Edit
1 private async Task<string> UpdateAsync(Users u) 2 { 3 string url = baseURL + @"/" + u.ID; 4 string requestMethod = "put"; 5 return await HandleData(u, url, requestMethod); 6 } 7 8 9 10 // GET: Users/Edit/5 11 public async Task<IActionResult> Edit(int? id) 12 { 13 if (id == null) 14 { 15 return BadRequest(); 16 } 17 var users = _context.FirstOrDefault(u => u.ID == id); 18 if (users == null) 19 { 20 return NotFound(); 21 } 22 return View(users); 23 } 24 25 // POST: Users/Edit/5 26 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 27 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 28 [HttpPost] 29 [ValidateAntiForgeryToken] 30 public async Task<IActionResult> Edit(int id, [Bind("ID,name,pwd")] Users users) 31 { 32 33 if (ModelState.IsValid) 34 { 35 if (id != users.ID) 36 { 37 return BadRequest(); 38 } 39 try 40 { 41 await UpdateAsync(users); 42 return RedirectToAction("Index"); 43 } 44 catch 45 { 46 if (UsersExist(users.ID)) 47 { 48 return NotFound(); 49 } 50 throw; 51 } 52 53 } 54 return View(); 55 }
1 private bool UsersExist(int iD) 2 { 3 return _context.Any(u => u.ID == iD); 4 }
具体用法 Delete
1 private async Task<string> DeleteAsync(Users u) 2 { 3 string url = baseURL + @"/" + u.ID; 4 string requestMethod = "delete"; 5 return await HandleData(u, url, requestMethod); 6 } 7 8 9 10 // GET: Users/Delete/5 11 public async Task<IActionResult> Delete(int? id) 12 { 13 if (id == null) 14 { 15 return BadRequest(); 16 } 17 var users = _context.FirstOrDefault(u => u.ID == id); 18 if (users == null) 19 { 20 return NotFound(); 21 } 22 23 return View(users); 24 } 25 26 // POST: Users/Delete/5 27 [HttpPost, ActionName("Delete")] 28 [ValidateAntiForgeryToken] 29 public async Task<IActionResult> DeleteConfirmed(int id) 30 { 31 var users = _context.SingleOrDefault(u => u.ID == id); 32 await DeleteAsync(users); 33 return RedirectToAction("Index"); 34 }
到这里调用远程API的东西都完成了,我在这里完善了一下 Details这个View
1 // GET: Users/Details/5 2 public async Task<IActionResult> Details(int? id) 3 { 4 if (id == null) 5 { 6 return BadRequest(); 7 } 8 var users = _context.FirstOrDefault(u => u.ID == id); 9 if (users == null) 10 { 11 return NotFound(); 12 } 13 return View(users); 14 }
下边这是测试结果
到这里全部都完成了,并且测试完毕
这是UsersContellers.cs 类的全部代码
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.Net.Http.Headers; 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 42 /// https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client 43 44 45 46 /// <summary> 47 /// 通过api获取所有的用户的信息 48 /// </summary> 49 /// <returns>JSON String</returns> 50 private string GetALLUserInfoFromAPI() 51 { 52 HttpClient client = new HttpClient(); 53 var con = client.GetStringAsync(baseURL); 54 return con.Result; 55 } 56 57 private string UsersConvertToJson(Users u) 58 { 59 return JsonConvert.SerializeObject(u); 60 } 61 /// <summary> 62 /// 传递数据到远程API的数据库中 63 /// </summary> 64 /// <param name="u"></param> 65 /// <returns></returns> 66 private async Task<string> CreateAsync(Users u) 67 { 68 string url = baseURL; 69 string requestMethod = "post"; 70 return await HandleData(u, url, requestMethod); 71 } 72 73 private async Task<string> UpdateAsync(Users u) 74 { 75 string url = baseURL + @"/" + u.ID; 76 string requestMethod = "put"; 77 return await HandleData(u, url, requestMethod); 78 } 79 /// <summary> 80 /// 处理数据 81 /// </summary> 82 /// <param name="Data">User实体类</param> 83 /// <param name="Url">远程API的URL</param> 84 /// <param name="RequestMethod">请求的方法</param> 85 /// <returns></returns> 86 private async Task<string> HandleData(Users Data, string Url, string RequestMethod) 87 { 88 string UsersJson = UsersConvertToJson(Data); 89 var request = WebRequest.CreateHttp(Url); 90 request.Accept = "application/json"; 91 //下边这行不设置会出现无法识别mediaType 415 这个错误 92 request.ContentType = "application/json"; 93 request.Method = RequestMethod; 94 //向request提交数据 95 using (StreamWriter writer = new StreamWriter(await request.GetRequestStreamAsync())) 96 { 97 writer.Write(UsersJson); 98 } 99 //获取响应 100 var reponse = await request.GetResponseAsync(); 101 //返回响应数据 102 using (StreamReader reader = new StreamReader(reponse.GetResponseStream())) 103 { 104 return reader.ReadToEnd(); 105 } 106 } 107 private async Task<string> DeleteAsync(Users u) 108 { 109 string url = baseURL + @"/" + u.ID; 110 string requestMethod = "delete"; 111 return await HandleData(u, url, requestMethod); 112 } 113 private bool UsersExist(int iD) 114 { 115 return _context.Any(u => u.ID == iD); 116 } 117 118 /// <summary> 119 /// 获取所有用户的List 120 /// </summary> 121 private IList<Users> GetAllUserList() 122 { 123 IList<Users> userslist = new List<Users>(); 124 var JsonString = GetALLUserInfoFromAPI(); 125 JArray UsersArray = JArray.Parse(JsonString); 126 for (int i = 0; i < UsersArray.Count; i++) 127 { 128 userslist.Add(StringConvertToUser(UsersArray[i].ToString())); 129 } 130 return userslist; 131 } 132 /// <summary> 133 /// 将Json对象的字符串转化为users对象 134 /// </summary> 135 /// <param name="JsonString">json对象的字符串</param> 136 /// <returns>Users对象</returns> 137 private Users StringConvertToUser(string JsonString) 138 { 139 return JsonConvert.DeserializeObject<Users>(JsonString); 140 } 141 #endregion 142 143 #region Index 144 // GET: Users 145 public async Task<IActionResult> Index() 146 { 147 return View(_context); 148 } 149 150 151 152 #endregion 153 154 #region Details 155 156 // GET: Users/Details/5 157 public async Task<IActionResult> Details(int? id) 158 { 159 if (id == null) 160 { 161 return BadRequest(); 162 } 163 var users = _context.FirstOrDefault(u => u.ID == id); 164 if (users == null) 165 { 166 return NotFound(); 167 } 168 return View(users); 169 } 170 171 #endregion 172 173 #region Create 174 175 // GET: Users/Create 176 public IActionResult Create() 177 { 178 return View(); 179 } 180 181 // POST: Users/Create 182 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 183 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 184 [HttpPost] 185 [ValidateAntiForgeryToken] 186 public async Task<IActionResult> Create([Bind("ID,name,pwd")] Users users) 187 { 188 if (ModelState.IsValid) 189 { 190 191 await CreateAsync(users); 192 return RedirectToAction("Index"); 193 } 194 return View(); 195 } 196 197 #endregion 198 199 #region Edit 200 201 // GET: Users/Edit/5 202 public async Task<IActionResult> Edit(int? id) 203 { 204 if (id == null) 205 { 206 return BadRequest(); 207 } 208 var users = _context.FirstOrDefault(u => u.ID == id); 209 if (users == null) 210 { 211 return NotFound(); 212 } 213 return View(users); 214 } 215 216 // POST: Users/Edit/5 217 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 218 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 219 [HttpPost] 220 [ValidateAntiForgeryToken] 221 public async Task<IActionResult> Edit(int id, [Bind("ID,name,pwd")] Users users) 222 { 223 224 if (ModelState.IsValid) 225 { 226 if (id != users.ID) 227 { 228 return BadRequest(); 229 } 230 try 231 { 232 await UpdateAsync(users); 233 return RedirectToAction("Index"); 234 } 235 catch 236 { 237 if (UsersExist(users.ID)) 238 { 239 return NotFound(); 240 } 241 throw; 242 } 243 244 } 245 return View(); 246 } 247 248 249 #endregion 250 251 #region Delete 252 253 254 // GET: Users/Delete/5 255 public async Task<IActionResult> Delete(int? id) 256 { 257 if (id == null) 258 { 259 return BadRequest(); 260 } 261 var users = _context.FirstOrDefault(u => u.ID == id); 262 if (users == null) 263 { 264 return NotFound(); 265 } 266 267 return View(users); 268 } 269 270 // POST: Users/Delete/5 271 [HttpPost, ActionName("Delete")] 272 [ValidateAntiForgeryToken] 273 public async Task<IActionResult> DeleteConfirmed(int id) 274 { 275 var users = _context.SingleOrDefault(u => u.ID == id); 276 await DeleteAsync(users); 277 return RedirectToAction("Index"); 278 } 279 #endregion 280 281 } 282 }
这是git地址 https://github.com/1483523635/dotNetCoreAPIDemoTest
关于HttpClient的学习微软官网上有一篇 https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client 这个我看了一下时间是2014年的,昨天还能看今天就看不到了,可能是要更新吧
这是HttpClient的API说明 https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.118).aspx
关于HttpClient的PostAsync方法谁有好的用法,欢迎告诉我,让我学习一下。