表单反序列化不起作用



我有一个异步的httpPost,它序列化我的表单数据并将其提交到我的控制器。在那里,我尝试将表单数据序列化到我的视图模型类中,但所有值均为 null 或分配了默认值。

public ActionResult GetSalesData(string vmString)
{
-serialization...
-use the data to select some other data
return new JsonResult { Data = d, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}

对于序列化,到目前为止,我尝试了以下两种方法:

1.)

{ vmString: $('form').serialize() }

结果:

Dataset.Ids=3,7,12&Type=Sales&DataSources=BeverageType&DisplayModes=Volume&SeriesTypes=Lines&SalesVm.DisplayOptions.ShowAverage=false&SalesVm.DisplayOptions.ShowTargetLine=false&ActionName=Sales_SelectBeverageTypes&Mode=LightboxInWizard&SelectedDatasetIdsWorkingCopy=3&SearchTerm=

2.)

{ vmString: JSON.stringify($('form')) }

结果:

{"length":2,"prevObject":{"0":{"jQuery1710039964356962994385":1,"location":{}},"context":{"jQuery1710039964356962994385":1,"location":{}},"length":1},"context":{"jQuery1710039964356962994385":1,"location":{}},"selector":"form","0":{"Dataset.Ids":{},"Type":{},"DataSources":{"jQuery1710039964356962994385":15},"3":{"jQuery1710039964356962994385":16},"DisplayModes":{"0":{"jQuery1710039964356962994385":42},"1":{"jQuery1710039964356962994385":43},"2":{"jQuery1710039964356962994385":44},"3":{"jQuery1710039964356962994385":45}},"SeriesTypes":{"0":{"jQuery1710039964356962994385":46},"1":{"jQuery1710039964356962994385":47}},"SalesVm.DisplayOptions.ShowAverage":{"0":{"jQuery1710039964356962994385":48},"1":{"jQuery1710039964356962994385":49}},"SalesVm.DisplayOptions.ShowTargetLine":{"0":{"jQuery1710039964356962994385":50},"1":{"jQuery1710039964356962994385":51}}},"1":{"ActionName":{},"Mode":{},"SelectedDatasetIdsWorkingCopy":{},"SearchTerm":{"jQuery1710039964356962994385":35}}}

为了反序列化,我尝试了:

m = (StatisticsViewerViewModel)new JsonSerializer().Deserialize(new System.IO.StringReader(vmString), typeof(StatisticsViewerViewModel));
m = (StatisticsViewerViewModel)new JsonSerializer().Deserialize(new System.IO.StringReader(vmString), vmString.GetType());
m = JsonConvert.DeserializeObject<StatisticsViewerViewModel>(vmString);
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(StatisticsViewerViewModel)); 
m = (StatisticsViewerViewModel) ser.ReadObject(stream);

我检查了我的所有字段是否都在表单中:

@using (Html.BeginForm())
{
some partial views containing some fields, all using the same model..
}

我还检查了使用的视图模型以及所有嵌套模型是否确实有一个空的构造函数。

是否有不同的方法来反序列化表单数据?我还能检查什么以确保一切正常?

  • 编辑-

视图模型根:

public class StatisticsViewerViewModel
{
public String BreadcrumbName { get; set; }
public String ActionName { get; set; }
public StatisticsType Type { get; set; }
public DropDownListModel DataSourceList { get; set; }
public MultiSelectionModel Dataset { get; set; }
public SalesViewModel SalesVm { get; set; }
//public EventsViewModel EventsVm { get; set; }
public ChartExportOptions ExportOptions { get; set; }
public StatisticsViewerViewModel()
{
DataSourceList = new DropDownListModel();
Dataset = new MultiSelectionModel();
SalesVm = new SalesViewModel();
ExportOptions = new ChartExportOptions();
}
public enum StatisticsType
{
Sales,
Events
}
}

嵌套视图模型

public class SalesViewModel
{
public SalesDisplayOptions DisplayOptions { get; set; }
public RadioButtonModel DisplayModes { get; set; }      // Volume, Value, ..
public RadioButtonModel SeriesTypes { get; set; }       // Line, Bar, ..
public SalesViewModel(bool initialize = false)
{
if (initialize) { Initialize(); }
}
}
public class SalesDisplayOptions
{
public DisplayMode Mode { get; set; }
public SeriesType Type { get; set; }
public bool ShowAverage { get; set; }
public bool ShowTargetLine { get; set; }
public enum SeriesType
{
Lines, ...
}
public enum DisplayMode
{
Value, ...
}
}

