Как создать пакетную сетку пользовательского интерфейса Kendo, в которой используются объектные объекты на платформе CSLA

Я пытаюсь создать класс сущностей Super для сохраненных продуктов. В зависимости от того, где находится продукт в приложении, необходимы определенные дополнительные атрибуты (но не всегда).

Например, когда продукт используется в сетке, я хочу иметь ViewModel, производную от Entity (наследующую все общие поля), а затем добавить атрибут уникального идентификатора, такой как "rowNumber", для удобного поиска в пользовательском интерфейсе kendo. сетка CRUD.

Я думал, что у меня все это работает, но я наткнулся на загвоздку... Все отображается нормально и работает правильно, пока я не нажму "сохранить" для пакетной сетки. Он выполняет функцию и все данные присутствуют, но когда он возвращается из CRUD, он ломается. В firebug я вижу, что генерируется исключение, но оно никогда не завершается (вращатель ajax остается там), и вся информация в исключении пуста...

Я не уверен, если это какая-то проблема с C# не очень хорошо играть с CSLA или нет. Я не уверен

Любая помощь будет оценена! Я не могу загрузить изображения, потому что моя репутация недостаточно высока, иначе я бы поместил изображение исключения, но я, по крайней мере, добавлю то, что появляется в консоли Firebug. Все остальное об этом пусто, хотя...

Исключение с бесконечным выполнением и без ответа:

GET http://localhost:32574/Exception/SystemException/00000000-0000-0000-0000-000000000000

Entity: Этот файл автоматически генерируется шаблоном CodeSmith, поэтому он выглядит бессмысленным, но содержит значения полей, которые отображаются в представлении (см. Ниже). Исключением из того, что находится в представлении, по сравнению с тем, что находится в сущности, являются поля, которые не "сплющены" в сущности, так как пользовательский интерфейс Kendo в настоящее время не поддерживает это внутри редактируемых сеток.

ViewModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace Project.MVC.Models
{
    //The MetaData Class is where to put all annotations and validations
    [MetadataType(typeof(Project.Business.Shipment.ItemMetaDataClass))]
    public class ItemModel : Project.Business.Shipment.Item
    {
        public ItemModel()
        {
        }

        public long rowNumber { get; set; }

        public decimal Length { get; set; }
        public decimal Width { get; set; }
        public decimal Height { get; set; }

        [Display(Name = "UoMDim")]
        [UIHint("ItemGrid_RefUnitOfMeasurementListingDimension")]
        public string DimensionUnitOfMeasure { get; set; }

        [Display(Name = "UoMW")]
        [UIHint("ItemGrid_RefUnitOfMeasurementListingWeight")]
        public string WeightUnitOfMeasure { get; set; }

        [Display(Name = "Weight")]
        public decimal WeightValue { get; set; }

        [Display(Name = "Type")]
        [UIHint("ItemGrid_RefUnitTypeListing")]
        public string QuantityUnitOfMeasure { get; set; }

        [Display(Name = "Units")]
        public decimal QuantityValue { get; set; }
}
}

Grid Controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Kendo.Mvc.UI;
using Kendo.Mvc.Extensions;

