• ASP.NET MVC 3.0 知识记要(3)【主从属性共同编辑后的表单提交】


    一般来说,对某个实体进行编辑都是没有问题的,比如微软官方的音乐商店,用自动生成的代码便可以顺利的搞定。但有一种业务情景是两个模型一同编辑,然后一同提交到Action,这时问题就来了。举一个例子,比如订单和订单明细。

    一.列举所用到的实现类

    /// <summary>
    /// 订单
    /// </summary>
    public class Order
    {
    public int OrderID { set; get; }

    [Display(Name = "订单简述")]
    public string Description { set; get; }

    [Display(Name = "创建人")]
    public string CreatePerson { set; get; }

    [Display(Name = "创建时间")]
    public DateTime CreateDate { set; get; }

    [Display(Name="订单类别")]
    public int CategoryID { set; get; }
    public List<OrderDetail> OrderDetailList { set; get; }
    }

    /// <summary>
    /// 订单明细
    /// </summary>
    public class OrderDetail
    {
    public int OrderDetailID { set; get; }
    public int OrderID { set; get; }
    public string ProductName { set; get; }
    public int Amount { set; get; }
    public double UnitPrice { set; get; }
    }

    /// <summary>
    /// 类别
    /// </summary>
    public class Category
    {
    public int CategoryID { set; get; }
    public string CategoryName { set; get; }
    }

    红线加粗的实体,便是接下来演练主从实体同时编辑,再一并提交的主解。

    二.定义两个Action,一个用以打开页面,一个用以响应客户端提交表单的请求。

    • 基于Get请求的CreateOrder()用以展现页面,它通过View视图层来呈现定单主体Order,以及定单从体OrderDetail(基于Ajax异步加载来生成),在此之前,顺便初始化一下定单类型下拉框,它需要的是SelectList类:
    [HttpGet]
    public ActionResult CreateOrder()
    {
    var CategoryItems = new List<Category>() {
    new Category(){
    CategoryID = 10,
    CategoryName = "公司内产"
    },
    new Category(){
    CategoryID = 11,
    CategoryName = "公司外购"
    }
    };

    ViewData["Order.CategoryID"] = new SelectList(CategoryItems, "CategoryID", "CategoryName", "");

    return View();
    }
    • 用以响应客户端提交表单的请求:
    [HttpPost]
    public ActionResult CreateOrder(Order order)
    {
    order.OrderDetailList = orderDetails;
    return RedirectToAction("CreateOrder");
    }

    三.将从属Model做成PartialView

    @model TelerikMvcApplication1.Models.OrderDetail
    @using TelerikMvcApplication1.Helpers

    <div class="editorRow">
    @using (Html.BeginCollectionItem("Order.OrderDetailList"))
    {
    @Html.LabelFor(d => d.ProductName)
    @Html.TextBoxFor(d => d.ProductName)
    <br />
    @Html.LabelFor(d => d.Amount)
    @Html.TextBoxFor(d => d.Amount)
    <br />
    @Html.LabelFor(d => d.UnitPrice)
    @Html.TextBoxFor(d => d.UnitPrice)
    <hr />
    <a href="#" class="deleteRow">delete</a>
    }
    </div>

    需要注意的是 Html.BeginCollectionItem("Order.OrderDetailList")的参数命名极为重要,因为它是OrderDetail呈现于主页面时其名称(name)的前缀,同时该名称还包括一对中括号”[]“,且其中值为Guid,比如产品名称ProductName,在客户端的名称很可能是:

    <input id="Order_OrderDetailList_5c9f0287-82a2-41f3-96b4-9c8b2459527c__ProductName" 

        type="text" 

        value="" 

        name="Order.OrderDetailList[5c9f0287-82a2-41f3-96b4-9c8b2459527c].ProductName">

    四.主页面的设置

      因为有从属模型OrderDetail的介入,所以主模型的名称也要统统加以前缀,否则本来正常的主模型也无法把提交的数据对应到主实体类上,原因暂不明:

    <label for="@string.Format("Order.{0}", "Description")">订单简述</label>
    @Html.TextBox(string.Format("Order.{0}", "Description"))

      顺便列举出下拉框的绑定方法:

    //Controller层
    var CategoryItems = new List<Category>() {
    new Category(){
    CategoryID = 10,
    CategoryName = "公司内产"
    },
    new Category(){
    CategoryID = 11,
    CategoryName = "公司外购"
    }
    };
    ViewData["Order.CategoryID"] = new SelectList(CategoryItems, "CategoryID", "CategoryName", "");


    //View层
    @Html.DropDownList(string.Format("Order.{0}", "CategoryID"), @ViewData["Order.CategoryID"] as List<SelectListItem>, "--请选择--", new { })


    五.订单明细的呈现

    规划出订单明细呈现的区域,其实就是一个Div,它位于订单的下方,在实际项目中可以认真研究一下排版:

    <fieldset>
    <legend>订单明细</legend>
    <div id="OrderDetailDiv">
    </div>
    </fieldset>

    六.通过单击“+”号按钮动态加载一行新的明细,并且支持删除,当然这一切都是无刷新:

    @using (Ajax.BeginForm("CreateOrderDetail", "Home", new AjaxOptions()
    {
    HttpMethod = "POST",
    InsertionMode = InsertionMode.InsertAfter,
    UpdateTargetId = "OrderDetailDiv",
    OnSuccess = "SuccessCallBack"
    }))
    {
    <input type="submit" id="btnAddDetail" value=" + " />
    }

    它以Post形式向服务端发起请求,当请求成功后,得到的返回值(HTML部分块)以“InsertAfter”方式进行添加,且更新于UpdateTargetId指定的区域,最后执行OnSuccess指定的JS函数。

    七.主模型字段需要注意,各字段name需要加前缀:

    @using (Html.BeginForm("CreateOrder", "Home", FormMethod.Post))
    {
    <input type="submit" value="全面提交" />
    <hr />

    <label for="@string.Format("Order.{0}", "Description")">订单简述
    </label>
    @Html.TextBox(string.Format("Order.{0}", "Description"))
    <br />
    <br />

    <label for="@string.Format("Order.{0}", "CreatePerson")">创建人员
    </label>
    @Html.TextBox(string.Format("Order.{0}", "CreatePerson"))
    <br />
    <br />

    <label for="@string.Format("Order.{0}", "CreateDate")">创建时间
    </label>
    @Html.TextBox(string.Format("Order.{0}", "CreateDate"))

    <br />
    <br />
    <label for="@string.Format("Order.{0}", "CategoryID")">
    </label>
    @Html.DropDownList(string.Format("Order.{0}", "CategoryID"), @ViewData["Order.CategoryID"] as List<SelectListItem>, "--请选择--", new { })
    <br />
    <br />
    <fieldset>
    <legend>订单明细</legend>
    <div id="OrderDetailDiv">
    </div>
    </fieldset>
    }

    建议调试方法:采用火狐浏览器的FireBug工具,和IE浏览器的HttpWatch

  • 相关阅读:
    获取全部 txt 文本中出现次数最多的前N个词汇
    提取txt文本有效内容
    部分画图
    Series结构(常用)
    C 语言实例
    HTML之marquee(文字滚动)详解
    一款好看的404页面代码 | 滚动的404
    VS2010到VS2019各个版本的密钥
    什么是工程/项目?
    什么是IDE(集成开发环境)?
  • 原文地址:https://www.cnblogs.com/luoxiaonet/p/2369953.html
Copyright © 2020-2023  润新知