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

简介: 原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端  chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解。
原文: 购物车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);
}

 

待续~~

 

目录
相关文章
|
19小时前
|
开发框架 安全 .NET
使用VB.NET构建Web服务和REST API的指南
【7月更文挑战第2天】使用VB.NET构建Web服务和REST API的指南:从Web服务基础到ASP.NET Core实践,涵盖控制器、路由、模型绑定、安全措施(如JWT、HTTPS)及测试、部署(Azure、Docker)与监控工具。了解如何利用VB.NET在现代云环境中创建高效、安全的API。开始你的VB.NET Web服务开发之旅!**
5 1
|
2天前
|
前端开发 JavaScript 开发者
现代前端开发中的Web组件化设计
随着Web应用程序复杂性的增加,现代前端开发越来越倾向于采用组件化设计。本文将探讨Web组件化的定义、优势以及实际应用中的最佳实践,帮助开发者更好地理解和应用这一技术。
|
5天前
|
前端开发 计算机视觉
视觉智能开放平台操作报错合集之人脸对比1:1,采用web前端直接调用,使用了base64处理图片,提示http错误码414,该如何处理
在使用视觉智能开放平台时,可能会遇到各种错误和问题。虽然具体的错误代码和消息会因平台而异,但以下是一些常见错误类型及其可能的原因和解决策略的概述,包括但不限于:1. 认证错误、2. 请求参数错误、3. 资源超限、4. 图像质量问题、5. 服务不可用、6. 模型不支持的场景、7. 网络连接问题,这有助于快速定位和解决问题。
|
5天前
|
弹性计算 算法 安全
视觉智能开放平台产品使用合集之在Web应用和WinForm应用程序中调用API时,出现Web端能够成功调用而WinForm端调用失败,是什么原因
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
5天前
|
前端开发 程序员 API
视觉智能开放平台产品使用合集之web前端拉起人脸识别该如何操作
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
6天前
|
移动开发 前端开发 JavaScript
快速上手web前端开发(超详细教程)
快速上手web前端开发(超详细教程)
|
6天前
|
JSON 前端开发 Java
一文读Web开发 之接口后端接口、类与前端请求、拦截器编写
一文读Web开发 之接口后端接口、类与前端请求、拦截器编写
21 6
|
8天前
|
前端开发 JavaScript
web开发前端适配
web开发前端适配
10 0
|
8天前
|
缓存 前端开发 安全
探索现代Web开发中的前端架构模式
【6月更文挑战第23天】随着互联网技术的飞速发展,前端架构在Web开发中扮演着越来越重要的角色。本文将深入探讨现代Web开发中使用的几种主流前端架构模式,包括单页面应用(SPA)、微前端架构和JAMStack等,并分析它们的优势与应用场景。通过实例演示,我们将看到如何根据项目需求选择合适的前端架构,以及如何利用这些架构模式提升开发效率和应用性能。
|
9天前
|
前端开发 JavaScript API
探索现代Web开发中的动态数据交互——前端与后端整合实战
本文探讨了现代Web开发中前端与后端整合的关键技术点,通过实际案例演示了如何利用JavaScript和Node.js实现动态数据交互,全面解析从数据请求到响应的全过程。