QA@IT

asp.net Javascriptによるasp:Labelタグの生成について

39653 PV

基本的な事で恐縮ですが、
以下のJavascriptをaspファイルに記載し、
IDがtest1~20のasp:Labelを生成したいのですが、
「サーバー タグが正しく形成されていません。 」
のエラーが出てしまいます。

<script language="javascript" type="text/javascript">
for (i = 1; i < 20; i++) {
    document.write("<asp:Label ID=test" + i + " runat=server ></asp:Label>");
}
</script>

以下でもエラーがでます。

<script language="javascript" type="text/javascript">
var aa;
for (i = 1; i < 20; i++) {
        aa = "<asp:Label ID=test" + i + " runat=server ></asp:Label>"
    document.write(aa);
}
</script>

以下のように、iを連結しなければ、エラーは出ないのですが、(iではなく空文字を連結しても上記エラーがでます)
連結するとエラーがでるのはどうしてでしょうか。

<script language="javascript" type="text/javascript">
for (i = 1; i < 20; i++) {
    document.write("<asp:Label ID=test runat=server ></asp:Label>");
}
</script>

動的にasp:Label IDを連番付けで生成する方法がありましたらご教授をお願いします。

回答

javascriptはブラウザで動作しますが、ブラウザでaspコントロールを作成することはできません。

「連結しないとエラーが出ない」というのは

<asp:Label ID=test" + i + " runat=server ></asp:Label>
は、asp:labelのタグとして不正で

<asp:Label ID=test runat=server ></asp:Label>
は、asp:labelのタグとして問題ない

という話になります。
このときjavascript中にあるかどうかは関係ありません。そこにある「文字」がASP.NETにとってタグとしておかしいかどうかです。
(やったことないので結果がどうなるのかはわかりませんが、spanタグになってdocument.writeで出力されるから改行が無ければ一応動くのかな?)

javascriptはasp.netがページ(aspx)からサーバータグを解析(正確にはコンパイル。エラーはこのとき出ている)したり、サーバー側のコードを処理したりして、htmlを作成し、ブラウザに返した後で、ブラウザで実行されます。
サーバータグ(asp:~とかrunat=serverとか)の解析の後に動くわけですから、仮にそれがうまく動いたとして、その後にたくさん出力できたとしても、ASP.NETは増えた分の存在を知りませんのでつじつまが合わないのでエラーになるでしょう。

動的にコントロールを作成するサンプルはmicrosoftのサイトにもありましたのでそれを張っておきます。
基本的にはaspxのコードビハインド(.cs/.vb)とか、aspx上にコードを記述(<%%>)したりして作成することになるでしょう。

https://support.microsoft.com/ja-jp/kb/317794

