0

我是客户端-服务器、SQL 程序员(RAD 人),公司决定我们必须迁移到 .NET 环境。我们现在正在检查平台。

这周我学习了 MVC4 和实体框架,并且阅读了很多关于 KendoUI 的内容。我持怀疑态度,因为大多数示例都带有 KendoGrid+WebApi。我对 WebApi 知之甚少,但我真的很喜欢实体的东西,所以我认为我不应该给它一个机会。

我想问一些看似幼稚但答案对我有很大帮助的问题

  1. 一旦我从现有数据库创建实体,我可以得到 Json 格式的结果并用它来提供 KendoGrid 吗?

    如果是,如何?我是说:

  2. 如何在 Controller 中转换 Json 中的结果?

  3. 在 KendoGrid 的传输属性中,我应该放置控制器/动作的 URL?

    和最天真的一个

  4. Telerik 是否有提供可视化工具来创建和配置 kendoGrid 的想法?让它更RAD,因为现在需要太多的编码。也许是一个向导,您可以将实体与网格列、数据源、传输选择器等连接起来。

4

2 回答 2

3

我希望你选择剑道实体路径,但会有一个学习曲线。不,关于第 4 个问题。但让我让您快速开始使用 Razor 视图引擎并回答 1、2 和 3。

首先,EF 正在创建业务对象。您“应该”将这些转换为 MVC 中的模型。在此示例中,Person 来自 EF。我认为这是扁平化的,因为它消除了对象的深度,尽管它仍然可用,所以如果你的数据库是这样设置的,你可以引用 Person.Titles.Name 之类的东西。你也可以加入 DataAnnotations,它只是摇滚。

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Project.Business;

namespace Project.Web.Models
{
    public class PersonModel
    {
        public int Id { get; set; }
        [Required(ErrorMessage = "Last Name is required.")]
        public string LastName { get; set; }
        [Required(ErrorMessage = "First Name is required.")]
        public string FirstName { get; set; }
        [Display(Name = "Created")]
        public System.DateTime StampCreated { get; set; }
        [Display(Name = "Updated")]
        public System.DateTime StampUpdated { get; set; }
        [Display(Name = "Enabled")]
        public bool IsActive { get; set; }

        public PersonModel()
        {}
        public PersonModel(Person person)
        {
            Id = person.Id;
            FirstName = person.FirstName;
            LastName = person.LastName;
            StampCreated = person.StampCreated;
            StampUpdated = person.StampUpdated;
            IsActive = person.IsActive;
        }

        public static IList<PersonModel> FlattenToThis(IList<Person> people)
        {
            return people.Select(person => new PersonModel(person)).ToList();
        }

    }
}

一路走来...

@(Html.Kendo().Grid<PersonModel>()
    .Name("PersonGrid")
    .Columns(columns => {
        columns.Bound(b => b.Id).Hidden();
        columns.Bound(b => b.LastName).EditorTemplateName("_TextBox50");
        columns.Bound(b => b.FirstName).EditorTemplateName("_TextBox50");
        columns.Bound(b => b.StampUpdated);
        columns.Bound(b => b.StampCreated);
        columns.Bound(b => b.IsActive).ClientTemplate("<input type='checkbox' ${ IsActive == true ? checked='checked' : ''} disabled />").Width(60);
            columns.Command(cmd => { cmd.Edit(); cmd.Destroy(); }).Width(180);
        })
    .ToolBar(toolbar => toolbar.Create())
    .Pageable()
    .Filterable()
    .Sortable()
    .Selectable()
    .Editable(editable => editable.Mode(GridEditMode.InLine))
    .DataSource(dataSource => dataSource
        .Ajax()
        .Events(events => events.Error("error_handler"))
        .Model(model =>
            {
                model.Id(a => a.Id);
                model.Field(a => a.StampCreated).Editable(false);
                model.Field(a => a.StampUpdated).Editable(false);
                model.Field(a => a.IsActive).DefaultValue(true);
            })
        .Create(create => create.Action("CreatePerson", "People"))
        .Read(read => read.Action("ReadPeople", "People"))
        .Update(update => update.Action("UpdatePerson", "People"))
        .Destroy(destroy => destroy.Action("DestroyPerson", "People"))
        .PageSize(10)
    )
)

那些 _TextBox50 是名为 _TextBox50.cshtml 的 EditorTemplates,必须放在相对于您的视图或相对于您的共享文件夹的子文件夹中 - 该文件夹必须称为 EditorTemplates。这个好像是这样的……

@Html.TextBox(string.Empty, string.Empty, new { @class = "k-textbox", @maxlength = "50" })

