通过Telerik:表格 - 动作(MVC)上的网格数据

时间:2015-09-16 07:04:54

标签: ajax asp.net-mvc telerik

我有一个非常特殊的问题,但却找不到任何可以帮我解决的问题。

我有一个表单,其中包含一堆文本框,下拉列表等,这些表单通过视图中附带的模型发回。但是我也有一个通过其中一个DropDownLists动态填充的Grid。我想将整个网格解析回窗体控制器,但我不知道如何做到这一点。

ajax-post不起作用,因为我无法访问实际模型。我唯一能做的就是发布控件值本身,但这种方法有些混乱。

模型本身有一个变量" Mappings"属于IEnumerable类型。这是我也绑定到网格的类型。所以应该有办法以某种方式将网格内的映射添加到模型中。我认为如果我将网格命名为主模型中的属性名称(" Mappings"),它可能会自动运行,但这并不起作用。所以我又回到原点。

也许你们有一个想法如何解决我的问题,因为我有点想法。

查看:

@using (Html.BeginForm("Save", "Profile", FormMethod.Post, new { Id = "addProfileForm", novalidate = "false" }))
    {   
            <ul id="progressbar">
                    <li class="active">Grundeinstellungen</li>
                    <li>CRM-Einstellungen</li>
                    <li>Mapping anlegen</li>
            </ul>
            <fieldset>
                <h2 class="fs-title">Grundinformationen</h2>
                @Html.LabelFor(model => model.Name, new { @class = "label req" })
                @Html.TextBoxFor(model => model.Name, new { @class = "input" })
                @Html.LabelFor(model => model.Description, new { @class = "label" })
                @Html.TextAreaFor(model => model.Description, new { @class = "input", rows = "3", cols = "25" })
                @Html.LabelFor(model => model.UserGroupId, new { @class = "label req" })
                @(Html.Kendo().DropDownListFor(model => model.UserGroupId)
                    .OptionLabel("Bitte auswählen... ")
                    .BindTo(Model.UserGroupList)
                )
                <input type="button" name="next" class="next action-button" value="Weiter" style="display:block"/>
            </fieldset>
            <fieldset>
                <h2 class="fs-title">CRM-Einstellungen</h2>
                @Html.LabelFor(model => model.OrdnungsbegriffTypeId, new { @class = "label req" })
                @(Html.Kendo().DropDownListFor(model => model.OrdnungsbegriffTypeId)
                    .OptionLabel("Bitte auswählen...")
                    .BindTo(Model.OrdnungsbegriffTypeList)
                )
                @Html.LabelFor(model => model.CrmTypeId, new { @class = "label req" })
                @(Html.Kendo().DropDownListFor(model => Model.CrmTypeId)
                    .Name("CrmTypeId")
                    .OptionLabel("Bitte auswählen...")
                    .BindTo(Model.CrmTypeList)
                    .Events(e =>
                        e.Select("onCrmTypeSelect"))
                )
                <br />
                <input type="button" name="previous" class="previous action-button" value="Zurueck" />
                <input type="button" name="next" class="next action-button" value="Weiter" />
            </fieldset>

            <fieldset>
                <h2 class="fs-title">Mapping anlegen</h2>
                @(Html.Kendo().Upload()
                    .Name("upMappingFile")
                    .Multiple(false)
                    .ShowFileList(true)
                    .TemplateId("fuCsvTemplate")
                    .Async(a => a
                        .AutoUpload(true)
                        .Save("SaveFile", "Mapping")
                        .Remove("RemoveFile", "Mapping")
                    )
                    .Enable(false)
                    .Events(e => e
                        .Success("onSuccess"))
                    .Messages(m => m
                        .Select("Durchsuchen...")
                        .HeaderStatusUploading("Uploading...")
                        .HeaderStatusUploaded("Fertig"))
                )
                <div id="gridContainer">
                </div>
                <div id="appendTo" class="k-block"></div>
                <input type="button" name="previous" class="previous action-button" value="Zurueck" />
                <input type="submit" name="submit" class="submit action-button" value="Speichern"/>
    </fieldset>
        @Html.Kendo().Notification().Name("crmTypeNotification")
    }

用于动态创建网格的Ajax-Post:

function onSuccess(e) {
    var gridNotification = $("#gridNotification").data("kendoNotification");
    var crmType = $("#CrmTypeId").data("kendoDropDownList");
    var csvHeadRow = e.response.csvHeadRow
    var url = '@Url.Action(MVC.Mapping.ReturnMappingGrid())';
        $.ajax({
            type: "POST",
            url: url,
            data: JSON.stringify({ csvHead: csvHeadRow, crmType: crmType.text() }),
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (data) {
                $('#gridContainer').html(data);
                gridNotification.show("Die Auswahl der jeweiligen Eigenschaft erfolgt durch Klicken des jeweiligen Eigenschaft-Felds!")
                var container = $(gridNotification.options.appendTo);

            },
            error: function (xmlHttpRequest, textStatus, errorThrown) {
                debugger;
                console.log(xmlHttpRequest.responseText);
                console.log(textStatus);
                console.log(errorThrown);
            },
            async: false
        });
    }

