レンダリングされたコントロールIDからctl00 $ ContentBody $を削除します

StackOverflow https://stackoverflow.com/questions/827723

  •  06-07-2019
  •  | 
  •  

質問

以前は単純なHTMLとJavascriptだった既存のアプリケーションにいくつかの変更を加えました。サーバー側の機能を追加するために、ASP.NETを選択し、マスターページの概念を活用しました。残念ながら、1つの巨大なWebフォームでは、コントロールIDはすべて<!> quot; ctl00 $ ContentBody $ <!> quot;でマングルされています。プレフィックス。 runat = <!> quot; server <!> quot;を追加しました。すべてのINPUTコントロールで、IDを変更したものを制御します。 IDが変更されたので、Javascript(非常に貧弱に書かれているので読むことすらできず、JSの経験も豊富です)は完全に壊れています。

では、このナンセンスがHTMLにレンダリングされるのを防ぐにはどうすればよいですか?私は何らかの形でHtmlGenericControlを継承するクラス(私はWebコントロールを使用せず、runat = <!> quot; server <!> quot;をすべての入力タグに追加する)と何らかの方法でロジックをオーバーライドできることを望んでいましたこの<!> quot; container id <!> quot; IDおよびNAME属性の先頭。次に、web.configでtagMappingを使用して、グローバルな変更を行うことができます。これは可能ですか?

役に立ちましたか?

解決 6

私が必要としたのは、素早くて汚いことです。そして、HBossのおかげで、非常にシンプルなソリューションを思いつくことができました。問題のページのコードビハインドに、このサブルーチンを追加しました...

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
    Dim Html As New StringWriter()
    Dim Render As New HtmlTextWriter(Html)
    MyBase.Render(Render)
    writer.Write(Html.ToString().Replace("name=""ctl00$ContentBody$", "name=""").Replace("id=""ctl00_ContentBody_", "id="""))
End Sub

他のヒント

今のところは小さな慰めですが、この<!> quot; feature <!> quot; Asp.Net 4.0で修正される予定です。設定可能なClientIDプロパティを取得します。

それ以外は、他の応答は良好です。
<!> lt;%= control.ClientID%<!> gt;

を使用します

またはJQueryをスローして、$(<!> quot; [id $ = 'myId'])を使用します

または、入力タグにruntime = 'server'を配置しないでください。 Formメンバを介して値を取得できるはずです(従来のaspと同様)

または、Asp.Net WebFormsをスキップして、生成されるHTMLマークアップを完全に制御できるAsp.Net MVCにスキップします。あなたは物事のやり方をもう少し変更する必要がありますが、それはあなたにとってそれほどイライラしないかもしれません。

このコードを試してみたところ、何らかの理由でページ全体が再編成されました。

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
    Dim Html As New StringWriter()
    Dim Render As New HtmlTextWriter(Html)
    MyBase.Render(Render)
    writer.Write(Html.ToString().Replace("name=""ctl00$ContentBody$", "name=""").Replace("id=""ctl00_ContentBody_", "id="""))
End Sub

URLを送信する例を表示したい場合

コントロールIDの前に名前付けコンテナーを追加する方法はありません。過去に便利なメソッドを使用して、タグ名を反復処理し、$realIDで終わるものと一致する正規表現を使用するjavascriptでそのようなIDを検索しました。ここで、realIDは指定したIDですマークアップのコントロール。ここで、次のようなセレクタを使用して、これにjQueryを使用します。

 $('[id$="realID"]')

基本的には以前の便利なメソッドと同じことを行いますが、フレームワークに組み込まれています。

私が知る限り、あなたが言ったまさにその理由でそれらを削除する方法はありません。それらが一意であることを確認します。私がそれを見る方法には、2つのオプションがあります:

  1. JS変数を作成し、すべてのJS呼び出しの前に追加して、正しいIDを探す
  2. <!> lt;%= control.ClientID%<!> gt;を使用します。 JavaScriptで新しいIDを使用します。

#1では、入力のいずれかが他のサーバータグ内にある場合、機能しません。これには多くの問題が発生する可能性があるため、可能であれば#2に進みます。

