我有一个非常特殊的问题,但却找不到任何可以帮我解决的问题。
我有一个表单,其中包含一堆文本框,下拉列表等,这些表单通过视图中附带的模型发回。但是我也有一个通过其中一个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; }
}
答案 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);
}