トップ回答者
ViewBagのDictionaryデータを、javascriptの変数で連想配列にしたい

質問
-
ViewBagのDictionaryデータを、javascriptの変数で連想配列にしたいのですが、
うまくできなくて困っています。
使用データ例 {"A":"TEST1","B":"TEST2"}
画面上のフォームで、内部:Id / 表示:Nameのような形をとる時に、
通常は、Controller上のViewBagでSelectListしてから、 View上でDropDownListForで使用していますが、
フォーム利用以外の時に、上記の使用データ例の方法を取って、javascriptの変数で連想配列にしたい時があります。
初歩的な質問ですみませんが、どなたかご教授をお願いします。
開発環境:Visual Studio 2012, ASP.NET MVC 5
// Controller public async Task<ActionResult> Index() { var authorities = await unitOfWork.AuthorityRepository.GetSelectListsAsync(); ViewBag.AuthorityId = authorities.ToDictionary(p => p.AuthorityId, p => p.AuthorityName); return View(); }
// Viewのjavascript // 試したこと // 直接入力では問題なく、連想配列になる var obj1 = {"A":"TEST1","B":"TEST2"}; // var obj2 = {"A":"TEST1","B":"TEST2"}; になるが、Uncaught SyntaxError: Unexpected identifier セミコロンでエラー var obj2 = @Html.Raw(Json.Encode(ViewBag.AuthorityId)); // var obj3 = "{"A":"TEST1","B":"TEST2"}"; のように 「"」があるので連想配列にならない var obj3 = "@Html.Raw(Json.Encode(ViewBag.AuthorityId))";
- 編集済み yuchan01 2020年1月7日 22:21
回答
-
【追記】
上の私のレスで書いたことを実際に検証してみました。
質問者さんの Dictionary は以下の画像の Controller の赤枠のコードで生成するものと同じ構造だと想像してますが、そうであれば上の私のレスに書いた JSON.parse は不要でした。
View で ViewBag.AuthorityId を JavaScriptSerializer で JSON 文字列にシリアライズし、それを @Html.Raw(@jsonString) で JavaScript のコードに渡すと、それはそのままオブジェクト初期化しとして有効なので、変数に代入すれば JavaScript オブジェクトを生成できました。
上記がやりたいことと異なる場合は、どこがどう違うのか具体的に書いてください。
でも、よく見てみれば質問者さんの質問にあるコードの、
var obj2 = @Html.Raw(Json.Encode(ViewBag.AuthorityId));
が html, javascript のコードに変換されると、
var obj2 = {"A":"TEST1","B":"TEST2"};
となるそうで、とすると上の私の検証結果と同じ結果になるようですが、何故ダメだったのでしょうね? 実はうまく行っていたのに勘違いがあったとか?
- 編集済み SurferOnWww 2020年1月8日 7:29 追記
- 回答としてマーク yuchan01 2020年1月8日 16:55
すべての返信
-
【追記】
上の私のレスで書いたことを実際に検証してみました。
質問者さんの Dictionary は以下の画像の Controller の赤枠のコードで生成するものと同じ構造だと想像してますが、そうであれば上の私のレスに書いた JSON.parse は不要でした。
View で ViewBag.AuthorityId を JavaScriptSerializer で JSON 文字列にシリアライズし、それを @Html.Raw(@jsonString) で JavaScript のコードに渡すと、それはそのままオブジェクト初期化しとして有効なので、変数に代入すれば JavaScript オブジェクトを生成できました。
上記がやりたいことと異なる場合は、どこがどう違うのか具体的に書いてください。
でも、よく見てみれば質問者さんの質問にあるコードの、
var obj2 = @Html.Raw(Json.Encode(ViewBag.AuthorityId));
が html, javascript のコードに変換されると、
var obj2 = {"A":"TEST1","B":"TEST2"};
となるそうで、とすると上の私の検証結果と同じ結果になるようですが、何故ダメだったのでしょうね? 実はうまく行っていたのに勘違いがあったとか?
- 編集済み SurferOnWww 2020年1月8日 7:29 追記
- 回答としてマーク yuchan01 2020年1月8日 16:55
-
コメントありがとうございます。
一旦、最初にコメントいただいたシリアライズ/デシリアライズの方法で実施したところ、連想配列にすることができました。
// Controller側 public async Task<ActionResult> Index() { var authorities = await unitOfWork.AuthorityRepository.GetSelectListsAsync(); ViewBag.AuthorityId = JsonConvert.SerializeObject(authorities.ToDictionary(p => p.AuthorityId, p => p.AuthorityName)); return View(); }
// Viewのjavascript // 連想配列になる var obj1 = JSON.parse(JSON.stringify(@Html.Raw(ViewBag.AuthorityId)));
@Html.Raw(ViewBag.AuthorityId) ですが単独で使用する場合、
私の環境、自宅でも、ダブルクォートでくくらないとエラーで停止してしまいます。
(html上で変換されるが、セミコロンでエラーしていて、その行で停止)
JSON.stringfy()の中だと @Html.Rawをダブルクォートで囲まなくてよかったです
JSON.parseを使用しない方法についても試してみたいと思います。
- 編集済み yuchan01 2020年1月8日 16:55
-
> @Html.Raw(ViewBag.AuthorityId) ですが単独で使用する場合、私の環境、自宅でも、ダブルクォートでくくらないとエラーで停止してしまいます。
上のレスの View のコードに以下の赤枠で囲った部分のコードを追加して試してみましたが(@Html.Raw(Json.Encode(ViewBag.AuthorityId)); の部分は質問者さんの最初の質問のコードで obj2 に代入されていたものと同じです。赤枠部分以外は先の私のレスのコードと同じです)、
以下の画像の通りエラーにはならず期待通りの結果が取得できるのですが?
何が違うのでしょうね?
ちなみに私の環境は Windows 10 64-bit Pro, Visual Studio Community 2015, IIS 10.0 Express, 対象フレームワーク .NET Framework 4.6.1, MVC 5.2.7 です。ブラウザは IE, Edge, Chrome, Firefox, Opera で同じ結果になります(上の画像は Edge の場合ですが、他のブラウザでも同じ結果になります)。
- 編集済み SurferOnWww 2020年1月9日 3:17 訂正
-
> @Html.Rowが一番外側の時、セミコロンの部分でエラーします。
アップしていただいた画像を拝見すると確かに赤の波線が出ていますね。
そこにマウスのカーソルを持ってくるとエラーメッセージが表示されませんか? 表示されたら何と書いてあるのか教えてください。- 編集済み SurferOnWww 2020年1月10日 4:24
-
質問者さんと私のコード・環境で影響がありそうな違いは、
最初の質問にあった質問者さんのコードが、
var authorities = await unitOfWork.AuthorityRepository.GetSelectListsAsync(); ViewBag.AuthorityId = authorities.ToDictionary(p => p.AuthorityId, p => p.AuthorityName);
で、私のコードが下記、Dictionary<string, string> dic = new Dictionary<string, string> { { "A", "TEST1" }, { "B", "TEST2" } }; ViewBag.AuthorityId = dic;
それと、環境では質問者さんが Visual Studio 2012 Express for Web で私が Visual Studio Community 2015 ということぐらいですよね。
私の方では質問者さんのコードは試せませんが、Visual Studio の方はバージョンを下げて VS2010 Pro, MVC4 で試してみました。やはりエラーにはなりません(@Html の下の緑の波線は条件付きコンパイルが無効になっているという警告です)。実行すると期待した結果が得られます。
質問者さんのコードで、authorities.ToDictionary(p => p.AuthorityId, p => p.AuthorityName); は、私のコードの dic; と同じになるのでしょうか? 念のため私のコードをコピペして試していただけませんか。
- 編集済み SurferOnWww 2020年1月10日 3:15
-
試してみました結果です
@Html.Rawのエラー個所は異なりますが、問題なく表示されました。
var authorities = await unitOfWork.AuthorityRepository.GetSelectListsAsync(); ViewBag.AuthorityId = authorities.ToDictionary(p => p.AuthorityId, p => p.AuthorityName);
は同様のDictionaryの内容だと思ってましたが、何か異なるのか、またはjavascript側の構文間違いかもしれません。
引き続き検証してみます。
--- 以下、同様に試したコード
---
---