是的,仅此而已。这是一个简单的例子,它们可以变得更复杂。或者您最初不必使用它们。

最后,我认为你真正在寻找什么......

public partial class PeopleController : Controller
{
    private readonly IPersonDataProvider _personDataProvider;

    public PeopleController() : this(new PersonDataProvider())
    {}
    public PeopleController(IPersonDataProvider personDataProvider)
    {
        _personDataProvider = personDataProvider;
    }

    public ActionResult Manage()
    {
>>> Left in as teaser, good to apply a special Model to a View to pass goodies ;)
        var model = new PeopleViewModel();
        model.AllQualifications = QualificationModel.FlattenToThis(_qualificationDataProvider.Read());
        return View(model);
    }

    [HttpPost]
    public JsonResult CreatePerson([DataSourceRequest]DataSourceRequest request, Person person)
    {
        if (ModelState.IsValid)
        {
            try
            {
                person = _personDataProvider.Create(person);
            }
            catch (Exception e)
            {
                ModelState.AddModelError(string.Empty, e.InnerException.Message);
            }
        }
        var persons = new List<Person> {person};
        DataSourceResult result = PersonModel.FlattenToThis(persons).ToDataSourceResult(request, ModelState);
        return Json(result, JsonRequestBehavior.AllowGet);
    }

    public JsonResult ReadPeople([DataSourceRequest]DataSourceRequest request)
    {
        var persons = _personDataProvider.Read(false);
        DataSourceResult result = PersonModel.FlattenToThis(persons).ToDataSourceResult(request);
        return Json(result, JsonRequestBehavior.AllowGet);
    }

    [HttpPost]
    public JsonResult UpdatePerson([DataSourceRequest]DataSourceRequest request, Person person)
    {
        if (ModelState.IsValid)
        {
            try
            {
                person = _personDataProvider.Update(person);
            }
            catch (Exception e)
            {
                ModelState.AddModelError(string.Empty, e.InnerException.Message);
            }
        }
        var persons = new List<Person>() {person};
        DataSourceResult result = PersonModel.FlattenToThis(persons).ToDataSourceResult(request, ModelState);
        return Json(result, JsonRequestBehavior.AllowGet);
    }

    [HttpPost]
    public JsonResult DestroyPerson([DataSourceRequest]DataSourceRequest request, Person person)
    {
        if (ModelState.IsValid)
        {
            try
            {
                person = _personDataProvider.Destroy(person);
            }
            catch (Exception e)
            {
                ModelState.AddModelError(string.Empty, "There was an error deleting this record, it may still be in use.");
            }
        }
        var persons = new List<Person>() {person};
        DataSourceResult result = PersonModel.FlattenToThis(persons).ToDataSourceResult(request, ModelState);
        return Json(result, JsonRequestBehavior.AllowGet);
    }
}

请注意,在这种情况下,每个方法都将 EF Person 作为参数,使用 PersonModel 会更好,但我将不得不展示 Flatten 的反面。这是有效的,因为它们实际上是相同的。如果模型不同,或者您使用的是类工厂,它会变得更加棘手。

我特意向你展示了所有的 CRUD 操作。如果您不将结果传递回网格,它会表现得很有趣并给您重复或无法在 CREATE 和 UPDATE 上正确显示更新。它在 DELETE 上传回以传递可能有任何错误的 ModelState。

最后是数据提供者,以免留下任何想象......(省略了命名空间声明。)

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using Project.Business;

public class PersonDataProvider : ProviderBase, IPersonDataProvider
{
    public Person Create(Person person)
    {
        try
        {
            person.StampCreated = DateTime.Now;
            person.StampUpdated = DateTime.Now;

            Context.People.Attach(person);
            Context.Entry(person).State = EntityState.Added;
            Context.SaveChanges();
            return person;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.Message);
            throw;
        }
    }

    public IList<Person> Read(bool showAll)
    {
        try
        {
            return (from q in Context.People
                      orderby q.LastName, q.FirstName, q.StampCreated
                      where (q.IsActive == true || showAll)
                      select q).ToList();
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.Message);
            throw;
        }
    }

...

}

请注意 Interface 和 ProviderBase 继承,您必须进行这些继承。应该足够简单以找到示例。

这可能看起来像很多编码,但一旦你把它写下来,只需复制粘贴。

快乐编码。

于 2013-01-06T01:07:22.173 回答
0

是的,您可以使用 JsonResult 或使用指定了允许获取的 JSON 将 JSON 发送回剑道 UI。您可以在传输中设置 url 并将 json 指定为类型。

关于你的最后一个问题,目前没有可视化工具,但有可用于 kendo UI 的辅助方法

于 2013-01-02T14:27:10.720 回答