編集 履歴 (0)
  • >javascript中にあるかどうかは関係ありません。そこにある「文字」がASP.NETにとってタグとしておかしいかどうか
    クライアントスクリプトブロックの中であれば、その文字がASP.NET(サーバ側)にとって正しいかおかしいかは関知するところではないのではないかと思うのですが
    -
  • aspxをレンダリングする上で「クライアントスクリプトブロックの中だから無視する」という事はないと思います。
    簡単な例では
    var x = "<%=1%>";
    というのはクライアントスクリプトブロックであってもレンダリングされるべきです。
    -
  • <asp:Label ID=Test runat=server>abc</asp:Label> のレンダリングによって生成される、'<span id="Test">abc</span>' という文字列をどう利用することが正しいかどうかまでは判断できないでしょうし、できるのはレンダリング対象の文字列として正しいかどうかだけと思いますが。 -
  • var x = "<%=1%>";でサーバ側が解釈すべきは<%%>のブロック内のみです
    それ以外のクライアントスクリプトブロックはサーバ側でなんら変更されるべきではありません
    クライアント側でどんなものをレンダリングしようとしても、それはサーバ側に関係ない話です
    -
  • クライアントスクリプトで<asp:Label>をレンダリングしたのであれば、クライアントブラウザ上で生成されるのは<asp:Label>要素です。<span>になったりしないしできません
    どのような文字列であってもクライアントスクリプトが正しいかどうかは判断できませんよね
    判断できないのに、検査してエラーにするからおかしな動作なのです
    -
  • クライアントスクリプトで<asp:Label>をレンダリングとはなんでしょう。なぜクライアントスクリプトの話が出てきますか?検査エラーとは何を言っていますか?
    runat=serverでも<asp:Label>がブラウザに送信されると思ってますか?
    -
  • 「どのような文字列であってもクライアントスクリプトが正しいかどうかは判断できませんよね」
    これは正しいですし、ASP.NETは判断してません。<asp:Label>内をASP.NETのルールに従いサーバー側でHTML要素として書き換えられないと言っているだけですよ。ASP.NETはサーバーサイドのフレームワークです。
    -
  • 実際にDOM上に<asp:Label>要素を出力しようとするのはクライアントスクリプトです。(この例の)document.writeはjavascriptの命令です
    .aspxに書かれている<asp:Label>は、クライアントスクリプトの文字列データです。サーバサイドにとってタグではありません
    -
  • 今回の話は、javascriptで"あいうえお"と出力しようとしたら、あいうえおは不正だってサーバ側エラーが出たって話と同じ構造だと思うのですが -
  • エラーの出ないパターンをいくつか試してみればわかると思いますが、実際に出力されるhtml中に書かれる文字列は<asp:Label>のままですよ
    つまり「サーバー側でHTML要素として書き換える」ような事は実際には起こりません
    出来る出来ない以前に、やってはいけないのです。サーバタグではなく文字列データですから
    -
  • > エラーの出ないパターンをいくつか試してみればわかると思いますが~

    runat=sererがない=サーバータグではないのでレンダリング対象ではないのでそうです。"あいうえお"もそうです。
    しかし <asp:Label ID=test" + i + " runat=server ></asp:Label> はサーバータグの条件にマッチしてしまうのでエラーというだけの話です。


    -
  • その文字列がクライアントスクリプトかどうかは、ASP.NETがHTMLを出力した後に決まります。 -
  • aspxファイル上に書かれている文字列をC#/VBに翻訳するのはASP.NETです(仮にあいうえおはどこに書いても不正だってaspxでルールができればエラーです)。サーバー処理の結果がHTMLとして送信されます。その後はもちろんASP.NETの検証は入りません。ブラウザが受け取って、(クライアント)スクリプトの出番です。

    平行線をたどっている気がするのでこれ以上のコメントは控えます。
    -
  • >サーバータグの条件にマッチしてしまうのでエラー
    マッチしても、実際にはサーバタグではないしサーバタグとしての動作も行われないのですが
    単純に文字列だけみてサーバタグだとしてパースエラー出すのがおかしいって話です
    エラーの無いパターンで出力されてる内容が<span>になってるとか言うならまだ納得できるんですがね
    -
  • document.write('<asp:Label ID=test runat=server ></asp:Label>') と書いた時にはエラー無くspanになるはずです(document.writeの引用符がシングルクォートじゃないとjavascriptでエラーになりますが)。
    run"+"at=serverの例は、サーバータグとは判断されていないので文字列がそのまま残っています。
    -
  • >その文字列がクライアントスクリプトかどうかは、ASP.NETがHTMLを出力した後に決まります
    初めからクライアントスクリプトとして.aspxに記述してるので、無加工のままクライアントスクリプトになってもらわないと困るって話ですが
    サーバコントロールや<%%>ブロック以外はサーバ側で操作されるべきものではありません
    -
  • 「"<asp:Label ID=test" + i + " runat=server ></asp:Label>"」 これが文字列としてそのままHTMLに残らないのはおかしい(=これはコンパイル対象にいれないようにうまくやれ)という思いもあるなら、それは開発チームに課題として提案するしかないかと。 -
  • まあ、これができたとして、もともとのさーばコントロールを動的に追加したいって話が実現できるわけではないので
    これ以上コメントしないってならそれでこの話は打ち切りですね
    -
  • タイミングがかぶりましたが、私が最後に追加したのはこれ含め3件です。
    とりあえず打ち切りですね。
    -

