2

フォーム データをシリアル化し、コントローラーにコミットする非同期の httpPost があります。そこで、ビュー モデル クラスにシリアル化されたフォーム データを取得しようとしましたが、すべての値が null であるか、デフォルト値が割り当てられています。

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

シリアライゼーションについては、これまでに次の 2 つの方法を試しました。

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..
}

また、使用されているビュー モデルと入れ子になったすべてのモデルに空のコンストラクターがあることも確認しました。

フォーム データをデシリアライズ/シリアル化するさまざまな方法はありますか? また、すべてが正常であることを確認するために、他に何を確認できますか?

  • 編集 -

ViewModel-ルート:

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
    }
}

ネストされた ViewModel

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 オブジェクトに関連しているかどうかを確認するために、手動 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 方式に問題があるようです。

4

3 に答える 3

1

自分でデシリアライズして管理するのではなく、デフォルトのモデル バインダーに処理させることにうんざりしていませんか?

そう

public ActionResult GetSalesData(string vmString)

これになる

public ActionResult GetSalesData(MyModel vmString)
于 2012-10-15T16:06:06.867 に答える
0

私の経験では、複雑な 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)
于 2012-10-15T17:26:09.903 に答える
0

問題はデシリアライゼーションの手順そのものではなく、kendoChart のデータソースでデータをバインドする方法にありました。この問題の解決策は、以下に示すようにデータソースとして ajax ポストを使用して関数を指定することでした。

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);
                             }
                         });
                     }
                 },
                 ....

変な質問でお騒がせしてすみません!

于 2012-10-16T14:29:35.513 に答える