部分视图网格:

    @(Html.Kendo().Grid<DAKCrmImportModel.Model.Entities.Base.CrmMapping>().Name("Mappings").BindTo(Model)
        .Columns(c =>
            {
                c.Bound(m => m.CsvColumn).Title("Spalte").Width(300);
                c.Bound(m => m.CrmProperty).EditorTemplateName("PropertyId");
            })
        .Editable(editable => editable.Mode(GridEditMode.InCell))
        .DataSource(dataSource => dataSource
            .Ajax()
            .Batch(true)
            .PageSize(20)
            .ServerOperation(false)
            .Model(m => 
                {
                    m.Id(ma => ma.Id);
                    m.Field(ma => ma.Id).Editable(false);
                })
        )
    )

CrmProfile-model:

    public class CrmProfile
        {


        public CrmProfile()
        {
            this.Mappings = new HashSet<CrmMapping>();
            this.Jobs = new HashSet<CrmJob>();
        }

        [Column(Order = 1)]
        [Key]
        public int Id { get; set; }

        [Required]
        [Display(Name = "Bezeichnung")]
        public string Name { get; set; }

        [Display(Name = "Beschreibung")]
        public string Description { get; set; }

        [Required]
        public string CreatedBy { get; set; }

        [Column(Order = 2)]
        [ForeignKey("UserGroup")]
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)]
        [Required]
        [Display(Name = "Usergruppe")]
        public int UserGroupId { get; set; }
        public UserGroup UserGroup { get; set; }

        [Column(Order = 3)]
        [ForeignKey("CrmType")]
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)]
        [Required]
        [Display(Name = "Einspielungstyp")]
        public int CrmTypeId { get; set; }
        public CrmImportType CrmType { get; set; }

        [Column(Order = 4)]
        [ForeignKey("OrdnungsbegriffType")]
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)]
        [Required]
        [Display(Name = "Ordnungsbegrifftyp")]
        public int OrdnungsbegriffTypeId { get; set; }
        public OrdnungsbegriffType OrdnungsbegriffType { get; set; }

        public byte[] SourceFile { get; set; }
        public string SourceFileName { get; set; }
        public string[] SourceFileHeadRow { get; set; }

        [Required]
        public DateTime CreatedAt { get; set; }

        public string LastUpdatedBy { get; set; }

        public DateTime? LastUpdatedAt { get; set; }

        public DateTime? LastUsedAt { get; set; }

        public ICollection<CrmMapping> Mappings { get; set; }
        public ICollection<CrmJob> Jobs { get; set; }

        [NotMapped]
        public IEnumerable<SelectListItem> UserGroupList { get; set; }
        [NotMapped]
        public IEnumerable<SelectListItem> CrmTypeList { get; set; }
        [NotMapped]
        public IEnumerable<SelectListItem> OrdnungsbegriffTypeList { get; set; }
    }

CrmMapping-model:

公共类CrmMapping     {

    [Key]
    [Column(Order = 0)]
    public int Id { get; set; }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)]
    [ForeignKey("Profile")]
    public int ProfileId { get; set; }

    public CrmProfile Profile { get; set; }

    [Required]
    public string CrmProperty { get; set;}

    [Required]
    public string CsvColumn { get; set; }

    [Required]
    public int CsvIndex { get; set; }

    [UIHint("PropertyId")]
    [NotMapped]
    public int PropertyId { get; set; }
    [NotMapped]
    public IEnumerable<CrmProperty> CrmProperties { get; set; }
}

[UPDATE] 我想用ajax发回网格数据,但我似乎没有在服务器端获得正确的数据类型。

function postProfileData() {
    var url = '/Profile/Save';
    $.ajax({
        type: "POST",
        url: url,
        data: $("#addProfileForm").serialize() + "&Mappings=" + getMappings(),
        success: function (data) {
            debugger;

        },
        error: function (xmlHttpRequest, textStatus, errorThrown) {
            debugger;
            console.log(xmlHttpRequest.responseText);
            console.log(textStatus);
            console.log(errorThrown);
        },
        async: false
    });
}

function getMappings() {
    var grid = $("#Mappings").data("kendoGrid");
    debugger;
    return grid._data;
}



[HttpPost]
public virtual ActionResult Save(CrmProfile crmProfile, List<CrmMapping> Mappings)
{
        using (DAKCrmImportContext db = new DAKCrmImportContext())
        {

            crmProfile.CreatedAt = DateTime.Now;
            crmProfile.CreatedBy = System.Web.HttpContext.Current.User.Identity.Name.Split('\\')[1];
            try
            {
                db.CrmProfiles.Add(crmProfile);
                db.SaveChanges();
            }
            catch (DbEntityValidationException e)
            {
                var vals = e.EntityValidationErrors;
                throw;
            }


        }

        return RedirectToAction("Add", "Mapping", crmProfile);
}

