【问题标题】:How to bind model in Kendo UI?如何在 Kendo UI 中绑定模型?
【发布时间】:2016-12-15 10:41:55
【问题描述】:

在使用带有 Angular 的 Kendo UI 创建动作后,我遇到了绑定模型的问题。

在调试模式下创建请求后,我在 PoController 中成功实现了所需的操作调用,但控制器必须接受的对象为空。

在 Fiddler 中,我可以通过正文观看请求“/PO/Create”:

模型=%5B%7B%22id%22%3Anull%2C%22po_number%22%3A%221%22%2C%22note%22%3A%22ojklj%22%2C%22valid_start%22%3A%222016- 08-09T10%3A06%3A46.703Z%22%2C%22valid_end%22%3A%222016-08-09T10%3A06%3A46.703Z%22%7D%5D

有人可以帮助进行模型绑定吗?可能是 Kendo UI 数据源配置错误?

app.js

var app = angular.module("app", ["kendo.directives"]);

poDataSource.js

'use strict';

app.factory('poDataSource',
    function () {
        return new kendo.data.DataSource({
            transport: {
                type: "odata",
                read: {
                    url: '/PO/GetAll',
                    datatype: 'jsonnp',
                    type: 'get',
                },
                create: {
                    url: "/PO/Create",
                    dataType: "jsonp",
                    type: "post"
                    },
                parameterMap: function (options, operation) {
                        if (operation !== "read" && options.models) {
                            return { models: kendo.stringify(options.models) };
                        }
                    }
                },
                batch: true,
                pageSize: 5,
                schema: {
                    model: {
                        id: "id",
                        fields: {
                            id: { editable: false, nullable: true },
                            po_number: { type: "string" },
                            note: { type: "string" },
                            valid_start: { type: "date" },
                            valid_end: { type: "date" }
                        }
                    }
                }

            });
    });

Index.cshtml

<kendo-grid k-data-source="dataSource"
            k-columns="gridColumns"
            k-editable="'inline'"
            k-toolbar="['create']"
            k-sortable="true"
            k-pageable="true"
            k-resizeable="true">
</kendo-grid>

_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title - SWE Team Dashboard</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/kendo/2016.1.226/kendo.common-material.min.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/kendo/2016.1.226/kendo.mobile.all.min.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/kendo/2016.1.226/kendo.dataviz.min.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/kendo/2016.1.226/kendo.material.min.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/kendo/2016.1.226/kendo.dataviz.material.min.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/kendo/2016.1.226/jquery.min.js")"></script>
    <script src="@Url.Content("~/Scripts/kendo/2016.1.226/angular.min.js")"></script>
    <script src="@Url.Content("~/Scripts/kendo/2016.1.226/jszip.min.js")"></script>
    <script src="@Url.Content("~/Scripts/kendo/2016.1.226/kendo.all.min.js")"></script>
    <script src="~/Content/app/app.js"></script>
    <script src="~/Content/app/services/appService.js"></script>
    <script src="~/Content/app/services/poDataSource.js"></script>
    <script src="~/Content/app/controllers/homeController.js"></script>
</head>
<body ng-app="app" ng-controller="homeController as app">
    <header>
        <div class="content-wrapper">
            <div class="float-left">
                <p class="site-title">@Html.ActionLink("SWE Team Dashboard", "Index", "Home")</p>
            </div>
            <div class="float-right">
                <nav>
                    <ul id="menu">
                        <li>@Html.ActionLink("PO", "Index", "Home")</li>
                        <li>@Html.ActionLink("TMT Tasks", "Tasks", "Home")</li>
                        <li>@Html.ActionLink("Task to PO mapping", "TaskPOReferences", "Home")</li>
                    </ul>
                </nav>
            </div>
        </div>
    </header>
    <div id="body">
        @RenderSection("featured", required: false)
        <section class="content-wrapper main-content clear-fix">
            @RenderBody()
        </section>
    </div>

    <footer>
        <div class="content-wrapper">
            <div class="float-left">
                <p>&copy; @DateTime.Now.Year - My Telerik MVC Application</p>
            </div>
        </div>
    </footer>
</body>
</html>

POController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Dashy.DB.Model;
using Dashy.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;

