原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端

chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解。

文章:
http://chsakell.com/2015/01/31/angularjs-feat-web-api/
http://chsakell.com/2015/03/07/angularjs-feat-web-api-enable-session-state/

源码:
https://github.com/chsakell/webapiangularjssecurity

本系列共三篇,本篇是第一篇。

购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端
购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session
购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证

■ 配置EF

首先搞清模型之间的关系:

  1. public class Gadget
  2. {
  3. public int GadgetID{get;set;}
  4. ...
  5.  
  6. public int CategoryID{get;set;}
  7. public Category Category{get;set;}
  8. }
  9.  
  10. public class Category
  11. {
  12. public int CategoryID{get;set;}
  13. ...
  14. public List<Gadget> Gadgets{get;set;}
  15. }
  16.  
  17. public class Order
  18. {
  19. public int OrderID{get;set;}
  20. ...
  21. public List<Gadget> Gadgets{get;set;}
  22. }
  23.  
  24. public class GadgetOrder
  25. {
  26. public int GadgetOrderID{get;set;}
  27.  
  28. public int OrderID{get;set;}
  29. public Order Order{get;set;}
  30.  
  31. public int GadgetID{get;set;}
  32. public Gadget Gadget{get;set;}
  33. }

以上,Category和Gadget是1对多的关系,GadgetOrder是Order和Gadget的中间表。

接着需要通过EF Fluent API来配置领域,需要实现EntityTypeConfiguration<TModel>这个基类。比如:

  1. public class OrderConfiguration : EntityTypeConfiguration<Order>
  2. {
  3. public OrderConfiguration()
  4. {
  5. Ignore(o => o.Gadgets);
  6. }
  7. }

然后就配置上下文,继承DbContext这个基类。

  1. public class StoreContext : DbContext
  2. {
  3. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  4. {
  5. ...
  6. modelBuilder.Configurations.Add(new OrderConfiguration());
  7. }
  8.  
  9. public DbSet<Order> Orders{get;set;}
  10. ...
  11. }

我们还希望在生成数据库的时候生成一些种子数据,需要继承DropCreateDatabaseIfModelChanges<TContext>这个泛型类。

  1. public class StoreInitializer : DropCreateDatabaseIfModelChanges<StoreContext>
  2. {
  3. protected override void Seed(StoreContext context)
  4. {
  5. try
  6. {
  7. GetCategoreis().ForEach(c => context.Categories.Add(c));
  8. ...
  9. }
  10. catch(Exception ex)
  11. {
  12. Debug.WriteLine(ex.Message);
  13. }
  14. }
  15.  
  16. private static List<Category> GetCategories()
  17. {
  18. ...
  19. }
  20. }

如何调用数据库种子数据的类StoreInitializer呢?有一种方法使在项目全局文件中配置。(还有一种方法使在DbContext的构造函数中配置,还有一种在数据库迁移文件中配置,etc.)

  1. void Application_Start(object sender, EventArgs e)
  2. {
  3. Database.SetInitializer(new StoreIntializer());
  4. }

最后,关于EF的配置部分,需要在Web.config中配置,大致如下:

  1. <connectionStrings>
  2. <add name="ProductServiceContext" connectionString="Data Source=.;User=someusername;Password=somepassword;Initial Catalog=MyProductService;Integrated Security=True" providerName="System.Data.SqlClient"/>
  3. </connectionStrings>

■ CategoriesController

先俯瞰。

  1. public class CategoriesController : ApiController
  2. {
  3. private StoreContext db = new SotoreContext();
  4.  
  5. ...
  6.  
  7. private bool CategoryExists(int id)
  8. {
  9. return db.Categories.Count(g => g.CategoryID=id) > ;
  10. }
  11.  
  12. protected override void Dispose(boo disposing)
  13. {
  14. if(disposing)
  15. {
  16. db.Dispose();
  17. }
  18. base.Dispose(disposing);
  19. }
  20. }

