【问题标题】:How can I save model data to different tables than that of the View?如何将模型数据保存到与视图不同的表中?
【发布时间】:2017-11-24 16:10:10
【问题描述】:

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

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);
}

【问题讨论】:

  • 那么目前到底发生了什么?它是否进入 AddToCart 操作?您是否在调试中运行它来检查流程?
  • AddToCart 操作正在运行,但它没有收到任何数据。但就像现在一样,它被设置为写入 Product 表,而不是 Cart 和 CartItem 表。如果我将操作方法​​更改为 CartItem 而不是 Product,它只会将 NumEach 的 0 和 ProductId 的 0 保存到 CartItem 表,并重定向到没有 Id 的 Home/Details,导致 404。这很奇怪,因为 if -测试product.Id(或cartItem.ID,如果我改变它,没关系)> 0,然后重定向到Home/Details + Id,它应该有一个Id > 0 ...

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


【解决方案1】:

一方面,Bind() 需要的不仅仅是“id”,记住你想要绑定的内容必须包含你想要传递给新操作的对象的所有相关属性。

在行中引用 cmets -->>

[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 和产品的数量(你的 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,但它也将包含与访问者一起生成的 carid .该 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;}
 }

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 2011-04-13
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 2014-03-13
    • 1970-01-01
    相关资源
    最近更新 更多