• 购物车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

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

    public class Gadget
    {
        public int GadgetID{get;set;}
        ...
        
        public int CategoryID{get;set;}
        public Category Category{get;set;}
    }
    
    public class Category
    {
        public int CategoryID{get;set;}
        ...
        public List<Gadget> Gadgets{get;set;}
    }
    
    
    public class Order
    {
        public int OrderID{get;set;}
        ...
        public List<Gadget> Gadgets{get;set;}
    }
    
    public class GadgetOrder
    {
        public int GadgetOrderID{get;set;}
        
        public int OrderID{get;set;}
        public Order Order{get;set;}
        
        public int GadgetID{get;set;}
        public Gadget Gadget{get;set;}
    }

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

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

    public class OrderConfiguration : EntityTypeConfiguration<Order>
    {
        public OrderConfiguration()
        {
            Ignore(o => o.Gadgets);
        }
    }

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

    public class StoreContext : DbContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            ...
            modelBuilder.Configurations.Add(new OrderConfiguration());
        }
        
        public DbSet<Order> Orders{get;set;}
        ...
    }

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

    public class StoreInitializer : DropCreateDatabaseIfModelChanges<StoreContext>
    {
        protected override void Seed(StoreContext context)
        {
            try
            {
                GetCategoreis().ForEach(c => context.Categories.Add(c));
                ...
            }
            catch(Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        
        private static List<Category> GetCategories()
        {
            ...
        }
    }

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

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

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

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

    ■ CategoriesController

    先俯瞰。

    public class CategoriesController : ApiController
    {
        private StoreContext db = new SotoreContext();
        
        ...
        
        private bool CategoryExists(int id)
        {
            return db.Categories.Count(g => g.CategoryID=id) > 0;
        }
        
        protected override void Dispose(boo disposing)
        {
            if(disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }

    再细节。

    /GET api/Categories
    public IQueryable<Category> GetCategories()
    {
        return db.Categories;
    }
    
    //GET api/Categories/5
    [ResponseType(typeof(Category))]
    public async Task<IHttpActionResult> GetCategory(int id)
    {
        Category category = await db.Categories.FindAsync(id);
        if(category == null)
        {
            return NotFound();
        }
        return Ok(category);
    }
    
    //put api/Categories/5
    [ResponseType(typeof(void))]
    public async Task<IHttpActionResult> PutCategory(int id, Category category)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        
        if(id != category.CategoryID)
        {
            return BadRequest();
        }
        
        db.Entry(category).State = EntityState.Modified;
        
        try
        {
            await db.SavheChangesAsync();
        }
        catch(DbUpdateConcurrencyException)
        {
            if(!CategoryExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return StatusCode(HttpStatusCOde.NoContet);
    }
    
    //post api/Categories
    [ResponseType(typeof(Category))]
    public async Task<IHttpActionResult> PostCategory(Category category)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        
        db.Categories.Add(category);
        await db.SaveChangesAsync();
        
        //返回到指定的路由
        return CreatedAtRoute("DefaultApi", new {id = category.CategoryID}, category);
    }
    
    //delete api/Categoreis/5
    [ResponseType(typeof(Category))]
    public async Task<IHttpActionResult> DeleteCategory(int id)
    {
        Category category = await db.Categories.FindAsync(id);
        if(category == null)
        {
            return NotFound();
        }
        
        db.Categories.Remove(category);
        await db.SaveChangesAsync();
        return Ok(category);
    }

    ■ GadgetsController

    先俯瞰。

    public class GadgetsController : ApiController
    {
        private StoreContext db = new StoreContext();
        
        protected override void Dispose(bool disposing)
        {
            if(disposing)
            {
                db.Dispose();
            }
            
            base.Dispose(disposing);
        }
        
        private bool GadgetExists(int id)
        {
            return db.Gadgets.Count(g => g.GadgetID == ID) > 0;
        }
    }

    再细节。

    //get api/Gadgets
    public IQueryable<Gadget> GetGadgets()
    {
        return db.Gadgets;
    }
    
    //get api/Gadgets/5
    [ResponseType(typeof(Gadgets))]
    public async Task<IHttpActionResult> GetGadget(int id)
    {
        Gadget gadget = await db.Gadgets.FindAsync(id);
        if(gadget == null)
        {
            return NotFound();
        }
        return Ok(gadget);
    }
    
    //put api/Gadgets/5
    [ResponseType(typeof(void))]
    public async Task<IHttpActionResult> PutGadget(int id, Gadget gadget)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        
        if(d != gadget.GadgetID)
        {
            return BadRequest();
        }
        
        db.Entry(gadget).State = EntityState.Modified;
        
        try
        {
            await db.SaveChangesAsync();
        }
        catch(DbUpdateConcurrencyException)
        {
            if(!GadgetExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
    }
    
    //post api/Gadgets
    [ResposneType(typeof(Gadget))]
    public async Task<IHttpActionResult> PostGadget(Gadget gadget)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        db.Gadgets.Add(gadget);
        await db.SaveChangesAsync();
        
        return CreatedAtRoute("DefaultApi", new {id=gadget.GadgetID}, gadget)
    }
    
    //delete api/Gadgets/5
    [ResponseType(typeof(Gadget))]
    public async Task<IHttpActionResult> DeleteGadget(int id)
    {
        Gadget gadget = await db.Gadgets.FindAsync(id);
        if(gadget == null)
        {   
              return NotFound();
        }
        db.Gadgets.Remove(gadget);
        await db.SaveChangesAsync();
        return Ok(gadget);
    }

    ■ OrdersController

    firstly overview.

    public class OrdersController : ApiController
    {
        private StoreContext db = new StoreContext();
        
        protected override void Dispose(bool dispoing)
        {
            if(disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
        
        private bool OrderExists(int id)
        {
            return db.Orders.Count(g => g.OrderID == id) > 0;
        }
    }

    then details.

    // get api/Orders
    public IQueryable<Order> GetOrders()
    {
        return db.Orders;
    }
    
    //get api/Orders/5
    [ResponseType(typeof(Order))]
    public async Task<IHttpActionResult> GetOrder(int id)
    {
        Order order = await db.Orders.FindAsync(id);
        if(order == null)
        {
            return NotFound();
        }
        return Ok(order);
    }
    
    //put api/Orders/5
    [ResponseType(typeof(void))]
    public async Task<IHttpActionResult> PutOrder(int id, Order order)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        
        if(id != order.OrderID)
        {
            return BadRequest();
        }
        
        db.Entry(order).State = EntityState.Modified;
        
        try
        {
            await db.SaveChangesAsync();
        }
        catch(DbUpdateConcurrecyException)
        {
            if(!OrderExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return StatusCode(HttpStatusCOde.NoContet);
    }
    
    //post api/Orders
    [RequestType(typeof(Order))]
    public async Task<IHttpActionResult> PostOrder(Order order)
    {
        if(!ModelState.IsValid)
        {
            reuturn BadRequest(ModelState);
        }
        try
        {
            db.Orders.Add(order);
            foreach(Gadget gadget in order.Gadgets)
            {
                db.GadgetOrders.Add(new GadgetOrder{
                    OrderID = order.OrderID,
                    GadgetID = gadget.GadgetID
                })
            }
            
            await db.SaveChangesAsync();
        }
        catch(Exception ex)
        {
            return BadRequest(ex.Message);
        }
        return CreatedAtRoutne("Default", new {controller = "Home", action="viewOrder", id = order.orderID}, order);
    }
    
    
    //delete api/Orders/5
    [ResponseType(typeof(Order))]
    public async Task<IHttpActionResult> DeleteOrder(int id)
    {
        Order order = await db.Orders.FindAsync(id);
        if(order == null)
        {
            return NotFound();
        }
        
        db.Orders.Remoe(order);
        await db.SaveChangesAsync();
        return Ok(order);
    }

    待续~~

  • 相关阅读:
    POJ1475【推箱子】(双bfs)
    CH2101:【可达性统计】(拓扑排序+状态压缩)
    拓扑排序模板
    BZOJ 2288: 【POJ Challenge】生日礼物 优先队列+贪心+链表
    Play Framework 完整实现一个APP(六)
    Play Framework 完整实现一个APP(五)
    Play Framework 完整实现一个APP(四)
    Play Framework 完整实现一个APP(三)
    Play Framework 完整实现一个APP(二)
    Play Framework 完整实现一个APP(一)
  • 原文地址:https://www.cnblogs.com/darrenji/p/4959623.html
Copyright © 2020-2023  润新知