3

私は一日中アクションに苦労しています。テストアプリケーションをセットアップして同じ JSON を渡すと、モデルバインダーに問題はありませんが、何らかの理由で、モデルバインダーがアプリケーションで着信 JSON を受け入れることができないようです。

モデルは次のようになります。

public class AdjustmentDefaultsModel
{
    public Guid EmployeeId { get; set; }
    public List<AdjustmentDefault> Adjustments { get; set; }
}

public class AdjustmentDefault
{
    public int Id { get; set; }
    public string EmployeeId { get; set; }
    public string AdjustmentTargetTypeId { get; set; }
    public string AdjustmentTargetId { get; set; }
    public string AdjustmentTargetTypeDescription { get; set; }
    public string AdjustmentTargetDescription { get; set; }
    public string Amount { get; set; }
}

完全を期すために、ここに私の行動があります:

    [HttpPost]
    public JsonResult AddAdjustmentDefaults(AdjustmentDefaultsModel adjustments)
    {
        // will be more code here when I get the model in properly
        return Json(null);
    }

メイン プロジェクトとテスター プロジェクトの両方で Ajax によって行われている投稿は、同様に構成されていますが、唯一の違いは URL です。テスターのデータには JSON が直接割り当てられますが、実際のプロジェクトのデータはノックアウトによって構築されます。

            $.ajax({
                url: '/Employee/AddAdjustmentDefaults',
                crossDomain: true,
                data: ko.toJSON(self),
                contentType: "application/json; charset=utf-8",
                dataType: 'json',
                type: 'POST',
                success: function (data) { alert("Saved."); },
                error: function (error) { alert("Error."); },
            });

メイン プロジェクトを実行したときに、失敗した JSON を Fiddler でキャプチャし、テスト プロジェクトに貼り付けました。前述のように、テスト プロジェクトのバインディングに問題はありませんでした。

次の JSON は、メイン プロジェクトとテスター プロジェクトで機能します。

{"EmployeeId":"cd930985-d66c-4d25-ae0c-253665242cf0","Adjustments":[]}

モデルには EmployeeId GUID が適切に設定されており、Adjustments プロパティは null です。

ただし、リストに追加しようとすると、モデル バインダーが爆発し、リストが null になるだけでなく、従業員 Guid も null になります。

ここからデバッグする場所がわかりません。モデル バインダーが何を実行できなかったのかを知ることができればよいのですが、その点に関して有用なものをキャプチャできませんでした。これが機能しない理由の詳細を取得するには、カスタム モデル バインダーを作成する必要がありますか?

アップデート

asymptoticFault のコメントに従って、モデルのカスタム モデル バインダーを作成しました。コードは次のようになります。

public class AdjustmentDefaultsModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
            return null;    // not JSON request

        var request = controllerContext.HttpContext.Request;
        request.InputStream.Position = 0;
        var incomingData = new StreamReader(request.InputStream).ReadToEnd();

        if (String.IsNullOrEmpty(incomingData))
            return null;    // no JSON data

        return JsonConvert.DeserializeObject(incomingData, bindingContext.ModelType);
    }
}

このモデル バインダーを使用すると、アクションはすべて正しい値でモデルを生成するようになりました。

なぜこれが機能するのかわかりません。検証のために DefaultModelBinder ソースをダウンロードしていませんが、基本的にはこれが実行されるべきことのように思えます。結局のところ、DefaultModelBinder は受信する JSON の大部分で機能するように思われます。

したがって、私の実際の質問はまだ実際には回答されていませんが、このタスクに最初に見積もっていた予算の 10 分よりも約 6 時間多くの時間を費やしたため、この問題にこれ以上時間を費やすことはできません。(はぁ。)

4

1 に答える 1

1

カスタム モデル バインダーを使用してみてください。最終的には必要ないかもしれませんが、サーバーに渡された値で実際に何が起こっているかをデバッグするのに役立ちます。

これは非常に簡単なプロセスであり、実際には次の 2 つのステップだけです。

1)インターフェースを実装するクラスを作成します。System.Web.Mvc.IModelBinderこれは1つのメソッドに過ぎないと思いますBindModel().

2)などのOnApplicationStart()方法でバインダーを追加します。Global.asax.cs

ModelBinders.Binders.Add(typeof(AdjustmentDefaultsModel), new YourModelBinder());
于 2013-08-14T02:44:08.883 に答える