私は一日中アクションに苦労しています。テストアプリケーションをセットアップして同じ 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 時間多くの時間を費やしたため、この問題にこれ以上時間を費やすことはできません。(はぁ。)