如何用视图模型和表格内容序列化表单?

Posted

技术标签:

【中文标题】如何用视图模型和表格内容序列化表单?【英文标题】:How to serialize form with viewmodel and table content? 【发布时间】:2020-11-06 13:28:47 【问题描述】:

我是 ASP.NET MVC 的新手。我面临一个问题,无法找到解决方案。实际上我正在创建一个库存管理项目。在这个项目中,我有 2 个 ViewModel。一个是 PurchaseOrderViewModel,另一个是 TableViewModel。现在我在弹出模式中使用两者并将详细信息保存在视图模型中,但我无法做到这一点。在图像中,您可以看到下面显示了一个表记录,我需要将其插入到视图模型中。请帮助我。我真的很感谢你。

        [HttpPost]
    public async Task<ActionResult> CreateOrUpdatePurchase(PurchaseOrderViewModel purchase)
    
        PurchaseOrder purchase2 = new PurchaseOrder();
        int suplierId = purchase.Supplier_ID;
        purchase.Supplier_ID = suplierId;
        purchase.SupplierName = context.Suppliers.Where(x => x.Supplier_ID == suplierId).Select(x => x.Supplier_Name).FirstOrDefault();
        string loginId = Convert.ToString(Session["LoginId"]);
        string UserRoleName = Convert.ToString(Session["UserTypeName"]);
        try
        
            if (!string.IsNullOrEmpty(loginId))
            
                if (UserRoleName == RoleTypeConstant.CustomerUserType)
                
                    PurchaseOrder purchase1 = new PurchaseOrder();
                    purchase1.LoginID = loginId;
                    purchase1.PurchaseID = purchase.PurchaseID;
                    purchase1.SupplierID = purchase.Supplier_ID;
                    purchase1.SupplierName = purchase.SupplierName;
                    purchase1.Currency = purchase.Currency;
                    purchase1.Date_Of_Purchase = purchase.Date_Of_Purchase;
                    purchase1.Due_Date = purchase.Due_Date;
                    purchase1.CreatedBy = loginId;
                    purchase1.CreatedOn = DateTime.Now;
                    purchase1.UpdatedBy = loginId;
                    purchase1.UpdatedOn = DateTime.Now;
                    purchase1.Status = StatusConstant.Active;
                    bool regCustBen = await _websiteRepo.AddPurchase(purchase1);
                    if (regCustBen)
                    
                        return Json(new  success = true, message = "Saved Successfully" , JsonRequestBehavior.AllowGet);
                    
                    return RedirectToAction("GetPurchasePartial");
                
                else
                
                    return RedirectToAction("Purchase_Order", "Home");
                
            
            else
            
                return RedirectToAction("Login", "Account");
            
        
        catch (Exception)
        
            throw;
        
    


public class TableViewModel 


    public int Pid  get; set; 
    //public string ProductName  get; set; 
    public string Qty  get; set; 
    public string Price  get; set; 
    public string Amount  get; set; 



public class PurchaseOrderViewModel

    public int PurchaseID  get; set; 
    public string LoginID  get; set; 

    public int SupplierID  get; set; 
    public int Supplier_ID  get; set; 

    public string SupplierName  get; set; 
    public string Supplier_Name  get; set; 

    public string Currency  get; set; 

    [DisplayFormat(DataFormatString = "0:MM/dd/yyyy")]
    public string Date_Of_Purchase  get; set; 

    [DisplayFormat(DataFormatString = "0:MM/dd/yyyy")]
    public string Due_Date  get; set; 

    public string CreatedBy  get; set; 

    public DateTime? CreatedOn  get; set; 

    public string UpdatedBy  get; set; 

    public DateTime? UpdatedOn  get; set; 
    public int? Status  get; set; 

    public int OrderID  get; set; 

    public string ProductName  get; set; 

    //public List<Order> s  get; set; 

    public int Stock_ID  get; set; 
    public string Stock_Name  get; set; 

    public string Quantity  get; set; 

    public decimal Price  get; set; 

    public decimal Amount  get; set; 

    public List<TableViewModel> TableListDto   get; set; 