namespace Project.MVC.Controllers
{
    [Authorize]
    public class ItemGridController : Csla.Web.Mvc.Controller
    {
        public ActionResult GetProducts([DataSourceRequest]DataSourceRequest request)
        {
            Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;

            return Json(shipmentModel.ItemModelList.ToDataSourceResult(request));
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult CreateProducts([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Models.ItemModel> itemsToAdd)
        {
            Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
            var results = new List<Models.ItemModel>();

            if (ModelState.IsValid)
            {
                foreach (Models.ItemModel newItem in itemsToAdd)
                {

                    if (shipmentModel.ItemModelList.Count > 0)
                    {
                        var nextID = (from i in shipmentModel.ItemModelList
                                      select i.rowNumber).Max() + 1;

                        newItem.rowNumber = nextID;
                    }

                    shipmentModel.ItemModelList.Add(newItem);
                    results.Add(newItem);
                }
            }

            return Json(results.ToDataSourceResult(request, ModelState));
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult UpdateProducts([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Models.ItemModel> itemsToUpdate)
        {
            Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
            var results = new List<Models.ItemModel>();

            foreach (var item in itemsToUpdate)
            {
                Models.ItemModel target = shipmentModel.ItemModelList.Find(i => i.rowNumber == item.rowNumber);
                if (target != null)
                {
                    target = item;
                }
            }

            return Json(ModelState.ToDataSourceResult());
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult DeleteProducts([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Models.ItemModel> itemsToDelete)
        {
            Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;

            foreach (var item in itemsToDelete)
            {
                shipmentModel.ItemModelList.Remove(item);
            }

            return Json(ModelState.ToDataSourceResult());
        }
    }
}

Посмотреть:

@model Project.MVC.Models.ShipmentModel
@using Kendo.Mvc.UI

@(Html.Kendo().Grid<Project.MVC.Models.ItemModel>()
    .Name("QuoteItemGrid")
    .Columns(columns =>
    {
        columns.Bound(i => i.FreightClass)
            .EditorTemplateName("ItemGrid_RefFreightClassListing")
            .Width(50);
        columns.Bound(i => i.Length).Width(30);
        columns.Bound(i => i.Width).Width(30);
        columns.Bound(i => i.Height).Width(30);
        columns.Bound(i => i.DimensionUnitOfMeasure)
            .EditorTemplateName("ItemGrid_RefUnitOfMeasurementListingDimension")
            .Width(50);
        columns.Bound(i => i.QuantityValue).Width(30);
        columns.Bound(i => i.QuantityUnitOfMeasure)
            .EditorTemplateName("ItemGrid_RefUnitTypeListing")
            .Width(50);
        columns.Bound(i => i.WeightValue).Width(30);
        columns.Bound(i => i.WeightUnitOfMeasure)
            .EditorTemplateName("ItemGrid_RefUnitOfMeasurementListingWeight")
            .Width(50);
        columns.Bound(i => i.NmfcCode).Width(50);
        columns.Bound(i => i.ItemDescription).Width(100);
        columns.Command(command =>
        {
            command.Destroy();
        }).Width(60);
    })
    .ToolBar(toolbar =>
    {
        toolbar.Create();
        toolbar.Save();
    })
    .Editable(editable => editable.Mode(GridEditMode.InCell).CreateAt(GridInsertRowPosition.Bottom))
    .Pageable()
    .Sortable()
    .Scrollable()
    .Resizable(resize => resize.Columns(true))
    .DataSource(dataSource => dataSource
        .Ajax()
        .Batch(true)
        .ServerOperation(false)
        .Events(events => events.Error("QuoteItemGrid_ErrorHandler"))
        .Model(model =>
        {
            model.Id(i => i.rowNumber);
            model.Field(i => i.DimensionUnitOfMeasure).DefaultValue("in");
            model.Field(i => i.WeightUnitOfMeasure).DefaultValue("lbs");
        })
        .Create(create => create.Action("CreateProducts", "ItemGrid"))
        .Read(read => read.Action("GetProducts", "ItemGrid"))
        .Update(update => update.Action("UpdateProducts", "ItemGrid"))
        .Destroy(destroy => destroy.Action("DeleteProducts", "ItemGrid"))
    )
)

2 ответа

Решение

С архитектурной точки зрения моя группа, в конечном счете, посчитала неразумным связывать объекты, созданные в нашей базе данных, так близко к нашему представлению. Особенно сейчас, когда проект используется в нескольких местах (приложение.Net, приложение Webservices и т. Д.).

Итак, в итоге мы создали ViewModels для каждой сущности, чтобы мы могли быть гибкими с нашими сущностями на разных платформах. Эта реструктуризация устранила проблему, описанную выше, поскольку объекты теперь никогда не присутствуют в представлении.

Однако, предостережение: если вы используете Kendo UI, вам придется "сгладить" модели представлений, которые вы хотите представить в единственном компоненте, который представляет собой глубокие объекты (например, объект внутри другого объекта). На данный момент Кендо не поддерживает это. Мы используем ValueInjecter.

Надеюсь, эта информация поможет кому-то еще.

Я полностью согласен. В идеале ваши объекты на основе CSLA .NET являются объектами домена, а не объектами данных, и поэтому соответствуют форме, необходимой бизнес-требованиям, а не таблицам базы данных или запросам.

К сожалению, многие люди в конечном итоге (неправильно) используют CSLA, как ORM, и поэтому имеют объекты, ориентированные на данные, поэтому упускают значительную часть инфраструктуры и требуют создания и обслуживания слишком сложных типов моделей представления в дополнение к чему (должны были) виды бизнеса.

Другие вопросы по тегам