2013-06-28 15 views
27

複雑なJSONオブジェクトをMVC 4コントローラアクションに渡そうとしています。 JSONコンテンツは可変であるため、MVCがJSONの個々のプロパティ/要素をアクションメソッドのパラメータリストのパラメータにマッピングすることは望ましくありません。私はちょうどコントローラのアクションで単一のJSON文字列パラメータとしてデータを取得したい。ここでJSONデータをjQuery経由でASP.NETにポストする.NET MVC 4コントローラアクション

は私のアクションメソッドのシグネチャです:

[HttpPost] 
    [ValidateInput(false)] 
    public string ConvertLogInfoToXml(string jsonOfLog) 

そして、ここでは私のブラウザから、いくつかのJSONデータを投稿する私の試みです:

data = {prop: 1, myArray: [1, "two", 3]}; 
    //'data' is much more complicated in my real application 
    json = {jsonOfLog: data}; 

    $.ajax({ 
     type: 'POST', 
     url: "Home/ConvertLogInfoToXml", 
     data: JSON.stringify(json), 
     success: function (returnPayload) { 
      console && console.log ("request succeeded"); 
     }, 
     error: function (xhr, ajaxOptions, thrownError) { 
      console && console.log ("request failed"); 
     }, 
     dataType: "xml", 
     contentType: "application/json",    
     processData: false, 
     async: false 
    }); 

私は最初に私のブレークポイントにヒットするとConvertLogInfoToXMLメソッド、jsonOfLogがnullです。

jsonOfLogプロパティを単純な文字列にするために、JavaScriptで 'json'変数がどのように設定されているかを変更します。 :ConvertLogInfoToXMLメソッドの冒頭に私のブレークポイントにヒットしたときに

json = { jsonOfLog: "simple string" }; 

はその後、jsonOfLogは、文字列(例えば「単純な文字列」)の値です。

I型のオブジェクトであることがアクションメソッドにjsonOfLogパラメータの種類を変更しようとした:今

[HttpPost] 
    [ValidateInput(false)] 
    public string ConvertLogInfoToXml(object jsonOfLog) 

、私はより複雑な「データ」オブジェクトを渡していオリジナルJavaScriptコード(と)、jsonOfLogは{object}の値を取得します。しかし、デバッガはウォッチウィンドウにこれ以上の詳細を表示しません、私はこの変数を操作するためにどのメソッドを使用できるかわかりません。

渡されたデータが文字列化された複雑なオブジェクトであるMVCコントローラにJSONデータを渡すにはどうすればよいですか?

おかげで、 ノートルダム

+0

私は、これはあなたがhttp://stackoverflow.com/questions/21578814/how-to-receive-json探しているものだと思います-in-a-mvc-5-action-a-a-paramter –

答えて

23

問題は、dataTypeと、dataパラメータの形式です。私はサンドボックスと、次の作品でこれをテストした:

C#

[HttpPost] 
    public string ConvertLogInfoToXml(string jsonOfLog) 
    { 
     return Convert.ToString(jsonOfLog); 
    } 

javascriptの

<input type="button" onclick="test()"/> 

    <script type="text/javascript"> 

     function test() { 
      data = { prop: 1, myArray: [1, "two", 3] }; 
      //'data' is much more complicated in my real application 
      var jsonOfLog = JSON.stringify(data); 

      $.ajax({ 
       type: 'POST', 
       dataType: 'text', 
       url: "Home/ConvertLogInfoToXml", 
       data: "jsonOfLog=" + jsonOfLog, 
       success: function (returnPayload) { 
        console && console.log("request succeeded"); 
       }, 
       error: function (xhr, ajaxOptions, thrownError) { 
        console && console.log("request failed"); 
       }, 

       processData: false, 
       async: false 
      }); 
     } 

    </script> 

は、テキストを送信するときに、あなたが一致する変数を送信する必要があり、dataに特別な注意を払いますパラメータの名前それはかなりではありませんが、それはあなたの欲望のフォーマットされていない文字列を取得します。

