Day06 - 纯 Html 复杂型别 - object + object collection

结合已提到的 object 及 collection 在 Model Binding 的格式说明
很接近多数人在工作中常碰到的挑战
以资料表结构来看,就是一主表对多子表的结构

今天 ViewModel 都使用相同的结构:

public class ViewModel
{
    public DateTime? OrderDate { get; set; }

    public OrderItem[] Items { get; set; }
}

/// <summary>
/// 订单项目
/// </summary>
public class OrderItem
{
    /// <summary>
    /// 名称
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 数量
    /// </summary>
    public int? Quantity { get; set; }
}

Case01

提醒:这个 Case 是 Binding 失败的 !

  • Controller

    [HttpGet]
    public IActionResult Case01()
    {
        return View();
    }
    
    [HttpPost]
    public IActionResult Case01([FromForm]ViewModel vm)
    {
        return Ok(vm);
    }
    
  • View

    套用上一篇 Case01 提到的格式来给定 name,则 tbody 内的 html 就会是

    <tbody>
        <tr>
            <td>
                <input type="text"
                    name="Items.Name">
            </td>
            <td>
                <input type="text"
                       name="Items.Quantity">
            </td>
        </tr>
        <tr>
            <td>
                <input type="text"
                       name="Items.Name">
            </td>
            <td>
                <input type="text"
                       name="Items.Quantity">
            </td>
        </tr>
        <tr>
            <td>
                <input type="text"
                       name="Items.Name">
            </td>
            <td>
                <input type="text"
                       name="Items.Quantity">
            </td>
        </tr>
    </tbody>
    

网站执行後,在该页面输入资料,并 submit form !

由下图可以看出 request body 的资料,以及後端回传的资料 !

可以发现 Items Binding 失败了 !

Image

可以到 bin 执行目录下找 Log 来看

  • 目录位於 Project\bin\Debug\net5.0\Fiele\Logs\nlog-all-yyyy-MM-dd.log
    • yyyy-MM-dd - 就是指执行程序的日期

其中完整的错误讯息如下:

2021-05-22 16:41:57.1340 | 13 | DEBUG | Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder | Attempting to bind property 'Project.Models.Day05.ViewModel.Items' of type 'Project.Models.Day05.OrderItem[]' using the name 'Items' in request data ... 
2021-05-22 16:41:57.1340 | 28 | DEBUG | Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder | Could not bind to collection using a format like Items=value1&Items=value2 
2021-05-22 16:41:57.1340 | 29 | DEBUG | Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder | Attempting to bind model using indices. Example formats include: [0]=value1&[1]=value2, Items[0]=value1&Items[1]=value2, Items.index=zero&Items.index=one&Items[zero]=value1&Items[one]=value2 
2021-05-22 16:41:57.1340 | 24 | DEBUG | Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinder | Attempting to bind model of type 'Project.Models.Day05.OrderItem' using the name 'Items[0]' in request data ... 
2021-05-22 16:41:57.1492 | 18 | DEBUG | Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinder | Could not bind to model of type 'Project.Models.Day05.OrderItem' as there were no values in the request for any of the properties. 
2021-05-22 16:41:57.1492 | 14 | DEBUG | Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder | Done attempting to bind property 'Project.Models.Day05.ViewModel.Items' of type 'Project.Models.Day05.OrderItem[]'. 

撷取关键的错误讯息:

  • Items=value1&Items=value2 binding collection 会失败

    Could not bind to collection using a format like Items=value1&Items=value2
    
  • 下面讯息提到三种格式

    Example formats include: [0]=value1&[1]=value2, Items[0]=value1&Items[1]=value2, Items.index=zero&Items.index=one&Items[zero]=value1&Items[one]=value2 
    
    1. [0]=value1&[1]=value2

    就是上上篇所提到的做法 !

    1. Items[0]=value1&Items[1]=value2

    就是上一篇 Case02 所提到的做法 !

    1. Items.index=zero&Items.index=one&Items[zero]=value1&Items[one]=value2

    就是上一篇 Case03 所提到的做法 !


Case02

  • Controller

    • Get 语法只有 Action 名称与 Case01 不同,所以就不细看了 !
    • Post 语法都与 Case01 共用,就不写重复的程序码了 !
  • View

    套用上一篇 Case02 提到的格式来给定 name,则 tbody 内的 html 就会是

    <tbody>
        <tr>
            <td>
                <input type="text"
                       name="Items[0].Name">
            </td>
            <td>
                <input type="number"
                       step="1"
                       min="0"
                       name="Items[0].Quantity">
            </td>
        </tr>
        <tr>
            <td>
                <input type="text"
                       name="Items[1].Name">
            </td>
            <td>
                <input type="number"
                       step="1"
                       min="0"
                       name="Items[1].Quantity">
            </td>
        </tr>
        <tr>
            <td>
                <input type="text"
                       name="Items[2].Name">
            </td>
            <td>
                <input type="number"
                       step="1"
                       min="0"
                       name="Items[2].Quantity">
            </td>
        </tr>
    </tbody>
    

网站执行後,在该页面输入资料,并 submit form !

由下图可以看出 request body 的资料,以及後端可以正确回传原本 submit 的资料 !

Image


Case03

  • Controller

    • Get 语法只有 Action 名称与 Case01 不同,所以就不细看了 !
    • Post 语法都与 Case01 共用,就不写重复的程序码了 !
  • View

    套用上一篇 Case03 提到的格式,并打乱 index 来给定 name,则 tbody 内的 html 就会是

    <tbody>
        <tr>
            <input type="hidden"
                   name="Items.index"
                   value="0">
            <td>
                <input type="text"
                       name="Items[0].Name">
            </td>
            <td>
                <input type="number"
                       step="1"
                       min="0"
                       name="Items[0].Quantity">
            </td>
        </tr>
        <tr>
            <input type="hidden"
                   name="Items.index"
                   value="1">
            <td>
                <input type="text"
                       name="Items[1].Name">
            </td>
            <td>
                <input type="number"
                       step="1"
                       min="0"
                       name="Items[1].Quantity">
            </td>
        </tr>
        <tr>
            <input type="hidden"
                   name="Items.index"
                   value="3">
            <td>
                <input type="text"
                       name="Items[3].Name">
            </td>
            <td>
                <input type="number"
                       step="1"
                       min="0"
                       name="Items[3].Quantity">
            </td>
        </tr>
    </tbody>
    

网站执行後,在该页面输入资料,并 submit form !

由下图可以看出 request body 的资料,以及後端可以正确回传原本 submit 的资料 !

Image

这个语法比较特殊,之後会在前端动态新增/删除的文章中再次使用 !


这篇先到这里,下一篇来看 如何搭配 Html Helper 来产生符合预期的 name 格式 !


<<:  [Tableau Public] day 6:尝试制作不同种类的报表-3

>>:  Day-5 现代电视游玩怀旧主机可接受的最低标准、最终方案 S 端子

DAY05 - XAMPP的vhost与SSL设定

前言: 今天是铁人赛的第五天,要特别讲一下vhost(虚拟网站)的设定方式 启动XAMPP的Apac...

[Java Day21] 5.1. 私有化

教材网址 https://coding104.blogspot.com/2021/06/java-5...

网路对等连线

Peering Connection 继前两天提到的VPC,这边就不得不提到VPC网路对等连线(Pe...

Day 7 python字典

今天我们要介绍的是python的字典,所谓的字典就是指将元素用{}包住并且元素是由一个键(key)配...

Day24 DB-NodeJS中的mongoDB

昨天讲了关联式资料库的MySQL,今天要接着介绍NoSQL中受欢迎的mongoDB,以及在NPM里m...