再细节。

  1. /GET api/Categories
  2. public IQueryable<Category> GetCategories()
  3. {
  4. return db.Categories;
  5. }
  6.  
  7. //GET api/Categories/5
  8. [ResponseType(typeof(Category))]
  9. public async Task<IHttpActionResult> GetCategory(int id)
  10. {
  11. Category category = await db.Categories.FindAsync(id);
  12. if(category == null)
  13. {
  14. return NotFound();
  15. }
  16. return Ok(category);
  17. }
  18.  
  19. //put api/Categories/5
  20. [ResponseType(typeof(void))]
  21. public async Task<IHttpActionResult> PutCategory(int id, Category category)
  22. {
  23. if(!ModelState.IsValid)
  24. {
  25. return BadRequest(ModelState);
  26. }
  27.  
  28. if(id != category.CategoryID)
  29. {
  30. return BadRequest();
  31. }
  32.  
  33. db.Entry(category).State = EntityState.Modified;
  34.  
  35. try
  36. {
  37. await db.SavheChangesAsync();
  38. }
  39. catch(DbUpdateConcurrencyException)
  40. {
  41. if(!CategoryExists(id))
  42. {
  43. return NotFound();
  44. }
  45. else
  46. {
  47. throw;
  48. }
  49. }
  50. return StatusCode(HttpStatusCOde.NoContet);
  51. }
  52.  
  53. //post api/Categories
  54. [ResponseType(typeof(Category))]
  55. public async Task<IHttpActionResult> PostCategory(Category category)
  56. {
  57. if(!ModelState.IsValid)
  58. {
  59. return BadRequest(ModelState);
  60. }
  61.  
  62. db.Categories.Add(category);
  63. await db.SaveChangesAsync();
  64.  
  65. //返回到指定的路由
  66. return CreatedAtRoute("DefaultApi", new {id = category.CategoryID}, category);
  67. }
  68.  
  69. //delete api/Categoreis/5
  70. [ResponseType(typeof(Category))]
  71. public async Task<IHttpActionResult> DeleteCategory(int id)
  72. {
  73. Category category = await db.Categories.FindAsync(id);
  74. if(category == null)
  75. {
  76. return NotFound();
  77. }
  78.  
  79. db.Categories.Remove(category);
  80. await db.SaveChangesAsync();
  81. return Ok(category);
  82. }

■ GadgetsController

先俯瞰。

  1. public class GadgetsController : ApiController
  2. {
  3. private StoreContext db = new StoreContext();
  4.  
  5. protected override void Dispose(bool disposing)
  6. {
  7. if(disposing)
  8. {
  9. db.Dispose();
  10. }
  11.  
  12. base.Dispose(disposing);
  13. }
  14.  
  15. private bool GadgetExists(int id)
  16. {
  17. return db.Gadgets.Count(g => g.GadgetID == ID) > ;
  18. }
  19. }

