2

次のようなUIがあります。

ここに画像の説明を入力

サーバーが保存できるように、新しく作成された行のデータをサーバーに送信しようとしています。

クライアントから MVC アプリケーションにデータを JSON 形式で送信しています。ここに私のajaxリクエストがあります:

var values = []; // an array with each item being an object/associative array

// more code to get values into variables

for (var i = 0; i < cultures.length; i++) {
  var cultureName = cultures[i];
  var valueTextBox = $(row).find(...);
  var value = $(valueTextBox).val();

  var cultureNameAndValue = { 'CultureShortName' : cultureName, 'StringValue' : value };

  values.push(cultureNameAndValue);
}

var stringTableRow = 
  { 
    'ResourceKeyId': resourceKeyId, 
    'Key': resourceKeyName, 
    'CategoryId': categoryId, 
    'CategoryName': categoryName, 
    'StringValues': values 
  };

var stringified = JSON.stringify({ StringTableRow: stringTableRow });

$.ajax('/Strings/JsonCreateNew', 
      { 
        cache: false, 
        async: false, 
        type: 'POST', 
        contentType: 'application/json; charset=UTF-8', 
        data: stringified, 
        dataType: 'json', 
        error: SaveNewResourceClientSideHandler.OnError, 
        success: SaveNewResourceClientSideHandler.OnSuccess 
      });

送信するデータは次のとおりです (Firebug で見られるように)。

{"StringTableRow":{"ResourceKeyId":"","Key":"Foo",
"CategoryId":"1","CategoryName":"JavaScript",
"StringValues":[
{"CultureShortName":"en-US","StringValue":"Something"},
{"CultureShortName":"fr-FR","StringValue":""}]
}}

これが私のサーバー側のコードです:

public ActionResult JsonCreateNew(StringTableRow row)
{
  // CreateNewStringTableRow(row);

  // return a success code, new resource key id, new category id
  // return Json(
              new { Success = true, ResourceKeyId = row.ResourceKeyId, 
                    CategoryId = row.CategoryId }, 
                JsonRequestBehavior.AllowGet);

  return new EmptyResult();
}

そして、受信した POST されたデータをバインドするビジネス オブジェクトは次のとおりです。

public class StringTableRow
{
    public StringTableRow()
    {
        StringValues = new List<CultureNameAndStringValue>();
    }

    public long ResourceKeyId { get; set; }

    public string Key { get; set; }

    public long CategoryId { get; set; }

    public string CategoryName { get; set; }

    public IList<CultureNameAndStringValue> StringValues { get; set; }  
}


public class CultureNameAndStringValue
{
  public string CultureShortName { get; set; }

  public string StringValue { get; set; }
}

Global.asax

public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
        }
    }

問題:

アクションJsonCreateNewは、null ではないが、すべてのプロパティが初期化されていないオブジェクトを受け取ります。つまり、すべての null 許容プロパティは null であり、値プロパティはデフォルト値です。したがって、クライアントが完全に有効な Json 文字列を送信しても、事実上、データはまったく取得されません。

カスタム モデル バインドを行う必要がありますか?

4

2 に答える 2

2

さて、私は自分の問題を解決しました。これは、他のプログラマーにとっても重要な洞察になるかもしれません。自分の問題を解決しているときに何かを学んだからです。

私の解決策: JSON を使用しないことに頼り、代わりに、HTTP が投稿された値をエンコードするために使用するデフォルトのエンコーディングを使用し、カスタム モデル バインディングのようなものを使用しました (モデル バインダーを実際に作成することはありません)。

説明: 通常、ajax リクエストを作成してクライアントから任意のサーバー プラットフォームにデータを渡す場合、エンコーディング、つまりcontentTypejQuery の ajax メソッドの設定オブジェクトのパラメーターを指定しない場合 (または他の手段を使用してjQuery 以外の ajax リクエストを作成しますが、ContentTypeHTTP ヘッダーを設定するのはあなたの目的です)、HTTP はデフォルトのエンコーディングを使用して投稿されたデータをエンコードします。これは、クエリ文字列の後に GET リクエストで投稿するものとよく似ています。バイナリ エンコードされるだけで、URL の一部として送信されません。

その場合、任意の型 ( IListIEnumerableICollectionIDictionaryなど) のコレクションを ASP.NET MVC に投稿する場合は、コレクションを具体化するために JavaScript で連想配列を作成しないでください。配列も作成しないでください。何も作成しないでください。

実際、規則を使用して、メインの大きなオブジェクト内でそれを渡すだけです。

data = 
{ /*scalar property */ Gar: 'har', 
  /* collection */ 'Foo[index++].Bar' : 'value1', 
  'Foo[index++].Bar' : 'value2'
}

また、JSON を使用しないでください。それはあなたの問題の半分を解決します。

サーバー側では、投稿されたデータを で受け取り、FormCollectionそのIValueProviderメソッド ( GetValue) を使用して必要なデータを掘り出します。そのためにモデル バインダーを明示的に作成する必要はありません。コントローラー自体のプライベート メソッドで実行できます。

もう少し時間があれば、この回答を改善します。

于 2013-10-15T16:43:42.643 に答える
-3

データ バインディングには Backbone または KnockoutJs を使用します。

于 2013-10-10T20:31:03.760 に答える