これを実行する場合、jsonOfLogは、サーバ機能に次のようになります

jsonOfLog "{\"prop\":1,\"myArray\":[1,\"two\",3]}" string 

HTTPのPOSTヘッダ:

Key Value 
Request POST /Home/ConvertLogInfoToXml HTTP/1.1 
Accept text/plain, */*; q=0.01 
Content-Type application/x-www-form-urlencoded; charset=UTF-8 
X-Requested-With XMLHttpRequest 
Referer http://localhost:50189/ 
Accept-Language en-US 
Accept-Encoding gzip, deflate 
User-Agent Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0) 
Host localhost:50189 
Content-Length 42 
DNT 1 
Connection Keep-Alive 
Cache-Control no-cache 
Cookie EnableSSOUser=admin 

HTTP POSTボディ:

jsonOfLog={"prop":1,"myArray":[1,"two",3]} 

応答ヘッダー:

Key Value 
Cache-Control private 
Content-Type text/html; charset=utf-8 
Date Fri, 28 Jun 2013 18:49:24 GMT 
Response HTTP/1.1 200 OK 
Server Microsoft-IIS/8.0 
X-AspNet-Version 4.0.30319 
X-AspNetMvc-Version 4.0 
X-Powered-By ASP.NET 
X-SourceFiles =?UTF-8?B?XFxwc2ZcaG9tZVxkb2N1bWVudHNcdmlzdWFsIHN0dWRpbyAyMDEyXFByb2plY3RzXE12YzRQbGF5Z3JvdW5kXE12YzRQbGF5Z3JvdW5kXEhvbWVcQ29udmVydExvZ0luZm9Ub1htbA==?= 

レスポンスボディ:

{"prop":1,"myArray":[1,"two",3]} 
+0

あなたが提案したことは何ですか?**問題**があります。しかし、ajaxオブジェクトのデータプロパティのためではありません。代わりに、contentTypeプロパティが削除されます。これを削除すると、デフォルトの "application/x-www-form-urlencoded"が使用されます。この問題は、投稿されたデータが「大」になると、切り詰められてしまいます。私はそのサーバーによって思っています。私は同じソリューションを早期に発見し、その問題に遭遇するまでは非常に満足していました。 – Notre

+0

'application/x-ww-form-urlencoded'には48KBの制限があります。大規模なデータセットの場合、通常は 'multipart/form-data'にフォールバックする必要がありますが、そうです。この場合、動作しません。あなたは建築の四角いペグ/丸穴のポイントを打っているかもしれません。私はあなたが将来的に知って良い良いおしゃべりになるので、何かを動作させる場合、興味があります。がんばろう。 –

+0

あなたのコメントをありがとう、私の質問に時間を費やしてくれてありがとう。大規模なデータセットの問題(元の質問では指定されていない)を除いて、あなたのソリューションは良好です。たぶん私は新しい質問を入力する必要があります、あなたはこの1つのクレジットを得ることができます... – Notre

0

数ヶ月前、私は、私はまた私のコントローラに戻っていくつかのJSON形式の日付を送信するために必要な奇妙な状況に遭遇しました。ここで私は私の髪を引っ張った後、思い付いたものです:

私のクラスには、次のようになります。

public class NodeDate 
{ 
    public string nodedate { get; set; } 
} 
public class NodeList1 
{ 
    public List<NodeDate> nodedatelist { get; set; } 
} 

と私のC#のコードを次のように

 public string getTradeContribs(string Id, string nodedates) 
    {    
     //nodedates = @"{""nodedatelist"":[{""nodedate"":""01/21/2012""},{""nodedate"":""01/22/2012""}]}"; // sample Json format 
     System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer(); 
     NodeList1 nodes = (NodeList1)ser.Deserialize(nodedates, typeof(NodeList1)); 
     string thisDate = ""; 
     foreach (var date in nodes.nodedatelist) 
     { // iterate through if needed... 
      thisDate = date.nodedate; 
     } 
    } 

ので、私はデシリアライズすることができました"ノード"オブジェクト内の私のnodedates Jsonオブジェクトパラメータ。当然もちろん "NodeList1"クラスを使って動作させています。

私は ボブ

+0

あなたの返信にBobありがとうございます。あなたのクライアントコードは、(?)nodedatesをgetTradeContribsに投稿したように見えましたか?私の重要な問題は、コントローラのアクションを取得するとすぐに、基本文字列以外のものが含まれている場合、パラメータ(たとえば、nodedates)がnullに設定されているようです。呼び出し側でnodesatesが "文字列化されましたか" – Notre

2

....これが役に立てば幸い私はあなたがこの記事を参照している場合、あなたの答えを見つけることだと思う:Deserialize JSON into C# dynamic object?

あなたがここに欲しいものを達成するための様々な方法があります。 System.Web.Helpers.Jsonのアプローチ(いくつかの答えがダウンしている)は最も単純なようです。

+0

ありがとうございます。私は、私のキー問題は、私がアクション文字列 "jsonOfLog"内のパラメータをnull以外の値にすることだと思います。もし私がちょうど翻訳の束(私はモデルのバインダーが途中で取得していると思う)なしで私のアクションメソッドでストリングされたJSONを得ることができる、私は設定されると思います。 – Notre

+0

文字列を操作する場合は、J Torresが提供するソリューションを使用してください。しかし、そのデータで何か意味のあることを行う必要があると仮定すると、逆シリアル化されたデータを扱う方がはるかに良いと思います。 – Acorn

+0

一般的に言えば、バインダーが自動的にタイプを作成するのが普通です。あなたがコメントを見るならば、Jトーレスのソリューションは完璧です。ただし、私は大規模なデータセットが渡されたときに問題にぶつかります。 – Notre

0

まあ、私のクライアント側(CSHTMLファイル)(今大きいインフラジスティックスコントロールを使用して)、グリッドを表示するのDataTableを使用していました。 ユーザーが行をクリックすると、行イベントとそのレコードに関連付けられた日付が取得され、サーバーに戻って取引などのサーバー側のリクエストが追加されます。 いいえ - 私は文字列化しませんでしたそれ...

のDataTableデフ本(ものの多くを省い)としてスタートし、クリックイベントは、私は私のJSONオブジェクトにプッシュところの下に見られている:

oTablePf = $('#pftable').dataTable({   // INIT CODE 
      "aaData": PfJsonData, 
      'aoColumnDefs': [      
       { "sTitle": "Pf Id", "aTargets": [0] }, 
       { "sClass": "**td_nodedate**", "aTargets": [3] } 
       ] 
       }); 

    $("#pftable").delegate("tbody tr", "click", function (event) { // ROW CLICK EVT!! 

     var rownum = $(this).index(); 
     var thisPfId = $(this).find('.td_pfid').text(); // Find Port Id and Node Date 
     var thisDate = $(this).find('.td_nodedate').text(); 

     //INIT JSON DATA 
     var nodeDatesJson = { 
      "nodedatelist":[] 
     }; 

     // omitting some code here... 
     var dateArry = thisDate.split("/"); 
     var nodeDate = dateArry[2] + "-" + dateArry[0] + "-" + dateArry[1]; 

     nodeDatesJson.nodedatelist.push({ nodedate: nodeDate }); 

      getTradeContribs(thisPfId, nodeDatesJson);  // GET TRADE CONTRIBUTIONS 
    }); 
2

VB.NETのVERSION

さて、私は数時間かけて投稿可能な方法を探しました。複数のパラメータをMVC 4 WEB APIに追加しましたが、私が見つけたもののほとんどは 'GET'アクションかまったくフラットアウトでは動作しませんでした。しかし、私はついにこれを手に入れました。私は私のソリューションを分かち合うと思っていました。

  1. JSON-js json2Json.NETをダウンロードするために使用NuGetパッケージ。 NuGetパッケージをインストールする手順:

    (1)Visual Studioで、>はNuGetパッケージの管理ウェブサイトに行く...enter image description here

    (2)(その旨をか何か)JSONを型に検索バーとJSON-js json2Json.NETを見つける。それらをダブルクリックすると、現在のプロジェクトにパッケージがインストールされます。 enter image description here

    (3)NuGetは自動的にjsonファイルをプロジェクトディレクトリの~/Scripts/json2.min.jsに配置します。 json2.min.jsファイルを見つけ、それをあなたのウェブサイトの頭にドラッグ・アンド・ドロップします。 注:インストール手順については、を参照してください。js(javascript)ファイルは、this solutionと読みます。

  2. 目的のパラメータを含むクラスオブジェクトを作成します。これを使用して、APIコントローラのパラメータにアクセスします。コード例:

    Public Class PostMessageObj 
    
    Private _body As String 
    Public Property body As String 
        Get 
         Return _body 
        End Get 
        Set(value As String) 
         _body = value 
        End Set 
    End Property 
    
    
    Private _id As String 
    Public Property id As String 
        Get 
         Return _id 
        End Get 
        Set(value As String) 
         _id = value 
        End Set 
    End Property 
    End Class 
    
  3. その後、我々のセットアップ、我々はPOSTアクションのために使用される実際のMVC 4のWeb APIコントローラ。ここでは、Json.NETを使用して、文字列オブジェクトが転記されたときにそれを逆直列化します。適切な名前空間を使用することを忘れないでください。前の例を続けると、ここに私のコードは次のとおりです。

    Public Sub PostMessage(<FromBody()> ByVal newmessage As String) 
    
    Dim t As PostMessageObj = Newtonsoft.Json.JsonConvert.DeserializeObject(Of PostMessageObj)(newmessage) 
    
    Dim body As String = t.body 
    Dim i As String = t.id 
    
    End Sub 
    
  4. 今、私たちは私たちのAPIコントローラは、当社の文字列化されたJSONオブジェクトを受信するように設定されていることを、私たちは$を使用して、クライアント側から自由にPOSTアクションを呼び出すことができます。アヤックス;前の例を続けると、ここに(適切にはlocalhost + ROOTPATHを置き換える)私のコードです:

    var url = 'http://<localhost+rootpath>/api/Offers/PostMessage'; 
    var dataType = 'json' 
    var data = 'nothn' 
    var tempdata = { body: 'this is a new message...Ip sum lorem.', 
        id: '1234' 
    } 
    var jsondata = JSON.stringify(tempdata) 
    $.ajax({ 
        type: "POST", 
        url: url, 
        data: { '': jsondata}, 
        success: success(data), 
        dataType: 'text' 
    }); 
    

あなたのようにそれを渡して、私たちは基本的に文字列に変換し、JSONオブジェクトを構築している見ることができるようにJSON.NETフレームワークを使用して再構築します。 APIコントローラに戻り値を含めなかったので、success()関数に任意の文字列値を配置しただけです。


著者のノートは

これはASP.NET 4.0、Webフォーム、VB.NET、およびMVC 4のWeb APIコントローラーを使用してVisual Studioの2010年に行われました。 MVC 4 Web APIとVS2010の統合に問題がある人は、パッチをダウンロードして可能にすることができます。 MicrosoftのDownload Centerからダウンロードできます。ここで

は(主にC#で)助けたいくつかの追加の参照です:

1

//のasp.net MVCでの単純なJSONオブジェクト

var model = {"Id": "xx", "Name":"Ravi"}; 
$.ajax({ url: 'test/[ControllerName]', 
         type: "POST", 
         data: model, 
         success: function (res) { 
          if (res != null) { 
           alert("done."); 
          } 
         }, 
         error: function (res) { 

         } 
        }); 


//model in c# 
public class MyModel 
{ 
public string Id {get; set;} 
public string Name {get; set;} 
} 

//controller in asp.net mvc 


public ActionResult test(MyModel model) 
{ 
//now data in your model 
} 
関連する問題