我的脚本是

    function CreateOrUpdate() 
        debugger;
        var modal = $("#purchaseModal");
        var form = $('form[name="purchaseForm"]');

        let tableData = $('#detailsTable > tbody > tr');
        debugger;
        console.log(tableData);

        var tableDto = [];

        $.each(tableData, function (rindex, row) 
            console.log(row);

            let tmp = ;

            tmp.pid = $(row).find('td:nth-child(1)').attr('pid');
            //tmp.productName = $(row).find('td:nth-child(1)').text();
            tmp.qty = $(row).find('td:nth-child(2)').text();
            tmp.price = $(row).find('td:nth-child(3)').text();
            tmp.amount = $(row).find('td:nth-child(4)').text();

            tableDto.push(tmp);
            tmp = ;
        );



        form.validate();
        if (!form.valid()) 
            return;
        
        else 
            var data = form.serialize();
            //data.TableListDto = tableDto.serialize();
            $.post("/Home/CreateOrUpdatePurchase", data, function (res) 
                if (res) 
                    modal.modal('hide');
                    dataTable.ajax.reload();
                    $.notify("Saved Successfully", 
                        className: "success",
                        globalPosition: 'top - center'
                    );
                
            )
        
    

让我向您展示我的输出屏幕。 Click Here

【问题讨论】:

不要使用 nth-child(1) 类型的东西,给 td 一个类以供使用 - 例如,您可以移动列而不必重做逻辑。 在您的方法中使用 purchase 之前验证它 purchase.Supplier_ID = suplierId;?为什么?混淆Supplier_IDSupplierID 对我来说毫无意义 嗨,马克,如果我删除了第 n 个孩子(1),那么我怎样才能得到表中的值。你能为我提供正确的代码吗?请查看我刚刚在帖子中上传的输出屏幕。 标记,用于来自供应商表的下拉值,以保存视图模型中的值。 【参考方案1】:

您将要发布您的购买清单,这有点捏造和人为的示例,但应该向您展示 c# 中的基本移植和命名空间中savePurchases 函数中的核心保存部分。我写得很快,并且没有测试过这个非常基本的(也没有 c# 测试),所以可能有一些错别字等。

为此你只需要注意两件事

    要保存的模型(这些列表) 发送到该保存车方法的对象(与该方法匹配的数组)参见savePurchases 函数

我制作了一个可以使用的表单,将物品放入购物车(没有添加删除),购物车是命名空间中的 purchases 对象数组。这只有简单的“添加项目”,其中没有超级花哨的东西。

[HttpPost]
public async Task<JsonResult> CreateOrUpdatePurchase(List<SaveModel> purchase)

    // first validate your data here
    // second, call your middle ware code to update database
    // third return results back, whatever you need, I made this up
    return Json(
         new PurchaseResultModel
         
              PurchaseQuantity = somevalue,
              PurchaseValue = somemoney,
              /*These are Provider only options.*/
              SavedOK = true, //verify save OK
              ValidData = true // validated data OK
          );
 
public class SaveModel 

    public int Pid  get; set; 
    public string Qty  get; set; 

创建一些 JSON 发送回

