Удалить ctl00 $ ContentBody $ из обработанного идентификатора элемента управления - PullRequest
7 голосов
/ 06 мая 2009

Я внес некоторые изменения в существующее приложение, которое ранее было простым HTML и Javascript. Чтобы добавить функциональность на стороне сервера, я выбрал ASP.NET и воспользовался концепцией Master Page. К сожалению, в одной огромной веб-форме все идентификаторы элементов управления искажены префиксом "ctl00 $ ContentBody $". Я прикрепил runat = "server" ко всем элементам управления INPUT, что и изменило идентификаторы. Теперь, когда идентификаторы были изменены, Javascript (который написан так плохо, что я даже не могу его прочитать, и у меня большой опыт работы с JS) полностью сломан.

Итак, как я могу предотвратить превращение этой ерунды в HTML? Я надеялся каким-то образом создать класс, который наследует HtmlGenericControl (я не использую веб-элементы управления, я просто прикрепил runat = "server" к каждому входному тегу) и каким-то образом переопределил логику, которая прикрепляет этот "идентификатор контейнера" начало атрибутов ID и NAME. Тогда я мог бы использовать tagMapping в web.config для глобальных изменений. Это возможно?

Ответы [ 9 ]

6 голосов
/ 06 мая 2009

Небольшое утешение на данный момент, но эта «особенность» будет исправлена ​​в Asp.Net 4.0. Вы получите настраиваемое свойство ClientID.

Кроме этого, другие ответы хороши.
Используйте <% = control.ClientID%>

или добавьте JQuery и используйте $ ("[id $ = 'myId'])

Или, в ваших входных тегах, не ставьте runtime = 'server'. Вы должны быть в состоянии получить значения через член Form (как в традиционном asp)

Или пропустите Asp.Net WebForms и перейдите к Asp.Net MVC, который дает вам полный контроль над созданной разметкой HTML. Вы должны изменить то, как вы делаете вещи, немного больше, но это может вас расстроить.

4 голосов
/ 03 мая 2011

Я попробовал этот кусок кода, и по какой-то причине он реорганизует всю страницу:

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

2 голосов
/ 06 мая 2009

Я не знаю способа удалить контейнер именования из префикса к идентификатору элемента управления. В прошлом я использовал удобный метод для поиска таких идентификаторов в javascript, который перебирает имена тегов и использует регулярное выражение, совпадающее с тем, которое заканчивается на $realID, где realID - это идентификатор, который я дал контроль в разметке. Теперь я бы использовал jQuery для этого с помощью селектора вроде:

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

Который в основном делает то же самое, что и мой старый удобный метод, но он встроен в фреймворк.

0 голосов
/ 09 февраля 2012

На самом деле, чтобы прокрутить ответ Джоша, я обнаружил, что первое решение, представленное ниже, проблематично, поскольку другие элементы управления вводом и PostBacks работают неправильно. Поэтому вместо того, чтобы вносить пустые изменения, я выбрал второе решение ниже, чтобы изменить JavaScript, а не имя элемента.

Решение Джоша :

Код-Behind:

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 (ПРИМЕЧАНИЕ: я не мог изменить идентификатор, который может решить это решение):

Code-Behind:

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:

JavaScript в aspx-файле, где списки радиокнопок используют соглашение 'rbl [name]':

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

Code-Behind:

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"));
}
0 голосов
/ 17 ноября 2011

Я хотел бы добавить свои два цента к этому:

Я сделал это таким образом (в принятом ответе), но мне показалось, что переопределение элемента управления 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));
}
0 голосов
/ 09 июня 2011

Отметьте это: http://clientidless.codeplex.com/ - вы можете отключить ClientID практически для любого элемента управления. Вот демо: http://show -demos.net / NoClientId / - нажмите «рендер без идентификаторов» или «рендеринг с идентификаторами», чтобы увидеть, как изменяется размер страницы. Просмотр источника, чтобы увидеть разницу.

0 голосов
/ 06 мая 2009

Быстро и грязно - вот что мне было нужно, ребята. И благодаря 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
0 голосов
/ 06 мая 2009

Поскольку кажется, что вы просто пытаетесь удалить идентификаторы клиента из окончательного вывода, вы можете переопределить событие рендеринга на своей странице и использовать регулярное выражение для их удаления. Вы можете увидеть пример в посте ниже.

Перезаписать вывод страницы ASP.NET

После того, как вы получите текст, с которым работаете, вы, скорее всего, напишите что-то вроде ...

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

А затем запишите окончательный вывод в HtmlTextWriter.

Надеюсь, это поможет.

0 голосов
/ 06 мая 2009

Насколько я знаю, нет способа удалить их по той самой причине, по которой вы сказали; чтобы они были уникальными. На мой взгляд, у вас есть два варианта:

  1. Создайте переменную JS и добавьте ее ко всем вызовам JS, чтобы она искала правильный идентификатор
  2. Используйте <% = control.ClientID%> в своем javascript, чтобы он использовал новый идентификатор.

С # 1, если любой из ваших входов находится внутри какого-либо другого тега сервера, он не будет работать. Это склонно ко многим проблемам, поэтому я бы пошел с # 2, если вы можете.

2 зависит от того, находится ли javascript на самой странице или если JS является внешним, вам необходимо иметь возможность передавать идентификаторы. Этот код не проверен и предназначен только для примера, но я имею в виду следующее:

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

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

Это действительно зависит от того, как реализован ваш JS.

...