一个相关的点可能是该帖子是由 kendoChart 触发的。这是视图中有趣的块:

....
<div id="chart"></div>
....
@this.ScriptBlock(
@<script type="text/javascript">
$("#chart").kendoChart({
dataSource: new kendo.data.DataSource({
transport: {
read: {
url: actionUrl,
data: { vmString: $('form').serialize() },
dataType: "json",
contentType: "application/json; charset=utf-8"
}
},
sort: ...
....

为了检查问题是否与 kendoChart-Object 有关,我测试性地实现了手动 POST:

....
<div class="round-corner-bottom-right">
<button id="send-form" type="button">
<span class="button-label">Send Form Data</span>
</button>
</div>
....
@this.ScriptBlock(
@<script type="text/javascript">
$('document').ready(function () {
$('#send-form').on('click', function () {
var data = $('form').serialize();
$.ajax({
type: "POST",
url: actionUrl,
data: data,
cache: false,
success: function (returnData) {
}
});
}); // document ready

在这种情况下,问题不会持续存在,所有值都按预期设置。所以kendoChart-methode似乎有问题。

您是否厌倦了使用允许默认模型绑定器来处理它,而不是尝试自己反序列化和管理它?

所以

public ActionResult GetSalesData(string vmString)

变成这个

public ActionResult GetSalesData(MyModel vmString)

根据我的经验,将复杂的 JS 对象传递给 Asp.net 控制器操作并将数据序列化为视图模型的唯一简单方法是首先在 JS 端预先格式化对象。

本页介绍了该方法: http://erraticdev.blogspot.com/2010/12/sending-complex-json-objects-to-aspnet.html

要预先格式化数据,您可以执行以下操作:

$.post(URL, $.toDictionary({ ... }), function(response) { ... });

以下是jQuery.toDictionary插件的缩小源代码:

/*!
* jQuery toDictionary() plugin
*
* Version 1.2 (11 Apr 2011)
*
* Copyright (c) 2011 Robert Koritnik
* Licensed under the terms of the MIT license
* http://www.opensource.org/licenses/mit-license.php
*/
(function (a) { if (a.isFunction(String.prototype.format) === false) { String.prototype.format = function () { var a = this; var b = arguments.length; while (b--) { a = a.replace(new RegExp("\{" + b + "\}", "gim"), arguments[b]) } return a } } if (a.isFunction(Date.prototype.toISOString) === false) { Date.prototype.toISOString = function () { var a = function (a, b) { a = a.toString(); for (var c = a.length; c < b; c++) { a = "0" + a } return a }; var b = this; return "{0}-{1}-{2}T{3}:{4}:{5}.{6}Z".format(b.getUTCFullYear(), a(b.getUTCMonth() + 1, 2), a(b.getUTCDate(), 2), a(b.getUTCHours(), 2), a(b.getUTCMinutes(), 2), a(b.getUTCSeconds(), 2), a(b.getUTCMilliseconds(), 3)) } } var b = function (c, d, e, f) { if (a.isPlainObject(c)) { for (var g in c) { if (f === true || typeof c[g] !== "undefined" && c[g] !== null) { b(c[g], d, e.length > 0 ? e + "." + g : g, f) } } } else { if (a.isArray(c)) { a.each(c, function (a, c) { b(c, d, "{0}[{1}]".format(e, a)) }); return } if (!a.isFunction(c)) { if (c instanceof Date) { d.push({ name: e, value: c.toISOString() }) } else { var h = typeof c; switch (h) { case "boolean": case "number": h = c; break; case "object": if (f !== true) { return }; default: h = c || "" } d.push({ name: e, value: h }) } } } }; a.extend({ toDictionary: function (c, d, e) { c = a.isFunction(c) ? c.call() : c; if (arguments.length === 2 && typeof d === "boolean") { e = d; d = "" } e = typeof e === "boolean" ? e : false; var f = []; b(c, f, d || "", e); return f } }) })(jQuery)

问题不在于反序列化先验本身,而在于数据在 kendoChart 数据源中的绑定方式。 该问题的解决方案是将一个带有 Ajax POST 的函数指定为数据源,如下所示:

var data = $('form').serialize();
$("#chart").kendoChart({
title: {
text: "Solution"
},
dataSource: new kendo.data.DataSource({
transport: {
read: function (options){
$.ajax({
url: actionUrl,
data: data,
type: "POST",
cache: false,
success: function (result) {
options.success(result);
}
});
}
},
....

很抱歉用错误的问题打扰您!

最新更新