Используйте генерацию кода управления сервером ASP.Net из .ashx

Я пытаюсь взять существующую кучу кода, которая ранее была на полной странице .aspx, и сделать то же самое в обработчике .ashx.

Код создал объект HtmlTable, добавил строки и ячейки в эти строки, затем добавил эту html-таблицу в коллекцию элементов управления .aspx, а затем добавил ее в div, который уже был на странице.

Я пытаюсь сохранить код в такте, но вместо того, чтобы поместить элемент управления в div, фактически сгенерировать html, и я верну его в виде большого фрагмента текста, который можно вызвать через клиентскую часть AJAX.

HtmlTable выдает ошибки, когда я пытаюсь использовать свойство InnerHtml (говорит, что оно не поддерживается), и когда я пытаюсь использовать RenderControl, после создания сначала объекта TextWriter, а затем объекта HtmlTextWriter, я получаю сообщение об ошибке, что страница не может быть нулевой.

Кто-нибудь делал это раньше? Какие-либо предложения?


person Matt Dawdy    schedule 28.04.2010    source источник


Ответы (2)


*Самая последняя указана выше.

Хорошо, даже после обновления Мэтта есть обходной путь;)

Во-первых, мы должны использовать страницу с form внутри. В противном случае мы не сможем добавить элемент управления ScriptManager. Еще одно: элемент управления ScriptManager должен быть первым элементом управления в форме. Дальше проще:

Page page = new Page();
Button button = new System.Web.UI.WebControls.Button
{
    ID = "btnSumbit",
    Text = "TextButton",
    UseSubmitBehavior = true
};
HtmlForm form = new HtmlForm
{
    ID="theForm"
};
ScriptManager scriptManager = new ScriptManager
{
    ID = "ajaxScriptManager"
};
form.Controls.Add(scriptManager);
form.Controls.Add(button);
page.Controls.Add(form);

using (StringWriter output = new StringWriter())
{
    HttpContext.Current.Server.Execute(page, output, false);

    context.Response.ContentType = "text/plain";
    context.Response.Write(output.ToString());
}

Это работает. Вывод довольно большой, поэтому я решил не включать его в свой ответ :)


На самом деле, есть обходной путь. Да, мы можем отобразить элемент управления в обработчике.

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

Элемент управления 'btnSumbit' типа 'Кнопка' должен быть помещен внутри тега формы с runat=server.

public class FormlessPage : Page
{
    public override void VerifyRenderingInServerForm(Control control)
    {
    }
}

Во-вторых, никто не может помешать нам создать экземпляр нашей страницы FormlessPage. А теперь давайте добавим туда элемент управления (я решил добавить элемент управления Button для примера, но вы можете использовать любой).

FormlessPage page = new FormlessPage();
Button button = new System.Web.UI.WebControls.Button
{
    ID = "btnSumbit",
    Text = "TextButton",
    UseSubmitBehavior = true
};
page.Controls.Add(button);

В-третьих, давайте зафиксируем вывод. Для этого используем метод HttpServerUtility.Execute:

Выполняет обработчик для указанного виртуального пути в контексте текущего запроса. System.IO.TextWriter фиксирует выходные данные выполненного обработчика, а логический параметр указывает, очищать ли коллекции System.Web.HttpRequest.QueryString и System.Web.HttpRequest.Form.

Вот код:

using (StringWriter output = new StringWriter())
{
    HttpContext.Current.Server.Execute(page, output, false);

    context.Response.ContentType = "text/plain";
    context.Response.Write(output.ToString());
}

Результат будет:

<input type="submit" name="btnSumbit" value="TextButton" id="btnSumbit" />

Кроме того, я могу порекомендовать статью ScottGu Совет/подсказка: крутая техника шаблонизации пользовательского интерфейса для использования с ASP.NET AJAX для сценариев без UpdatePanel. Надеюсь, вы могли бы найти там много полезного.

person Alex    schedule 28.04.2010
comment
Это отлично работает для 90% того, что мне нужно, так что большое спасибо за это. Однако у меня осталась 1 загвоздка. Здесь есть элементы управления Telerik, которые необходимо отобразить. Я могу добавить управление, но им нужен менеджер сценариев, иначе он взрывается при рендеринге. Я попытался добавить его в качестве элемента управления на страницу, но затем он вылетает с ошибкой объекта, не установленного в экземпляр. - person Matt Dawdy; 29.04.2010

Другой вариант — разместить конвейер ASP.NET HTTP в своем процессе, отобразить страницу в потоке и прочитать HTML-код, который необходимо отправить из потока HttpListenerContext.Response.OutputStream после обработки страницы.

Подробности в этой статье: http://msdn.microsoft.com/en-us/magazine/cc163879.aspx

person Damien    schedule 28.04.2010