質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Razor

RazorはASP.NET Web PagesとASP.NET MVCで使われているビュー・エンジンです。HTMLマークアップとC#またはVisual Basicのコードに対応しています。マークアップとコードの間の切り替えは"@"で記されています。

ASP.NET MVC Framework

ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。

Q&A

解決済

1回答

15438閲覧

ビュー・ヘルパーFor型(TextBoxFor)使用時に、nameを指定したい

tkta

総合スコア21

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Razor

RazorはASP.NET Web PagesとASP.NET MVCで使われているビュー・エンジンです。HTMLマークアップとC#またはVisual Basicのコードに対応しています。マークアップとコードの間の切り替えは"@"で記されています。

ASP.NET MVC Framework

ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。

0グッド

0クリップ

投稿2019/01/21 09:16

編集2019/01/24 01:15

ビュー・ヘルパーFor型(TextBoxFor)使用時に、nameを指定したい

前提・実現したいこと
TextBoxForで、modelに紐づいた?nameではなく、@Html.TextBoxを使用する際に指定したnameを<input>タグに付けたい

環境
ASP.NETMVC5
VisualStudio2013
c#

発生している問題・エラーメッセージ
該当のソースコード

↓↓↓求めている形↓↓↓
<input class="form-control input-information" id="hoge" name="ABC" type="text" value="ほげ">

@Html.TextBoxForを用いて、上記の形で出力したい。

@Html.TextBoxFor(m => item.MEMBER.NAME, new { @class = "form-control input-information" ,name = "ABC" })
↑上記でnameをABCと明示しても、nameがABCとならず、

<input class="form-control input-information" id="item.MEMBER.NAME" name="item.MEMBER.NAME" type="text"> のような感じで出力されます。

@Html.TextBoxForではなく、
@Html.TextBox("ABC",item.MEMBER.NAME, new { @class = "form-control input-information"})とすれば、
求めている形で出力されます。

試したこと
下記サイトの内容を試してみても、自分で指定したnameがつかないです。
https://code.i-harness.com/ja/q/5c6f89

補足
nameの箇所以外、不必要そうなところは削除していますので「こういうhtmlにはならない、おかしい」と思われるかもしれませんが、そこはスルーしてください。
知りたいことは、htmlヘルパー(TextBoxFor)を使用した際にnameを指定することが可能なのか、もし可能ならその方法を知りたい、ということです。
よろしくお願いします。

画面イメージ
イメージ説明
イメージ説明

追記

>EditorFor を利用すると、モデルのプロパティの型によってレンダリングされる html 要素が適切に選ばれる

EditorForがモデルに紐づいたフォームを作るというのは理解していたのですが、
テキストボックスならTextBoxFor、
チェックボックスならCheckBoxFor、
という風に、ソース上で明示した方がわかりやすいんじゃ?
と、思うことがあり、EditorForの優位性をあまり実感できていないというのが現状です……。

>TextBoxFor の方は、ダメだったような・・・(定かではないです)

数字入力のみのフォームに、文字を入力した際、
モデルのErrorMessageが表示されるのは確認しました。

>idを指定しないと、「.」「[」「]」が「_」に変換されてしまうみたいで?

の件ですが、
Viewのコード↓

View

1 2@Html.EditorFor(m => m.MEMBER[num].BOSS.NAME)

をchromeの開発者ツールで確認してみたところ、下記のように表記されていて、

html

1<input class="text-box single-line" id="m_MEMBER_0___BOSS_NAME" name="m.MEMBER[0].BOSS.NAME" type="text" value="安藤">

internet explorerの開発者ツールで確認してみても、

html

1<input class="text-box single-line" id="m_MEMBER_0___BOSS_NAME" name="m.MEMBER[0].BOSS.NAME" type="text" value="安藤" />

と同様のコードが表示されており、id属性値もエンコード???が起きてしまってます(TextBoxForでも同じ状況です)。
modelの書き方が原因な気もしてきましたが、
SurferOnWwwさんにこれ以上お手数をおかけするわけにもいかないので、
この部分は気にしないでください。

それも紹介した記事「コレクションのデータアノテーション検証」に例が出ていますが、以下のようにすれば良いはずですけど・・・
私のレスをきちんと読んでもらっているでしょうか? 読んだけど意味不明だったということでしょうか?

いや読んではいるのですが、

View

1@Html.ValidationMessageFor(m => m.CountryList[i].Name)

に、クラス属性を与えたく、

View

1@Html.ValidationMessageFor(m => m.CountryList[i].Name,new{@class="text-danger"})

と、するとエラーが出てしまい、
クラスの付与の仕方がわからず、困り果てコメントのコードに達しました。

最終的には、

View

1@Html.ValidationMessageFor(m => m.CountryList[i].Name,"",new{@class="text-danger"})

