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

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

原文:
购物车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);
}

 

待续~~

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109250.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 黑马程序员—wpf学习笔记四—banding的那些事

    黑马程序员—wpf学习笔记四—banding的那些事——-WindowsPhone7手机开发、.Net培训、期待与您交流!——-一、WPF中,对控件做数据banding,可以方便的进行赋值和获得值的操作:例如一:<Grid><SliderName=”Slider1″HorizontalAlignment=”Left”Margi…

    2022年10月13日
    0
  • docker基本操作命令_docker里面运行docker

    docker基本操作命令_docker里面运行docker一、Docker安装1、卸载Dockersudoyumremovedocker\docker-client\docker-client-latest\docker-common\docker-latest\docker-latest-logrotate\

    2022年9月18日
    0
  • CMD命令提示符窗口中的快捷键、小技巧和常用命令

    CMD命令提示符窗口中的快捷键、小技巧和常用命令快捷键:F1:按F1一次,命令提示符向后切换到已经执行过的命令字符。如果已经是最后的一条的命令,则不进行任何切换操作。例子:之前输入“dir”,按F1一次后自动输入d,按两次自动输入i,三次自动输入r。F2:按下此键后,会提示“输入可复制的字符数量”,此时直接按下上次输入命令中包含的字符(区分大小写)后命令提示符将自动输入到按键字符之前的上次输入的命令

    2022年4月5日
    84
  • robots.txt详解[通俗易懂]

    robots.txt详解[通俗易懂]怎样查看robots文件?浏览器输入主域名/robots.txtrobots.txt的作用robots.txt文件规定了搜索引擎抓取工具可以访问网站上的哪些网址,并不禁止搜索引擎将某个网页纳入索引。如果想禁止索引(收录),可以用noindex,或者给网页设置输入密码才能访问(因为如果其他网页通过使用说明性文字指向某个网页,Google在不访问这个网页的情况下仍能将其网址编入索引/收录这个网页)。robots.txt文件主要用于管理流向网站的抓取工具流量,通常用于阻止Google.

    2022年5月1日
    44
  • 乱码问题分析

    乱码问题分析字符乱码的事,估计大家都遇到过,很烦,什么utf-8、GBK、GB2312转来转去,不知道什么时候才能转正常。我们做个试验,如果你是windows系统,打开记事本,新建一个文件,输入”联通”两个字之后,保存,关闭,然后再次打开,出现了什么现象?乱码!那你赶紧去找IT吧,你中招了!开玩笑的,这是著名的“windows联通之谜事件”。继续往下看,后面会有谜底的解释。那么我们就讨论下字符编码哪些事吧,首

    2022年5月27日
    61
  • maven安装步骤_eclipse使用maven教程

    maven安装步骤_eclipse使用maven教程前言本篇文章是基于win10系统下载安装Maven的教程。一、Maven介绍1.什么是Maven​ Maven是一个跨平台的项目管理工具。作为Apache组织的一个颇为成功的开源项目,其主要服务于基于Java平台的项目创建,依赖管理和项目信息管理。maven是Apache的顶级项目,解释为“专家,内行”,它是一个项目管理的工具,maven自身是纯java开发的,可以使用maven对java项目进行构建、依赖管理。2.Maven的作用依赖管理依赖指的就是是我们项目中需要使用的第三方

    2022年9月8日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号