再细节。

  1. //get api/Gadgets
  2. public IQueryable<Gadget> GetGadgets()
  3. {
  4. return db.Gadgets;
  5. }
  6.  
  7. //get api/Gadgets/5
  8. [ResponseType(typeof(Gadgets))]
  9. public async Task<IHttpActionResult> GetGadget(int id)
  10. {
  11. Gadget gadget = await db.Gadgets.FindAsync(id);
  12. if(gadget == null)
  13. {
  14. return NotFound();
  15. }
  16. return Ok(gadget);
  17. }
  18.  
  19. //put api/Gadgets/5
  20. [ResponseType(typeof(void))]
  21. public async Task<IHttpActionResult> PutGadget(int id, Gadget gadget)
  22. {
  23. if(!ModelState.IsValid)
  24. {
  25. return BadRequest(ModelState);
  26. }
  27.  
  28. if(d != gadget.GadgetID)
  29. {
  30. return BadRequest();
  31. }
  32.  
  33. db.Entry(gadget).State = EntityState.Modified;
  34.  
  35. try
  36. {
  37. await db.SaveChangesAsync();
  38. }
  39. catch(DbUpdateConcurrencyException)
  40. {
  41. if(!GadgetExists(id))
  42. {
  43. return NotFound();
  44. }
  45. else
  46. {
  47. throw;
  48. }
  49. }
  50. }
  51.  
  52. //post api/Gadgets
  53. [ResposneType(typeof(Gadget))]
  54. public async Task<IHttpActionResult> PostGadget(Gadget gadget)
  55. {
  56. if(!ModelState.IsValid)
  57. {
  58. return BadRequest(ModelState);
  59. }
  60. db.Gadgets.Add(gadget);
  61. await db.SaveChangesAsync();
  62.  
  63. return CreatedAtRoute("DefaultApi", new {id=gadget.GadgetID}, gadget)
  64. }
  65.  
  66. //delete api/Gadgets/5
  67. [ResponseType(typeof(Gadget))]
  68. public async Task<IHttpActionResult> DeleteGadget(int id)
  69. {
  70. Gadget gadget = await db.Gadgets.FindAsync(id);
  71. if(gadget == null)
  72. {
  73. return NotFound();
  74. }
  75. db.Gadgets.Remove(gadget);
  76. await db.SaveChangesAsync();
  77. return Ok(gadget);
  78. }

■ OrdersController

firstly overview.

  1. public class OrdersController : ApiController
  2. {
  3. private StoreContext db = new StoreContext();
  4.  
  5. protected override void Dispose(bool dispoing)
  6. {
  7. if(disposing)
  8. {
  9. db.Dispose();
  10. }
  11. base.Dispose(disposing);
  12. }
  13.  
  14. private bool OrderExists(int id)
  15. {
  16. return db.Orders.Count(g => g.OrderID == id) > ;
  17. }
  18. }

then details.

  1. // get api/Orders
  2. public IQueryable<Order> GetOrders()
  3. {
  4. return db.Orders;
  5. }
  6.  
  7. //get api/Orders/5
  8. [ResponseType(typeof(Order))]
  9. public async Task<IHttpActionResult> GetOrder(int id)
  10. {
  11. Order order = await db.Orders.FindAsync(id);
  12. if(order == null)
  13. {
  14. return NotFound();
  15. }
  16. return Ok(order);
  17. }
  18.  
  19. //put api/Orders/5
  20. [ResponseType(typeof(void))]
  21. public async Task<IHttpActionResult> PutOrder(int id, Order order)
  22. {
  23. if(!ModelState.IsValid)
  24. {
  25. return BadRequest(ModelState);
  26. }
  27.  
  28. if(id != order.OrderID)
  29. {
  30. return BadRequest();
  31. }
  32.  
  33. db.Entry(order).State = EntityState.Modified;
  34.  
  35. try
  36. {
  37. await db.SaveChangesAsync();
  38. }
  39. catch(DbUpdateConcurrecyException)
  40. {
  41. if(!OrderExists(id))
  42. {
  43. return NotFound();
  44. }
  45. else
  46. {
  47. throw;
  48. }
  49. }
  50. return StatusCode(HttpStatusCOde.NoContet);
  51. }
  52.  
  53. //post api/Orders
  54. [RequestType(typeof(Order))]
  55. public async Task<IHttpActionResult> PostOrder(Order order)
  56. {
  57. if(!ModelState.IsValid)
  58. {
  59. reuturn BadRequest(ModelState);
  60. }
  61. try
  62. {
  63. db.Orders.Add(order);
  64. foreach(Gadget gadget in order.Gadgets)
  65. {
  66. db.GadgetOrders.Add(new GadgetOrder{
  67. OrderID = order.OrderID,
  68. GadgetID = gadget.GadgetID
  69. })
  70. }
  71.  
  72. await db.SaveChangesAsync();
  73. }
  74. catch(Exception ex)
  75. {
  76. return BadRequest(ex.Message);
  77. }
  78. return CreatedAtRoutne("Default", new {controller = "Home", action="viewOrder", id = order.orderID}, order);
  79. }
  80.  
  81. //delete api/Orders/5
  82. [ResponseType(typeof(Order))]
  83. public async Task<IHttpActionResult> DeleteOrder(int id)
  84. {
  85. Order order = await db.Orders.FindAsync(id);
  86. if(order == null)
  87. {
  88. return NotFound();
  89. }
  90.  
  91. db.Orders.Remoe(order);
  92. await db.SaveChangesAsync();
  93. return Ok(order);
  94. }