との形にすれば、class属性を付与できると発見しました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/01/21 10:10

目的は何ですか? 勝手に変えるとモデルバインディングが上手くいかない(=勝手に変えてはいけないという意味)ような気がするのですか?
tkta

2019/01/21 11:12

ソースを上げにくくて申し訳ないのですが。 ・前提 登録画面は、@Html.TextBoxForで実装してあります。 登録画面に基づき、MEMBERテーブルにデータを登録します。 この際、上記のテーブルは1回の登録で、1レコードデータを保存します。 ・現状 上記のレコードを編集するのですが、登録の際は1レコードずつ登録処理を行っていましたが、編集の際は既存レコードを複数レコードまとめて編集可能(&編集の際は追加登録も同時に行うことも可能、みたいな感じです)。 画面としては、登録画面をタブ内容とし、大枠のタブメニューで編集レコードを行き来可能&追加登録の際は新たにタブを生成します。 タブ内のコードは登録時の使い回しで@Html.TextBoxForを使用しています。 この際、上記「発生している問題」に記載してある@Html.TextBoxForによるタブ1の<input>タグ、タブ2の<input>タグ、タブ3の.....、が同じnameになっていて、別名をつけれないか、と、いうのが目的です。 現在、foreachで登録済みデータをタブごとに生成しているのですが、最終的には、@Html.TextBoxForを使用する際、nameでMEMBER[0].TITLEみたいな形を明示できないかなあと試行錯誤しています(追加登録はインサート処理なので別モデルを生成して対応します)。 submit時に、 $('.classname').each(function(i){ $(this).attr('name','MEMBER[' + i + '].TITLE'); }) と名前を付けなおしても登録可能でしたが(我流すぎますね...)、htmlを書き直してしまうと、仮にエラーが起きた際おかしなことになりそうで、Htmlヘルパーで事前にnameを指定可能ならば、と思い、質問しました。 説明がわかりづらいところもあると思いますが、 ご意見をいただければ、と思います。 家に帰ってもう一度考えてみます。
退会済みユーザー

退会済みユーザー

2019/01/21 12:23

タブとか意味不明な言葉が出てきて、全体的にも理解不能です。すみませんがギブアップ。
退会済みユーザー

退会済みユーザー

2019/01/21 23:08 編集

タブという言葉に目が行って理解不能になってしまいましたが、要するにモデルに定義してあるクラスのオブジェクトのコレクションがアクションメソッドの引数にモデルバインドできれば良いのですか?
tkta

2019/01/22 02:51

「,Name = "ABC"」の形でnameを指定できました。 余談ですが、「,@Name = "ABC"」でも指定可能 「,name = "ABC"」「,@name = "ABC"」は、指定不可でした。 仕組みがわからすぎて怖いですが、こういう方法もあるのですね。 勉強になります!! SurferOnWwwさん、その通りです!! ループ処理にTextBoxForを使用し、複数入力フォームを作成しているのですが、それらの<input>タグのnameが同じのため、意図的に連番をつけて対応するのか?、と、考えた結果です。 説明が下手で大変申し訳ございません。
退会済みユーザー

退会済みユーザー

2019/01/22 03:31

「モデルに定義してあるクラスのオブジェクトのコレクションがアクションメソッドの引数にモデルバインドできれば良い」ということであれば、Microsoft 公式解説書にも書かれているやり方があります。詳しくは後で回答欄に書いておきます。(Name を使うなどというものではありません)
guest

回答1

0

ベストアンサー

要するに、モデルに定義してあるクラスのオブジェクトのコレクションがアクションメソッドの引数にモデルバインドできれば良いということだそうですので、そうするにはどうすればよいかについて回答します。

コレクションのモデルバインディングですが、それがうまく行われるようにするには、レンダリングされる html 要素の name 属性が連番のインデックスを含むようにします。

具体的には、name="prefix[index].Property" というパターンにします。prefix の部分にはアクションメソッドのパラメータ(仮引数)名が入ります。index は 0 から始まる連番です。

なので、質問者さんが質問のコメントに書かれた、

@Html.TextBoxForを使用する際、nameでMEMBER[0].TITLEみたいな形を明示できないかなあと試行錯誤しています

・・・というような形にするというのは正解です。

では、TextBoxFor や EditorFor(EditorFor を使うのがお勧めです)でどのように name 属性を設定するかですが、以下の記事が参考になると思いますので目を通してください。

コレクションのデータアノテーション検証
http://surferonwww.info/BlogEngine/post/2014/09/01/validation-of-collection-data-during-model-binding-using-data-annotation.aspx

他のコード例としては以下の Teratail の記事に私の回答がありますので見てください。

ASP.NET MVC ラジオボタンのView/Controllerのやり取り
https://teratail.com/questions/151505

不明点があれば質問してください。

【追記】