2は、ページ自体にあるJavaScriptに依存するか、JSが外部の場合、IDを渡すことができる必要があります。このコードはテストされておらず、例にすぎませんが、ここに私が意味するものがあります:

function alertValue(textID){
     alert(document.GetElementById(textID).value);
}

<input id="txtBox" runat="server" type="Button" text="Click Me" onClick="alertValue('<%= txtBox.ClientID %>');" />

JSの実装方法によります。

最終出力からクライアントIDを削除しようとしているように見えるため、ページ上のレンダリングイベントをオーバーライドし、正規表現を使用してそれらを削除できる場合があります。以下の投稿で例を見ることができます。

ASP.NETページ出力を書き換えます

作業中のテキストを取得したら、次のように書くことができます...

output = Regex.Replace(
    output, 
    @"id\=""ctl00\$[^\""]*""", 
    string.Empty, 
    RegexOptions.IgnoreCase
    );

そして、最終出力をHtmlTextWriterに書き込みます。

役立つこと。

これを確認してください: http://clientidless.codeplex.com/ -ClientIDをオフにして、任意のコントロール。 デモは次のとおりです。 http://show-demos.net/NoClientId/ -<!> quotを押します; IDなしでレンダリング<!> quot;または<!> quot; IDでレンダリング<!> quot;ページサイズがどのように変化するかを確認します。ソースを表示して違いを確認してください。

これに2セントを追加します:

この方法で(受け入れられた回答で)行いましたが、Renderコントロールをオーバーライドして新しいTextWriterに書き込み、そのコンテンツをページのOutputStreamに書き込むことは、リソースの無駄使いのように思えます。これは、HtmlTextWriterクラスをオーバーライドする小さなクラスを作成することで実行できることがわかりました。この方法では、ストリームに直接書き込み、テキストが属性として使用されている場合にのみテキストを置換しようとします。

public class CleanHtmlTextWriter : HtmlTextWriter
{
    private const string MASTER_PAGE_ID = "ctl00";
    private const string CONTENT_NAME = "MainContent";

    public CleanHtmlTextWriter(TextWriter writer)
        : base(writer)
    {
    }

    public override void WriteAttribute(string name, string value)
    {
        if (name == "name")
            value = value.Replace(CONTENT_NAME + "$", "").Replace(MASTER_PAGE_ID + "$", "");

        if (name == "id")
            value = value.Replace(CONTENT_NAME + "_", "").Replace(MASTER_PAGE_ID + "_", "");

        base.WriteAttribute(name, value);
    }
}

その後、次のように使用できます:

protected override void Render(HtmlTextWriter writer)
{
    base.Render(new CleanHtmlTextWriter(writer));
}

実際、Joshの答えに便乗して、以下の最初の解決策は、他の入力制御要素とPostBacksが正しく機能しないという問題があることがわかりました。そこで、空白の変更を加えるのではなく、要素名ではなくJavaScriptを変更するために、以下の2番目の解決策を選択しました。

ジョシュのソリューション

コードビハインド:

protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
    StringWriter Html = new StringWriter();
    HtmlTextWriter Render = new HtmlTextWriter(Html);
    base.Render(Render);
    writer.Write(Html.ToString()
        .Replace("name=\"ctl00$ContentBody$", "name=\"")
        .Replace("id=\"ctl00_ContentBody_", "id=\""));
}

ソリューション1 、PostBackの問題(注:このソリューションを解決するIDを変更できませんでした):

コードビハインド:

protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
    var html = new StringWriter();
    var render = new HtmlTextWriter(html);
    base.Render(render);
    writer.Write(html.ToString()
        .Replace("name=\"ctl00$contentBody$rbl",
                 "name=\"ctl00_contentBody_rbl"));
}

ソリューション2 、JavaScriptを変更するには:

ラジオボタンリストが 'rbl [name]'の規則を使用するaspxファイルのJavaScript:

if (!validateRadioButtonList("<% =rblTitle.ClientID %>"))

コードビハインド:

protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
    var html = new StringWriter();
    var render = new HtmlTextWriter(html);
    base.Render(render);
    writer.Write(html.ToString()
        .Replace("validateRadioButtonList(\"ctl00_contentBody_rbl", 
                 "validateRadioButtonList(\"ctl00$contentBody$rbl"));
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top