サーバー側で起こっていることと、クライアント側で起こっていることの区別がついてないのでは?

Label というのはサーバーコントロールでサーバー側のものです。それが ASP.NET によって HTML の span 要素に変換されてクライアントに送られ、それがブラウザ上に span 要素として表示されるのです。

JavaScript はクライアント側の処理に限って使えるもので JavaScript ではサーバーコントロールの追加は不可能です。 JavaScript で <asp:Label ... ></asp:Label> をブラウザの HTML に追加しても何の意味のないのは分かりますか?

Label というサーバーコントロールを動的に追加したいのであれば、コードビハインドで Page の Init イベントあたりで Label コントロールを動的に生成し、Page に追加することを考えてください。

編集 履歴 (1)
  • サーバ側とクライアント側の区別の問題はあるのですが、今回の例では(意味はないとしても)クライアント側の問題がサーバエラーとして表示されてるんじゃないかと思うのですが -
  • 今さらながらのレスですみません。
    > サーバエラーとして表示されてる
    .aspx ファイルはデフォルトでサーバー側でコンパイルされますが、その時インラインで書かれた JavaScript の runat=server 要素や asp プレフィックスにコンパイラが反応しているようです。
    -
  • 不適切なやり方が想定外の結果を生んだということに過ぎず、個人的には、ASP.NET として適切な動作か否かを議論しても意味がないと思っています。 -

javascriptがブラウザ上で動くのはflied_onionさんの回答の通りだし、クライアント側(javascript)でサーバタグを追加しても意味がないのはSurferOnWwwさんの回答の通りですが
そうであるなら、クライアントスクリプトブロック中のエラーがサーバ側エラーとなるのはおかしな話ではあります
試してみた感じでは、.aspxファイルのコンパイル時に、クライアントスクリプトの中も構文チェックして、そのチェック内容に不備があるんじゃないかと

document.write("<asp:Label ID=test" + i + " runat=server ></asp:Label>");

を、runatの部分で文字列を分割して

document.write("<asp:Label ID=test" + i + " run"+"at=server ></asp:Label>");

とした場合、スクリプトの動作としては実質同じなのに、こちらだとサーバエラーになりません
上の方法でも、純粋なhtmlで動作させればクライアントスクリプトとしては動作はします

つまり直接のエラーの原因としては、asp.netの.aspxファイルの解析に問題がある、ということになるんじゃないでしょうか

IE11の開発者ツールで見る限り、どちらにしても、クライアント上のDOMにlabelタグの要素は追加されてるようです
ただし、それをポストバックさせてもサーバ側で処理できるわけではないので、この例ではエラーが出ないとしても意味はないですけどね

編集 履歴 (1)
  • > スクリプトの動作としては実質同じなのに

    その前にASP.NETのコンパイルが入ります。javascriptがおかしいといっているのではなく runat=serverな <asp:Label ID=test" + i + " runat=server ></asp:Label> というタグがおかしいからそもそもHTMLを生成できないというエラーです。
    -
  • クライアント側スクリプトブロックの動作を、サーバ側でコンパイルすることはできませんよ
    だって、サーバ側が未知のクライアント側言語の可能性もあるし、コンパイルしたとしても、html中のテキストとしてしかクライアントに渡せませんから
    <asp:Label>というのは、あくまでクライアントスクリプト中の文字列データにすぎません。そもそもhtmlとして解釈するものではないです
    -
  • <asp:Label ID=test" + i + " runat=server >がサーバ側タグとして不正なのでエラーだというなら
    たとえばrunat=clientなどとしてみても、当然エラーにならなければなりませんが、これはエラーになりません
    ID=test1 runat=clientといった属性のasp:clientな要素がブラウザ上のDOMに追加されるだけです
    -
  • 最後の一文は
    asp:Label な要素がブラウザ上のDOMに追加されるだけです
    の間違いです
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。