下の 2019/01/23 18:09 の私のコメントで「長くなりそうなので回答欄に追記します」と書きましたが、それを以下に書きます。

EditorFor、TextBoxForの違いがわからなく

EditorFor を利用すると、モデルのプロパティの型によってレンダリングされる html 要素が適切に選ばれる(例: bool 型にするとチェックボックスになる)こと、プロパティ付与される DataType 属性によって、生成される html ソースの input 要素の type 属性が変わってくる(例:MultilineText の場合は input 要素でなく、textarea 要素になる)ことがあります。

あと、紹介した前者の記事にも書きましたが、ASP.NET がレンダリングする html 要素に、クライアントサイドでの jQuery ライブラリによる検証に必要な属性(例: data-val="true" など)が追加されないと、クライアント側での検証ができません。EditorFor を使用すると、クライアント側での検証に必要な属性が自動的に付与されます。

TextBoxFor の方は、ダメだったような・・・(定かではないです)

EditorForですと、「text-box」「single-line」クラスが自動で付与されていたので、

class="text-box single-line" はデフォルトでハードコーディングされている属性だそうです。MVC 5.1 からは EditorFor にも任意の属性が付与できるようになりました。詳しくは以下の記事を見てください。

EditorFor での属性の付与方法
http://surferonwww.info/BlogEngine/post/2018/02/23/how-to-pass-html-attributes-in-editorfor.aspx

idを指定しないと、「.」「[」「]」が「_」に変換されてしまうみたいで?

それはどういうことなのか分かりませんが、上に紹介した記事に書いたように、

@Html.EditorFor(m => m.LastName, new { htmlAttributes = new { @class = "coolTextBox", data_date = "12-02-2012" } })

とすれば、レンダリングされる html は以下のようになるのですが・・・

<input class="coolTextBox text-box single-line" data-date="12-02-2012" id="LastName" name="LastName" type="text" value="Gee" />

余談ですが、List型のValidationの結び付け方がわからなく、

それも紹介した記事「コレクションのデータアノテーション検証」に例が出ていますが、以下のようにすれば良いはずですけど・・・

@Html.LabelFor(m => m.CountryList[i].Name) @Html.EditorFor(m => m.CountryList[i].Name) @Html.ValidationMessageFor(m => m.CountryList[i].Name)

私のレスをきちんと読んでもらっているでしょうか? 読んだけど意味不明だったということでしょうか?

【追記2】

下の 2019/01/24 11:04 の私のコメントで「レス不要かもしれませんが、気になった点がありますので、後で回答欄に追記しておきます」と書きましたが、それを以下に書きます。

質問者さんが回答欄に追記された件に対するレスです。

数字入力のみのフォームに、文字を入力した際、モデルのErrorMessageが表示されるのは確認しました。

私の回答欄に【追記】で書いた「TextBoxFor の方は、ダメだったような・・・」は思い違いでした。間違った情報ですみません。

EditorFor に代えて TextBoxFor を使っても、クライアント側の検証用に使う属性 data-val-* は付与され、クライアント側での jQuery / JavaScript による検証はかかることを確認しました。

下の画像で、網掛けした方の input 要素が TextBoxFor 、その下の input 要素が EditorFor でレンダリングされたものです。

イメージ説明

ただし、Model のクラスのプロパティに付与した DisplayFormatAttribute が TextBoxFor では無視されます。

属性は以下の画像の赤枠のように付与していますが、上の画像の赤枠で示した value 属性の通り、TextBoxFor でレンダリングすると無視されるようです。他にも期待通りの結果にならないことがあるかもしれず、要注意だと思います。

イメージ説明

idを指定しないと、「.」「[」「]」が「_」に変換されてしまうみたいで?

html コードを貼っていただいて意味が分かりました。そこは、上の画像でしめした通り、自分の環境でも同じです。

裏技的な手段でコントロールする方法があるかもしれませんが、やり方は知りませんし、その必要もないと思っています。

id が勝手に書き換わると困るケースは、クライアントスクリプトで getElementById とかを使いたい場合がありますが、MVC4 以降には Html ヘルパーに IdFor メソッドが用意されていて、それを使えば html にレンダリングされた時の id の値は取得可能です。

詳しくは以下の記事を見てください。

Control.ClientID と Html.IdFor
http://surferonwww.info/BlogEngine/post/2017/02/19/control-clientid-and-html-idfor.aspx

name 属性の値を取得したいというケースもあるかもしれませんが、そのための Html ヘルパー NameFor も用意されています。

投稿2019/01/22 04:17

編集2019/01/24 02:52
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tkta

2019/01/22 05:45 編集

ご丁寧な回答をいただき、ありがとうございます。 急ぎの用件が入ったため、数日後になるかもしれませんが、必ずやろうと思います。 不明点等があった場合、質問させていただきますので、 お手数をおかけしますがご回答いただければ、と思います。 取り急ぎのご連絡で失礼します。
tkta