待续~~

购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端的更多相关文章

  1. 购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证 chsakell分享了前端使用AngularJS,后端使用ASP. ...

  2. 购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session chsakell分享了前端使用AngularJS,后端使用ASP.NE ...

  3. 对一个前端AngularJS,后端OData,ASP.NET Web API案例的理解

    依然chsakell,他写了一篇前端AngularJS,后端OData,ASP.NET Web API的Demo,关于OData在ASP.NET Web API中的正删改查没有什么特别之处,但在前端调 ...

  4. 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(4)

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

  5. 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(3)

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

  6. 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(2)

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

  7. 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(1)

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

  8. 前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查

    AngularJS中的$resource服务相比$http服务更适合与RESTful服务进行交互.本篇后端使用ASP.NET Web API, 前端使用$resource,实现增删改查. 本系列包括: ...

  9. ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app

    转载:http://bitoftech.net/2014/08/11/asp-net-web-api-2-external-logins-social-logins-facebook-google-a ...

随机推荐

  1. 小qyvlik 先看两个视频,和 QtQuick UI 问答

    http://edu.csdn.net/course/detail/1042 http://edu.csdn.net/course/detail/335 http://blog.csdn.net/qy ...

  2. 哪些产品不用开发原生APP,微信公众号就够了?

    最近一阶段H5技术被推到高峰,很多人认为借助H5就能利用微信公众号取代APP原生应用了,而事实是怎么样的?这里我从产品层做一个客观分析. 一,原生APP总体趋势 要谈APP是否会被微信取代,那么必须回 ...

  3. 【转】Android API 中文(14) —— ViewStub

    用一个XML源填充view.inflate(上下文对象,资源文件Id,父窗口组一般为null): 原文网址:http://www.cnblogs.com/over140/archive/2010/10 ...

  4. ZOJ3765---Lights (Splay伸展树)

    Lights Time Limit: 8 Seconds      Memory Limit: 131072 KB Now you have N lights in a line. Don't wor ...

  5. 【译】Javascript中的数据类型

    这篇文章通过四种方式获取Javascript中的数据类型:通过隐藏的内置[[Class]]属性:通过typeof运算符:通过instanceof运算符:通过函数Array.isArray().我们也会 ...

  6. POJ 3378

    题目链接 查找长度为5的上升序列总数 用的树状数组+高精度 用树状数组求在i前面比i小的数有几个 用的4个树状数组,A[i][j]表示长度为i的以j为结尾的个数,A[i][j]=A[i-1][1... ...

  7. python批量下载

    # -*- coding: utf-8 -*-__author__ = 'Administrator'from PyQt4.Qt import *from PyQt4.QtCore import *f ...

  8. 一个js编写全选、弹出对话框、ajax-json的案例

    js功能有:全选.弹出对话框.使用json传输ajax数据:不想在写多余的文字了,直接上代码: <%@ page language="java" contentType=&q ...

  9. Timus 1796. Amusement Park 聪明题

    On a sunny Sunday, a group of children headed by their teacher came to an amusement park. Aunt Frosy ...

  10. JMeter分布式性能测试

    利用JMeter进行负载测试的时候,使用单台机器模拟测试超过1000个行程的并发就有些力不从心,在执行的过程中,JMeter自身会自动关闭,要解决这个问题,可以使用分布式测试,运行多台机器运行所谓的  ...