namespace Dashy.Controllers
{
    public class POController : Controller
    {
        // GET: PO/GetAll
        public async Task<ActionResult> GetAll()
        {
            var allItems = new PODAL().GetAll();

            return Json(allItems, JsonRequestBehavior.AllowGet);
        }

        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(PO po)
        {
            try
            {
                new PODAL().AddPo(po);
                return RedirectToAction("Index");
            }
            catch (Exception exception)
            {
                return View();
            }
        }




        // GET: PO/GetTaskToPoMapping
        public string GetTaskToPoMapping()
        {
            var allItems = new PODAL().GetTaskToPoMapping();
            var jsonResult = JsonConvert.SerializeObject(allItems,
                new JsonSerializerSettings()
                {
                    ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
                });
            return jsonResult;
        }
    }
}

PO.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate;

namespace Dashy.DB.Model
{
    public class PO
    {
        public virtual string note { get; set; }
        public virtual int id { get; set; }
        public virtual DateTime valid_start { get; set; }
        public virtual DateTime valid_end { get; set; }
        public virtual string po_number { get; set; }
        public virtual IList<POLine> po_lines { get; set; }

        public virtual void AddPOLine(POLine line)
        {
            line.po = this;
            po_lines.Add(line);
        }
        public PO()
        {
            po_lines = new List<POLine>();
        }
    }
}

【问题讨论】:

  • 刚看了一眼,我发现了一个问题,变量 id 被声明为 int,但是您在模型中发送 NULL 值使其可以为空或更改模型数据models=[{"id":null,"po_number":"1","note":"ojklj","valid_start":"2016-08-09T10:06:46.703Z","valid_end":"2016-08-09T10:06:46.703Z"}]
  • @Vijai 不是说 id 可以为空:id: { editable: false, nullable: true }?还是你的意思是别的?
  • @StanislavMachel , "[{"id":null,"po_number":"1","note":"ojklj","valid_start":"2016-08-09T10:06:46.703Z","valid_end":"2016-08-09T10:06:46.703Z"}]" 您正在向服务器发送一个列表,但是在 POST Create Action 我可以看到它的 PO ,所以它应该是 List&lt;PO&gt; 或者您的客户端代码需要修改。顺便说一句,您还可以在参数中设置名为 DatasourceRequest 的内容

标签: angularjs asp.net-mvc kendo-ui model-binding


【解决方案1】:

batch 设置为 true,这意味着 Kendo UI DataSource 将通过以下方式在单个请求中发送所有新项目:

models: [
    { FieldName1: "value 1.1", FieldName2: "value 2.1" },
    { FieldName1: "value 1.2", FieldName2: "value 2.2" }
]

目前看来服务器端代码并​​没有预料到这一点。

要么更改服务器实现,要么禁用批处理操作。还要留意你的 parameterMap 函数,因为它也直接影响项目的提交方式。

http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-batch

http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-transport.parameterMap