2019/01/23 06:36

SurferOnWwwさんの回答にある 上記の方法を参考にして無事に実装できました。 EditorFor、TextBoxForの違いがわからなく、 EditorForですと、「text-box」「single-line」クラスが自動で付与されていたので、 今回はTextBoxForで下記のように実装しました。 @Html.TextBoxFor(m => m.MEMBER[num].BOSS.NAME, new { @class = ~~~ }) idを指定しないと、 「.」「[」「]」が「_」に変換されてしまうみたいで?、 <input id = "m_MEMBER_num__BOSS_NAME">みたいな気持ち悪いタグが生まれてきたので、 ひとつづつ属性名を指定して上書きしました。 余談ですが、List型のValidationの結び付け方がわからなく、 そのうえ、@Html.ValidationMessageForだと、 「,.new{@class = ~}」を記載すると、引数が云々?の警告を受けたので、 @Html.ValidationMessage("MEMBER[" + num + "].BOSS.NAME", new { @class = "text-danger" }) と強引な方法でvalidationを付与してみました。 多分解決しました。 SurferOnWwwさん、ありがとうございました。 また、wwbQzhMkhhgEmhUもありがとうございました。 色々と勉強になりました!!
退会済みユーザー

退会済みユーザー

2019/01/23 09:09

上のコメントにレスしようとしましたが、長くなりそうなので回答欄に追記します。
tkta

2019/01/24 01:14

質問の追記欄に追加しました。
退会済みユーザー

退会済みユーザー

2019/01/24 02:04

返答いただきありがとうございました。 レス不要かもしれませんが、気になった点がありますので、後で回答欄に追記しておきます。
tkta

2019/01/24 04:43 編集

確認までしていただき、ありがとうございます。 TextBoxForとEditorForの細かい仕様を理解できました。 DisplayFormatの挙動が違うのですね。 今までDisplayNameや、RegularExpression等の入力検証系のしか設定してなく、 あまりDisplayFormatは使用してこなかったのですが、これからは意識してみます。 調べてみたら、DisplayFormatを設定しつつ、 適応されないTextBoxForを意図的に使用する方法もあるようで奥が深いですね。 https://redwarrior.hateblo.jp/entry/2016/08/22/090000 >html コードを貼っていただいて... こういう仕様なのですね。バグ的なものかと思ってました...。 参考サイトのような方法で、対応できるのも理解できました。 目から鱗です。 ご丁寧に説明していただき、ありがとうございました。 色々と説明が足りず、申し訳ございませんでした。 また何かございましたら、よろしくお願いします。
退会済みユーザー

退会済みユーザー

2019/01/25 01:49

今さらながらですが、TextBoxFor ではサーバー側の検証に問題があったケースを思い出しましたので、連絡しておきます。 詳しい話は以下の記事を見てください。 Modelの型の検証を無効化・またはエラーメッセージを日本語にしたい https://teratail.com/questions/146213 要約すると・・・ public int Price { get; set; } というような int 型のプロパティをベースに、TextBoxFor で html をレンダリングすると、 <input type="text" data-val-number="The field Price must be a number." ... /> となって、数字以外を入力すると、クライアント側での検証で、出てほしくないのに "The field Price must be a number." というエラーメッセージが出る。 EdotorFor で html をレンダリングすると、 <input type="number" data-val-number="The field Price must be a number." ... /> 結果、ブラウザ依存ですが、例えば IE11 の場合、数字以外の文字を入力し、フォーカスを外すとクリアされ(テキストボックスは空白になる)、エラーメッセージは出ない。Chrome では数字以外入力できないという結果になります。 いずれにしても出てほしくない "The field Price must be a number." というエラーメッセージは出なくなります。
tkta

2019/01/25 05:09 編集

細かい話ですこし理解が追い付いていない可能性もありますが、 EditorForだと、モデルの型に適したフォームを作成する TextBoxForだと、常にテキストボックスを作成する という点を、複数のプラウザで確認できました。 Datetime型で試した際、 EditorForだとvalueの値が「2019/01/17」 TextBoxForだとvalueの値が「2019/01/17 0:00:00」という部分の違いも発見できました。 二時間ぐらいプラウザを変えたりして色々試したんですが、 混乱してきたので試すのはこれ以上やめておきます。 まあ難しいです。 一応、日付データはSqlServerから持ってきていて、 メタデータクラスを設定してたりするので、人によって結果が違うかもしれません。 わざわざご連絡いただき、ありがとうございました。
退会済みユーザー

退会済みユーザー

2019/01/25 06:02

要するに、EditorFor を利用することを前提に、上に書いた様に付与した属性が上手く働くような配慮がいろいろとされているようですので、TextBoxFor ではなくて EditorFor を使うのがお勧めということです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問