var myApp = 
  products: [
    pid: "123",
    name: "Water Cats",
    price: 42.34
  , 
    pid: "32234",
    name: "Bolts",
    price: 1.18
  , 
    pid: "56",
    name: "Sheep",
    price: 34.34
  , 
    pid: "2323",
    name: "Sack - cotton",
    price: 5.99
  ],
  currency: 'USD',
  currencySymbol: '$',
  onAddProduct: function() 
    let productCart = $('#product-cart');
    let firstProductItem = productCart
      .find('.product-item')
      .first();

  ,
  prod: ,
  savePurchases: function(event) 
    let me = event.data[0].arg1;
    if (me.purchases.length > 0) 
      // get what we sold
      let purchases = [];
      // this just to show how to make a match to the c# class
      // I left out price and amount since that should be a server calculation to prevent hacking of values.
      for (var i = 0; i < me.purchases.length; i++) 
        let p = 
          Pid: me.purchases[i].pid,
          Qty: me.purchases[i].qty
        ;
        purchases.push(p);
      

      $.ajax(
          url: "/Home/SavePurchase",
          data: purchases,
        )
        .complete(function(res) 
          if (res) 
            modal.modal('hide');
            dataTable.ajax.reload();
            $.notify("Saved Successfully", 
              className: "success",
              globalPosition: 'top - center'
            );
          
        )
        .fail(function(x) 
          // save fail action
        );
     else 
      // tell them they made no selections?
    
  ,
  validate: function() 
    form.validate();
    if (!form.valid()) 
      return;
     else 
      //do valid thing
    
  ,
  onQuantityChange: function(event) 
    let me = event.data[0].arg1;
    if (this.value > 0) 
      let opt = me.productSelect.find("option:selected");
      let product = opt.data('item');
      $('#price').val(product.price);
      let a = me.roundToCents(product.price * $(this).val());
      me.setFieldAmount(a, $('#amount-sold')[0]);
     else 
      $('#price').val(0);
      me.setFieldAmount(0, $('#amount-sold')[0]);
    
  ,
  localStringToNumber: function(s) 
    return Number(String(s).replace(/[^0-9.-]+/g, ""));
  ,
  setFieldAmount: function(amount, field) 
    var options = 
      maximumFractionDigits: 2,
      currency: this.currency,
      style: "currency",
      currencyDisplay: "symbol"
    ;
    field.value = amount ?
      this.localStringToNumber(amount).toLocaleString(undefined, options) :
      '';
  ,
  setTextAmount: function(amount, field) 
    var options = 
      maximumFractionDigits: 2,
      currency: this.currency,
      style: "currency",
      currencyDisplay: "symbol"
    ;
    let v =
      amount ?
      this.localStringToNumber(amount).toLocaleString(undefined, options) :
      '';
    field.text(v);
  ,
  onProductChange: function(event) 
    let me = event.data[0].arg1;
    let opt = me.productSelect.find("option:selected");
    let hasSelection = !!opt;
    me.productSelect.toggleClass('choice-made', hasSelection);
    let q = $('#quantity');
    q.prop('disabled', !hasSelection)
      .val(hasSelection ? 1 : 0)
      .trigger('change');
  ,
  roundToCents: function(num) 
    return Math.round(num * 100) / 100;
  ,
  onAddItem: function(event) 
    let me = event.data[0].arg1;
    let prod = me.productSelect;
    // only if we made a valid choice
    if (prod.hasClass('choice-made')) 
      let optVal = prod.find("option:selected").val();
      let product = me.products.find(x => x.pid === optVal);
      if (product) 
        let q = $('#quantity');
        let cart = $('#product-cart');
        let first = cart.find('.product-item').first();
        let itemRowC = first.clone();
        itemRowC.find('.product-name').text(product.name);
        itemRowC.find('.product-quantity').text(q.val());
        me.setTextAmount(product.price, itemRowC.find('.product-price').first());
        me.setTextAmount($('#amount-sold').val(), itemRowC.find('.product-amount').first());
        let v = 
          pid: optVal,
          qty: q.val()
        ;
        me.purchases.push(v);
        itemRowC.find('.hidden').find('div').unwrap('.hidden');
        let calctot = cart.find('.grand-total-group');
        itemRowC.insertBefore(calctot);
        let total = me.getCalculatedTotal(me.purchases);
        // reset quantity values
        q.prop('disabled', true)
          .val(0)
          .trigger('change');
        prod.val('')
          .removeClass('choice-made');
      
    
  ,
  getCalculatedTotal: function(purchases) 
    let total = 0;
    let count = purchases.length;
    for (var i = 0; i < purchases.length; i++) 
      let product = this.products.find(x => x.pid === purchases[i].pid);
      total = total + (product.price * purchases[i].qty);
    
    $('.products-in-cart').text(count);
    this.setTextAmount(total, $('#grand-total'));
    return total;
  ,
  startup: function() 
    this.productSelect = $('#products');
    this.purchases = [];
    //add products
    this.products.forEach(product => 
      const opt = $('<option value="' + product.pid + '">' + product.name + '</option>');
      opt.data('item', product);
      this.productSelect.append(opt);
    );
    $('#quantity').on('change', [
      arg1: this
    ], this.onQuantityChange);
    $('#products').on('change', [
      arg1: this
    ], this.onProductChange);
    $('#add-to-cart').on('click', [
      arg1: this
    ], this.onAddItem);
    $('#save-cart').on('click', [
      arg1: this
    ], this.savePurchases);
  