【讨论】:

    【解决方案2】:

    解码你的URI后看起来像下面,

    "[{"id":null,"po_number":"1","note":"ojklj",
    "valid_start":"2016-08-09T10:06:46.‌​703Z","valid_end":"2016-08-09T10:06:46.703Z"}]"
    

    在这里,您正在向服务器发送列表,但在 POST Create Action 中我可以看到 PO ,所以它应该是 List&lt;PO&gt; 或者您的客户端代码需要修改为发送单个对象.

    我的建议是,您还可以在参数中设置名为 DatasourceRequest 的内容,这样您就可以获得剑道支持的所有参数。

    更多关于 DatasourceRequest herehere

    【讨论】:

      【解决方案3】:

      以前的答案可以帮助我正确地解决这个问题。如果batch 设置为true 它返回项目列表,这意味着我需要重新实现我的控制器,它可以接收List&lt;PO&gt;

      但这里还有其他大问题。实际上这个控制器返回的不是http响应,而是返回视图和更好的决定是实现WEB API。基本上我需要重新实现程序。

      这里有一些变化

      POController.cs

      using Dashy.DB.Model;
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Net;
      using System.Net.Http;
      using System.Web.Http;
      using Dashy.Models;
      using System.ComponentModel.DataAnnotations;
      using FluentNHibernate.Conventions.Inspections;
      using System.Web.Mvc;
      
      namespace Dashy.Controllers
      {
          public class TestController : ApiController
          {
              private PODAL _podal = new PODAL();
      
              public IQueryable<PO> GetPOs()
              {
                  return _podal.GetAll().AsQueryable();
              }
      
              public HttpResponseMessage PostPO([Bind(Exclude="id,po_lines")]PO po)
              {
                  po.po_lines = new List<POLine>();
      
                  if (ModelState.IsValid)
                  {
                      _podal.AddPo(po);
                      HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, po);
                      response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = po.id }));
                      return response;
                  }
                  else
                  {
                      return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
                  }
              }
      }
      

      poDataSource.js

      'use strict';
      
      app.factory('poDataSource',
          function () {
              return new kendo.data.DataSource({
      
                  transport: {
                          type: "odata",
                          read: {
                              url: '/api/po',
                              type: 'get',
                          },
                          update: {
                              url: '/api/po',
                              dataType: "json",
                              type: "PUT",
                              contentType: "application/json"
                          },
                          create: {
                              url: "/api/po",
                              dataType: "json",
                              type: "POST",
                              contentType: "application/json"
                          },
                          parameterMap: function (options, operation) {
                                  if (operation !== "read") {
                                      debugger;
                                      return JSON.stringify(options);
      
                              }
                          }
                      },
                      pageSize: 5,
                      schema: {
                          model: {
                              id: "id",
                              fields: {
                                  id: { editable: false, nullable: true },
                                  po_number: { type: "string" },
                                  note: { type: "string" },
                                  valid_start: { type: "date" },
                                  valid_end: { type: "date" },
                                  po_lines : { editable: false, nullable: true}
                              }
                          }
      
      
                      },
                  });
          });
      

      homeController.js

      app.controller('homeController', function ($scope, $http, poDataSource, poLinesDataSource) {
      
          $scope.onChange = function (e) {
      
              $scope.showPoLines = true;
              var grid = e.sender;
              var selectedItem = grid.dataItem(grid.select());
              var selectedItemId = selectedItem.id;
      
              $http({
                  method: 'get',
                  url: 'api/polines/getlines',
                  params: { id: selectedItemId }
              })
                  .success(function (data) {
                      // new push new data to grid dataSource 
                      $('#PoLinesGrid').data('kendoGrid').dataSource.data(data);
                      var grid2 = $('#PoLinesGrid').data('kendoGrid');
                      grid2.dataSource.transport.options.create.url = "/api/polines/PostPO?=" + selectedItemId;
      
                  })
                  .error(function (data) {
                      console.log(data);
                  });
      
          };
          $scope.dataSource = poDataSource;
      
          $scope.gridColumns = [
                  { field: "id", title: "ID" },
                  { field: "po_number", title: "PO nr" },
                  { field: "valid_start", title: "Start date" },
                  { field: "valid_end", title: "End date" },
                  { field: "note", title: "Note" },
                  {
                      command: [{ template: "<button class='k-button' ng-click=''>PO lines</button>", }],
                      title: "PO lines"
                  },
                  { template: "<input type='text' ng-value='calculateTotal(dataItem)' />", title: "Total" },
                  {
                      command: [{ template: "<button class='k-button' ng-click='showDetails(dataItem)'>Show details</button>", }],
                      title: "Show details"
                  },
      
                  { command: ["edit", "destroy"], title: " " }
          ];
      
      
          $scope.dataSourceOfLines = poLinesDataSource;
      
          $scope.gridColumnsOfLines = [
                  { field: "id", title: "ID" },
                  { field: "total", title: "Total" },
                  { field: "note", title: "Note" },
                  { command: ["edit", "destroy"], title: " " }
          ];
      });
      

      Index.cshtml

      <kendo-grid id="#PoGrid" k-data-source="dataSource"
                  k-columns="gridColumns"
                  k-editable="'inline'"
                  k-toolbar="['create']"
                  k-sortable="true"
                  k-pageable="true"
                  k-resizeable="true"
                  k-on-change="onChange(kendoEvent)"
                  k-selectable="true">
      </kendo-grid>
      <div ng-show="showPoLines">
          <kendo-grid id="PoLinesGrid" k-data-source="dataSourceOfLines"
                      k-columns="gridColumnsOfLines"
                      k-editable="'inline'"
                      k-toolbar="['create']"
                      k-sortable="true"
                      k-pageable="true"
                      k-resizeable="true"
                      @*k-on-change="onChange(kendoEvent)"*@
                      k-selectable="true">
          </kendo-grid>
      </div>
      

      我希望解决这个问题也可以帮助其他人。我还要感谢帮助我找到这个答案的人。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-26
        • 1970-01-01
        • 1970-01-01
        • 2018-03-17
        • 1970-01-01
        相关资源
        最近更新 更多