如何将模型数据保存到不同于View的表中?

时间:2017-11-22 22:38:08

标签: asp.net-core-mvc asp.net-core-2.0

我试图在Asp.Net Core 2.0 MVC中制作一个简单的购物车应用程序。我没有做任何Ajax。我有三种模式:

public class Product
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Info { get; set; }
    public decimal Price { get; set; }
}

public class Cart
{
    public int Id { get; set; }
    public int CartItemId { get; set; }
    public int CustomerId { get; set; } // not in use yet
}

public class CartItem
{
    public int Id { get; set; }
    public int ProductId { get; set; }
    public int NumEach { get; set; } // not in use yet
}

从下面两个视图中的任何一个,我想更新Cart和CartItem,然后重定向回到我点击添加到购物车按钮的视图:

1)索引视图:

@model IEnumerable<simpleShop.Models.Product>

<table class="table">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => model.Title)</th>
            <th>@Html.DisplayNameFor(model => model.Info)</th>
            <th>@Html.DisplayNameFor(model => model.Price)</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    <a asp-action="Details" asp-route-id="@item.Id">
                        @Html.DisplayFor(modelItem => item.Title)
                    </a>
                </td>
                <td>@Html.DisplayFor(modelItem => item.Info)</td>
                <td>@Html.DisplayFor(modelItem => item.Price)</td>
                <td>
                    <form asp-action="AddToCart">
                        <button type="submit" value="@item.Id">Add to cart</button>
                    </form>
                </td>
            </tr>
        }
    </tbody>
</table>

2)详细信息 - 视图:

@model simpleShop.Models.Product
@{
    ViewData["Title"] = Html.DisplayFor(model => model.Title);
}
<h2>@Html.DisplayFor(model => model.Title)</h2>
<h4>@Html.DisplayFor(model => model.Info)</h4>
<h1>@Html.DisplayFor(model => model.Price)</h1>
<form asp-action="AddToCart">
    <input type="hidden" asp-for="Id" /> 
    <p>
        <input type="submit" value="Add to cart" />
    </p>
</form>
<div>
    <a asp-action="Index">Return to list</a>
</div>

以下是家庭控制器中我的错误AddToCart方法,目前肯定没有做任何事情来保存数据到Cart或CartItem表。我怎么能得到它?

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddToCart([Bind("Id")] Product product)
{
    if (ModelState.IsValid)
    {
        _context.Add(product);
        await _context.SaveChangesAsync();
        if (product.Id > 0) // added to cart via the details-view
        {
            return RedirectToAction("Details", "Home", product.Id);
        }
        else // added to cart via the index-view
        {
            return RedirectToAction(nameof(Index));
        }
    }
    return View(product);
}

1 个答案:

答案 0 :(得分:0)

对于一件事,Bind()需要的不仅仅是“id”,记住你想要绑定的东西必须包括你想要传递给新动作的对象的所有属性。

引用注释 - &gt;&gt;

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddToCart([Bind("Id")] Product product)
{
   if (ModelState.IsValid)
   {
       _context.Add(product); //**BAD this will probably try to
                              // add product to the product table again.**
                              // With error to follow about already exists
                              // exception at the SaveChangesAsync call.
       await _context.SaveChangesAsync();

       if (product.Id > 0) 
       {
           return RedirectToAction("Details", "Home", product.Id);
       }
       else // added to cart via the index-view
       {
           return RedirectToAction(nameof(Index));
       }
    }
    return View(product);
}

我的建议是这样的,你将拥有产品的ProductId和Qty(你的NumEach)

[HttpPost]
[ValidateAntiForgeryToken]
public asyync Task<IActionResult> AddToCart([Bind("ProductId", "NumEach", "CartId")] CartItem model, string ReturnUrl){
    if(ModelState.IsValid){

       _context.CartItem.Add(model);

        await _context.SaveChangesAsync();

        //model.Id greater than 0 indicates a save occurred.
        if(model.Id > 0)
          return RedirectToAction(ReturnUrl);  // forced return for further shopping?
        else
          return RedirectToAction("Index");      
    }

     //this assumes bad model state with no error unless model is 
     //annotated accordingly.

    return View(model);
}

购物车的问题虽然现在只能存储1件......

public class Cart{
   public Cart(){}


   public int Id {get;set;}   //cart's integer id

   public List<CartItem> CartItems {get;set;} //collection of cartitems

   //FK
   public int CustomerId {get;set;}   //customer's id
   //NAV
   public Customer CustomerId {get;set;}  //customer nav
   ...
}

public class CartItem{
   public CartItem(){}

   public int Id {get;set;}         //cart item id

   public int ProductId {get;set;}   //productid
   public Product Product {get;set;} //nav property

   public int NumEach {get;set;}     //quantity of each product

   //FK
   public int CartId {get;set;}      //Foreign Key
   //NAV
   public Cart Cart {get;set;}       //nav property
}

另一件事你的索引视图不仅仅是模型是一个产品集合,它可能是一个viewmdodel,其中包含一系列产品,但它也包含与访问者一起生成的cartid 。 CartId将跟随该访问者,直到交易完成,然后您有一个OrderId,或者一旦会话结束就会死亡。

@model simpleShop.Models.IndexViewModel

<table class="table">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => model.Title)</th>
            <th>@Html.DisplayNameFor(model => model.Info)</th>
            <th>@Html.DisplayNameFor(model => model.Price)</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.Products)
        {
            <tr>
                <td>
                    <a asp-action="Details" asp-route-id="@item.Id">
                        @Html.DisplayFor(modelItem => item.Title)
                    </a>
                </td>
                <td>@Html.DisplayFor(modelItem => item.Info)</td>
                <td>@Html.DisplayFor(modelItem => item.Price)</td>
                <td>
                    <form asp-action="AddToCart">
                        <input type="Hidden" asp-for="@Model.CartId" />

                        <button type="submit" value="@item.Id">Add to cart</button>
                    </form>
                </td>
            </tr>
        }
    </tbody>
</table>


public class IndexViewModel 
{  
     public IndexViewModel(){}

     public int CartId{get;set;}
     public List<Product> Products{get;set;}
 }

我想你从那里得到了这个想法。