;

myApp.startup();
.hidden 
  display: none;
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

<div id="purchaseModal">
  <div id="purchaseOptions" data-list="[]" class="container-fluid">
    <div class="row">
      <div class="col-md-4 order-md-2 mb-4">
        <h4 class="d-flex justify-content-between align-items-center mb-3">
          <span class="text-muted">Your cart</span>
          <span class="products-in-cart badge badge-secondary badge-pill">3</span>
        </h4>
        <ul id="product-cart" class="list-group mb-3">
          <li class="list-group-item d-flex justify-content-between lh-condensed product-item">
            <div class="hidden">
              <div>
                <h6 class="my-0">Product name</h6>
                <small class="text-muted product-name">Brief description</small>
              </div>
              <div>
                <h6 class="my-0">Quantity</h6>
                <small class="text-muted product-quantity">3</small>
              </div>
              <div>
                <h6 class="my-0">Price</h6>
                <small class="text-muted product-price">$12.24</small>
              </div>
              <div>
                <h6 class="my-0">Amount</h6>
                <small class="centered-text text-muted product-amount">$36.72</small>
              </div>
            </div>
          </li>
          <li class="grand-total-group list-group-item d-flex justify-content-between bg-light">
            <div class="text-success">
              <span>Total (USD)</span>
            </div>
            <strong class="text-success"><span id="grand-total">0</span></strong>

          </li>
        </ul>
      </div>
      <div class="col-md-12 order-md-1">
        <h4 class="mb-3">Choose Products</h4>
        <form class="product-choice needs-validation" novalidate="" _lpchecked="1">
          <div class="row">
            <div class="col-md-5 mb-3">
              <label for="products">Products</label>
              <select class="custom-select d-block w-100" id="products" required="">
                <option value="">Choose...</option>
              </select>
              <div class="invalid-feedback">
                Please select a valid Product.
              </div>
            </div>
          </div>
          <div class="row ">
            <div class="col-3 ">
              <label for="quantity">Quantity</label>
              <div class="input-group">
                <div class="input-group-prepend">
                  <span class="input-group-text">#</span>
                </div>
                <input type="number" disabled="true" class="form-control" id="quantity" placeholder="0" required="">
                <div class="invalid-feedback" style="width: 100%;">
                  Quantity is required.
                </div>
              </div>
            </div>
            <div class="col-3 ">
              <label for="price">Price</label>
              <div class="input-group">
                <div class="input-group-prepend">
                  <span class="input-group-text">$</span>
                </div>
                <input type="text" class="form-control" id="price" disabled="true">
              </div>
            </div>
            <div class="col-3 ">
              <label for="amount-sold">Amount</label>
              <div class="input-group">
                <div class="input-group-prepend">
                  <span class="input-group-text">$</span>
                </div>
                <input type="text" pattern="^\d+(?:\.\d1,2)?$" class="form-control" id="amount-sold" disabled="true">
              </div>
            </div>
          </div>
          <div class="col-3 ">
            <button id="add-to-cart" class="form-control btn btn-info btn-sm " type="button">Add to Cart</button>
          </div>
      </div>
      <hr class="sm-4">
      <button id="save-cart" class="btn btn-primary btn-md btn-block" type="button">Save Cart</button>
      </form>
    </div>
  </div>
</div>
</div>

【讨论】:

非常感谢。现在我得到了如何做到这一点的答案。非常感谢!!!!

以上是关于如何用视图模型和表格内容序列化表单?的主要内容,如果未能解决你的问题,请参考以下文章

Django 表单验证与 DRF 序列化程序验证

如何用SPSS判别时间序列是不是平稳?

django表单提交后如何用弹框提示成功?

如何用简单易懂的例子解释隐马尔可夫模型

实用案例精讲!如何用perl写一个截序列的脚本?

从 Django 表单序列化