Как связать модель в Kendo UI?

0

У меня проблемы с привязывающей моделью после создания действия с использованием пользовательского интерфейса Kendo с Angular.

После создания запроса в режиме отладки я успешно выполнил требуемый вызов действия в 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>();
        }
    }
}
  • 0
    Просто бросил взгляд, я обнаружил одну проблему, переменная 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"}]
  • 0
    @Vijai Разве это не значит, что id обнуляется: id: {editable: false, nullable: true}? Или вы имеете в виду что-то еще?
Показать ещё 1 комментарий
Теги:
asp.net-mvc
kendo-ui
model-binding

3 ответа

0
Лучший ответ

Предыдущие ответы помогают мне получить правильное представление об этой проблеме. Если batch задан как true он возвращает список элементов, это означает, что мне нужно повторно реализовать мой контроллер, чтобы он мог получить List<PO>.

Но здесь также есть и другая большая проблема. На самом деле этот контроллер возвращает не HTTP-ответ, но обратное представление и лучшее решение реализуют WEB API. Bassicaly Мне нужно было перепрограммировать программу.

Вот некоторые изменения

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>

Надеюсь, что решение этой проблемы может помочь и другим людям. Также я благодарю людей, которые помогают мне найти этот ответ.

2

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

0

После декодирования вашего 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 я могу видеть thare PO, поэтому он должен быть List<PO> или ваш код клиента должен быть изменен таким образом, что он должен отправить один объект.

что бы я вам посоветовал, вы также можете установить что-то под названием DatasourceRequest в аргументах, чтобы вы могли получать все параметры поддержки kendo.

подробнее о DatasourceRequest здесь и здесь

Ещё вопросы

Сообщество Overcoder
Наверх
Меню