[UPDATE2]所以问题很可能是JavaScript不喜欢我的Listtype(CrmMapping)并且不知道如何处理它。我不太清楚为什么,但我认为它的结构并不适合普通的id:value对。也许问题是Id在所有ListItem中都是0并且我必须手动填充它,但是CrmMapping实际上是一个模型类,所以我必须将它设置回0最终所以我&#39; d可能必须创建一个ViewModel来解析网格数据。

公共类CrmMapping {

[Key]
[Column(Order = 0)]
public int Id { get; set; }

[Key]
[Column(Order = 1)]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)]
[ForeignKey("Profile")]
public int ProfileId { get; set; }

public CrmProfile Profile { get; set; }

[Required]
public string CrmProperty { get; set;}

[Required]
public string CsvColumn { get; set; }

[Required]
public int CsvIndex { get; set; }

[UIHint("PropertyId")]
[NotMapped]
public int PropertyId { get; set; }
[NotMapped]
public IEnumerable<CrmProperty> CrmProperties { get; set; }

}

2 个答案:

答案 0 :(得分:1)

由于你是从@model创建网格而不是使用datasource.Read的ajax调用,你可以使用for循环创建隐藏的输入,只要它们在form标签中就会发布回来。

这样的东西
@(Html.Kendo().Grid<DAKCrmImportModel.Model.Entities.Base.CrmMapping>().Name("Mappings").BindTo(Model)
        .Columns(c =>
        {
            c.Bound(m => m.CsvColumn).Title("Spalte").Width(300);
            c.Bound(m => m.CrmProperty).EditorTemplateName("PropertyId");
        })
        .Editable(editable => editable.Mode(GridEditMode.InCell))
        .DataSource(dataSource => dataSource
            .Ajax()
            .Batch(true)
            .PageSize(20)
            .ServerOperation(false)
            .Model(m =>
            {
                m.Id(ma => ma.Id);
                m.Field(ma => ma.Id).Editable(false);
            })
        )
)

@for (int i = 0; i < Model.Count; i++)
{
    @Html.Hidden("Mappings[" + i.ToString() + "].Id", Model[i].Id)
    @Html.Hidden("Mappings[" + i.ToString() + "].CsvColumn", Model[i].CsvColumn)
    @Html.Hidden("Mappings[" + i.ToString() + "].CrmProperty", Model[i].CrmProperty)
}

如果您编辑任何列,则不会使用此方法回发新值,因此如果您希望能够维护,则应该将ajax数据源事件连接到读取,创建,编辑和删除网格数据正确

答案 1 :(得分:0)

好的,在尝试了很多东西之后我终于找到了解决方案。要做到这一点,我需要一个javscript-expension:

$.fn.serializeObject = function () {
    var o = {};
    var a = this.serializeArray();
    $.each(a, function () {
        if (o[this.name]) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

将表单序列化为对象而不是发布表单本身需要这样做。

接下来我们要做的是创建一个ViewModel,它具有我们想要提交/发布的表单模型的属性以及我们想要进入控制器操作的其他数据。

using DAKCrmImportModel.Model.Entities.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace DAKCrmImport.Models
{
    public class CrmProfileAddVM
    {
        public CrmProfile Profile { get; set; }
        public CrmMapping[] Mappings { get; set; }
    }
}

我们必须在这里声明CrmMapping为Array,因为这是Telerik网格使用的数据类型。

现在让我们使用form-data(Profile)和grid._data(Mappings)来创建包含ViewModel的ajax函数。

function postProfileData() {
        var url = '@Url.Action(MVC.Profile.Save())';
        $.ajax({
            type: "POST",
            url: url,
            //.serialize()
            //data: $("#addProfileForm").serialize(), "crmMappingList": getMappings(),
            contentType: 'application/json',
            data: JSON.stringify({
                Profile: $("form#addProfileForm").serializeObject(),
                Mappings: getMappings()
            }),
            //data: { Mappings: getMappings() },
            success: function (data) {
                debugger;

            },
            error: function (xmlHttpRequest, textStatus, errorThrown) {
                debugger;
                console.log(xmlHttpRequest.responseText);
                console.log(textStatus);
                console.log(errorThrown);
            },
            async: false
        });
    }

    function getMappings() {
        var grid = $("#Mappings").data("kendoGrid");

        return grid._data;
    }

最后,我们要做的最后一件事是更改controller-Action Parameter,以便我们可以访问ViewModel的实例。

        [HttpPost]
        public virtual ActionResult Save(CrmProfileAddVM model)
        {
                using (DAKCrmImportContext db = new DAKCrmImportContext())
                {

                    //crmProfile.CreatedAt = DateTime.Now;
                    //crmProfile.CreatedBy = System.Web.HttpContext.Current.User.Identity.Name.Split('\\')[1];
                    //try
                    //{
                    //    db.CrmProfiles.Add(crmProfile);
                    //    db.SaveChanges();
                    //}
                    //catch (DbEntityValidationException e)
                    //{
                    //    var vals = e.EntityValidationErrors;
                    //    throw;
                    //}


                }

                return RedirectToAction("Add", "Mapping", null);
        }