Как вернуть XML в ASP.NET?

Я столкнулся с множеством полурешений для задачи возврата XML в ASP.NET. Я не хочу слепо копировать и вставлять код, который обычно работает большую часть времени; Я хочу правильный код, и я хочу знать, почему это так. Я хочу критики; Я хочу информацию; Я хочу знания; Я хочу понимания.

Ниже приведены fragmentы кода в порядке возрастания сложности, представляющие некоторые частичные решения, которые я видел, включая некоторые из дальнейших вопросов, которые каждый из них вызывает, и которые я хотел бы ответить здесь.

Тщательный ответ должен касаться того, почему мы должны иметь или не иметь ни одного из следующих факторов, или объяснить, почему это не имеет значения.

  • Response.Clear ();
  • Response.ContentType = “text / xml“;
  • Response.ContentEncoding = Encoding.UTF8;
  • Response.ContentEncoding = Encoding.UTF16;
  • Response.ContentType = “text / xml; charset = utf-8”;
  • Response.ContentType = “text / xml; charset = utf-16”;
  • Response.End ()
  • Использование aspx с вырезанными файловыми файлами
  • Использование файла ashx

В конце концов, представьте, что вам нужно написать содержимое вспомогательной функции следующим образом:

///Use this call inside your (Page_Xxx) method to write the ///xml to the web client.  ///See for https://stackoverflow.com/questions/543319/how-to-return-xml-in-asp-net ///for proper usage. public static void ReturnXmlDocumentToWebClient( XmlDocument document, Page page) { ... } 

Каждое появившееся решение начинается с того, что вы берете пустую страницу aspx и обрезаете весь HTML из переднего файла (что вызывает предупреждения в Visual Studio):

  

Затем мы используем событие Page_Load для записи на выход:

 protected void Page_Load(object sender, EventArgs e) { String xml = "Hello, world!"; Response.Write(xml); } 

Нужно ли изменить ContentType на «text / xml» ? То есть:

 protected void Page_Load(object sender, EventArgs e) { String xml = "Hello, world!"; Response.ContentType = "text/xml"; Response.Write(xml); } 

Нужно ли нам сначала называть Response.Clear ?

 protected void Page_Load(object sender, EventArgs e) { String xml = "Hello, world!"; Response.Clear(); Response.ContentType = "text/xml"; Response.Write(xml); } 

Нужно ли нам это называть? Does not Response.Clear сделать предыдущий шаг, чтобы убедиться, что код в переднем файле пуст (даже не пробел или возврат каретки) вне ненужным?

Does Response.Clear делает его более надежным, если кто-то оставил пустую строку или пробел в файле кода?

Использует ashx так же, как пустой основной файл aspx, потому что понятно, что он не будет выводить HTML?


Нужно ли нам называть Response.End ? То есть:

 protected void Page_Load(object sender, EventArgs e) { String xml = "Hello, world!"; Response.Clear(); Response.ContentType = "text/xml"; Response.Write(xml); Response.End(); } 

Что еще может произойти после Response.Write которая нуждается в нас, чтобы закончить ответ прямо сейчас ?


Является ли контент-тип text/xml достаточным или вместо него должен быть text / xml; charset = utf-8 ?

 protected void Page_Load(object sender, EventArgs e) { String xml = "Hello, world!"; Response.Clear(); Response.ContentType = "text/xml; charset=utf-8"; Response.Write(xml); Response.End(); } 

Или это конкретно не так ? Имеет ли кодировка в типе контента, но не устанавливает свойство, завинчивает сервер?

Почему не какой-либо другой тип контента, например:

  • UTF-8,
  • UTF-16
  • UTF-16

Должна ли кодировка указываться в Response.ContentEncoding ?

 protected void Page_Load(object sender, EventArgs e) { String xml = "Hello, world!"; Response.Clear(); Response.ContentType = "text/xml"; Response.ContentEncoding = Encoding.UTF8; Response.Write(xml); Response.End(); } 

Использует Response.ContentEncoding лучше, чем заклинило его в Response.ContentType ? Это хуже? Поддерживается ли первая? Это последнее?


Я действительно не хочу писать String; Я хочу выписать XmlDocument . Кто-то предлагает мне использовать XmlWriter :

 protected void Page_Load(object sender, EventArgs e) { XmlDocument xml = GetXmlDocumentToShowTheUser(); Response.Clear(); Response.ContentType = "text/xml"; Response.ContentEncoding = Encoding.UTF8; using (TextWriter textWriter = new StreamWriter( Response.OutputStream, Encoding.UTF8)) { XmlTextWriter xmlWriter = new XmlTextWriter(textWriter); // Write XML using xmlWriter //TODO: How to do this? } } 

Обратите внимание на использование Response.OutputStream , а не Response.Write . Это хорошо? Плохо? Лучше? Хуже? Быстрее? Помедленнее? Больше памяти интенсивнее? Меньше памяти?


Я читал, что вы должны

XML в методе Render () страницы, чтобы избежать проблем с chunking, возникающих при использовании Page_Load ().

Что такое chunking ? В чем проблемы с блоками, и как их использовать с помощью Page_Render ?


Я не хочу писать содержимое моего объекта XmlDocument в строку, а затем писать, потому что это отнимает память. То есть любой из них был бы плохим:

 Response.Write(doc.ToString()); Response.Write(doc.InnerXml); xmlWrite.WriteString(doc.ToString()); xmlWrite.WriteString(doc.InnerXml); 

Похожие вопросы

Как вернуть XML в ASP.NET

Рекомендации

Как вернуть XML из ASPX в ASP.NET 1.1

Написание вывода XML на веб-страницу ASP.NET

Как вы выводите XML из ASP.NET?

Создание обработчика ASHX в ASP.NET

Я нашел правильный способ вернуть XML клиенту в ASP.NET. Я думаю, что если я укажу неверные пути, это сделает правильный путь более понятным.

Неправильно:

 Response.Write(doc.ToString()); 

Неправильно:

 Response.Write(doc.InnerXml); 

Неправильно:

 Response.ContentType = "text/xml"; Response.ContentEncoding = System.Text.Encoding.UTF8; doc.Save(Response.OutputStream); 

Верный:

 Response.ContentType = "text/xml"; //Must be 'text/xml' Response.ContentEncoding = System.Text.Encoding.UTF8; //We'd like UTF-8 doc.Save(Response.Output); //Save to the text-writer //using the encoding of the text-writer //(which comes from response.contentEncoding) 

Использование TextWriter

Не используйте Response.OutputStream

Использовать Response.Output

Оба являются streamами, но Output является TextWriter . Когда XmlDocument сохраняет себя в TextWriter , он будет использовать кодировку, указанную этим TextWriter. XmlDocument автоматически изменит узел объявления xml в соответствии с кодировкой, используемой TextWriter. например, в этом случае узел объявления XML:

  

станет

  

Это связано с тем, что TextWriter настроен на UTF-8. (Еще об этом мгновенно). Поскольку TextWriter передается символьными данными, он будет кодировать его с помощью последовательностей байтов, соответствующих его кодировке.

Неправильно :

 doc.Save(Response.OutputStream); 

В этом примере документ неправильно сохраняется в OutputStream, который не выполняет никаких изменений в кодировке и может не соответствовать кодировке содержимого ответа или указанному кодированию узла объявления XML.

Верный

 doc.Save(Response.Output); 

Документ XML правильно сохраняется в объекте TextWriter, гарантируя правильную обработку кодировки.


Установить кодировку

Кодировка, предоставляемая клиенту в заголовке:

 Response.ContentEncoding = ... 

должен соответствовать кодировке XML-документа:

  

должен соответствовать фактической кодировке, присутствующей в последовательностях байтов, отправленных клиенту. Чтобы все три соглашения совпали, установите одну строку:

 Response.ContentEncoding = System.Text.Encoding.UTF8; 

Когда кодировка задана на объекте Response , она устанавливает ту же кодировку в TextWriter . Набор кодировки TextWriter заставляет XmlDocument изменять объявление xml :

  

когда документ сохранен:

 doc.Save(someTextWriter); 

Сохранить в ответ

Вы не хотите сохранять документ в двоичном streamе или писать строку:

Неправильно:

 doc.Save(Response.OutputStream); 

Здесь XML некорректно сохраняется в двоичном streamе. Конечная последовательность кодирования байтов не будет соответствовать объявлению XML или кодированию содержимого ответа веб-сервера.

Неправильно:

 Response.Write(doc.ToString()); Response.Write(doc.InnerXml); 

Здесь XML неправильно преобразован в строку, которая не имеет кодировки. Узел объявления XML не обновляется, чтобы отражать кодировку ответа, и ответ неправильно кодируется в соответствии с кодировкой ответа. Кроме того, хранение XML в промежуточной строке отнимает память.

Вы не хотите, чтобы сохранить XML в строку или добавить XML в строку и response.Write строку, потому что:

 - doesn't follow the encoding specified - doesn't set the XML declaration node to match - wastes memory 

Используйте doc.Save(Response.Output);

Не используйте doc.Save(Response.OutputStream);

Не используйте Response.Write(doc.ToString());

Не используйте ‘Response.Write (doc.InnerXml); `


Задайте тип содержимого

Тип ContentType для ответа должен быть установлен как "text/xml" . Если нет, клиент не будет знать, что вы отправляете XML.

Итоговый ответ

 Response.Clear(); //Optional: if we've sent anything before Response.ContentType = "text/xml"; //Must be 'text/xml' Response.ContentEncoding = System.Text.Encoding.UTF8; //We'd like UTF-8 doc.Save(Response.Output); //Save to the text-writer //using the encoding of the text-writer //(which comes from response.contentEncoding) Response.End(); //Optional: will end processing 

Полный пример

У Роба Кеннеди была хорошая мысль, что я не смог включить пример от начала до конца.

GetPatronInformation.ashx :

 <%@ WebHandler Language="C#" Class="Handler" %> using System; using System.Web; using System.Xml; using System.IO; using System.Data.Common; //Why a "Handler" and not a full ASP.NET form? //Because many people online critisized my original solution //that involved the aspx (and cutting out all the HTML in the front file), //noting the overhead of a full viewstate build-up/tear-down and processing, //when it's not a web-form at all. (It's a pure processing.) public class Handler : IHttpHandler { public void ProcessRequest(HttpContext context) { //GetXmlToShow will look for parameters from the context XmlDocument doc = GetXmlToShow(context); //Don't forget to set a valid xml type. //If you leave the default "text/html", the browser will refuse to display it correctly context.Response.ContentType = "text/xml"; //We'd like UTF-8. context.Response.ContentEncoding = System.Text.Encoding.UTF8; //context.Response.ContentEncoding = System.Text.Encoding.UnicodeEncoding; //But no reason you couldn't use UTF-16: //context.Response.ContentEncoding = System.Text.Encoding.UTF32; //Or UTF-32 //context.Response.ContentEncoding = new System.Text.Encoding(500); //Or EBCDIC (500 is the code page for IBM EBCDIC International) //context.Response.ContentEncoding = System.Text.Encoding.ASCII; //Or ASCII //context.Response.ContentEncoding = new System.Text.Encoding(28591); //Or ISO8859-1 //context.Response.ContentEncoding = new System.Text.Encoding(1252); //Or Windows-1252 (a version of ISO8859-1, but with 18 useful characters where they were empty spaces) //Tell the client don't cache it (it's too volatile) //Commenting out NoCache allows the browser to cache the results (so they can view the XML source) //But leaves the possiblity that the browser might not request a fresh copy //context.Response.Cache.SetCacheability(HttpCacheability.NoCache); //And now we tell the browser that it expires immediately, and the cached copy you have should be refreshed context.Response.Expires = -1; context.Response.Cache.SetAllowResponseInBrowserHistory(true); //"works around an Internet Explorer bug" doc.Save(context.Response.Output); //doc saves itself to the textwriter, using the encoding of the text-writer (which comes from response.contentEncoding) #region Notes /* * 1. Use Response.Output, and NOT Response.OutputStream. * Both are streams, but Output is a TextWriter. * When an XmlDocument saves itself to a TextWriter, it will use the encoding * specified by the TextWriter. The XmlDocument will automatically change any * XML declaration node, ie: *  * to match the encoding used by the Response.Output's encoding setting * 2. The Response.Output TextWriter's encoding settings comes from the * Response.ContentEncoding value. * 3. Use doc.Save, not Response.Write(doc.ToString()) or Response.Write(doc.InnerXml) * 3. You DON'T want to save the XML to a string, or stuff the XML into a string * and response.Write that, because that * - doesn't follow the encoding specified * - wastes memory * * To sum up: by Saving to a TextWriter: the XML Declaration node, the XML contents, * and the HTML Response content-encoding will all match. */ #endregion Notes } private XmlDocument GetXmlToShow(HttpContext context) { //Use context.Request to get the account number they want to return //GET /GetPatronInformation.ashx?accountNumber=619 //Or since this is sample code, pull XML out of your rear: XmlDocument doc = new XmlDocument(); doc.LoadXml("Rob Kennedy"); return doc; } public bool IsReusable { get { return false; } } } 

В идеале вы должны использовать ashx для отправки XML, хотя я допускаю, чтобы код в ASPX перехватывал нормальное выполнение.

 Response.Clear() 

Я не использую это, если вы не уверены, что вы сбросили что-либо в ответ, уже нашли его и избавитесь от него.

 Response.ContentType = "text/xml" 

Определенно, обычный клиент не будет принимать контент как XML без этого типа контента.

  Response.Charset = "UTF-8"; 

Пусть class ответа обрабатывает заголовок заголовка содержимого правильно. Используйте UTF-8, если у вас нет действительно хорошей причины.

 Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetAllowResponseInBrowserHistory(true); 

Если вы не отправляете кеш-заголовки, некоторые браузеры (а именно IE) будут кэшировать ответ, последующие запросы не обязательно будут поступать на сервер. Вам также необходимо AllowResponseInBrowser, если вы хотите, чтобы это работало через HTTPS (из-за еще одной ошибки в IE).

Для отправки содержимого XmlDocument просто используйте:

 dom.Save(Response.OutputStream); 

 dom.Save(Response.Output); 

Просто убедитесь, что кодировки совпадают (еще одна веская причина использовать UTF-8).

Объект XmlDocument автоматически скорректирует encoding="..." встроенного encoding="..." кодировку Response (например, UTF-8 )

 Response.End() 

Если вам действительно нужно в ASPX, но это немного радикально, в ASHX этого не делать.

Ниже приведен пример правильного пути, который я думаю. По крайней мере, это то, что я использую. Вам нужно выполнить Response.Clear, чтобы избавиться от каких-либо заголовков, которые уже заполнены. Вам нужно передать правильный ContentType text / xml. Так вы подаете xml. В общем, вы хотите использовать его в качестве кодировки UTF-8, поскольку это то, что ожидают большинство парсеров. Но я не думаю, что это должно быть так. Но если вы измените его, обязательно измените декларацию документа xml и укажите там кодировку. Вам нужно использовать XmlWriter, чтобы вы могли писать в UTF-8, а не по умолчанию. И чтобы он правильно кодировал ваши XML-данные в UTF-8.

  ' ----------------------------------------------------------------------------- ' OutputDataSetAsXML ' ' Description: outputs the given dataset as xml to the response object ' ' Arguments: ' dsSource - source data set ' ' Dependencies: ' ' History ' 2006-05-02 - WSR : created ' Private Sub OutputDataSetAsXML(ByRef dsSource As System.Data.DataSet) Dim xmlDoc As System.Xml.XmlDataDocument Dim xmlDec As System.Xml.XmlDeclaration Dim xmlWriter As System.Xml.XmlWriter ' setup response Me.Response.Clear() Me.Response.ContentType = "text/xml" Me.Response.Charset = "utf-8" xmlWriter = New System.Xml.XmlTextWriter(Me.Response.OutputStream, System.Text.Encoding.UTF8) ' create xml data document with xml declaration xmlDoc = New System.Xml.XmlDataDocument(dsSource) xmlDoc.DataSet.EnforceConstraints = False xmlDec = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", Nothing) xmlDoc.PrependChild(xmlDec) ' write xml document to response xmlDoc.WriteTo(xmlWriter) xmlWriter.Flush() xmlWriter.Close() Response.End() End Sub ' ----------------------------------------------------------------------------- 

Похоже, по крайней мере, 10 вопросов, включенных в один здесь, пару очков.

Response.Clear – это действительно зависит от того, что еще происходит в приложении – если у вас есть httpmodules в начале конвейера, который может писать ненужные материалы, а затем очистите его. Протестируйте его и узнайте. Для этого полезно использовать Fiddler или Wireshark.

Content Type to text / xml – yup – хорошая идея – прочитайте в спецификации HTTP о том, почему это важно. IMO, кто занимается веб-работой, должен хотя бы раз читать спецификации 1.0 и 1.1.

Кодирование – как ваш XML-код закодирован – если это utf-8, тогда скажите так, если нет, скажите что-то еще подходящее, просто убедитесь, что все они совпадают.

Страница – лично, будет использовать ashx или httpmodule, если вы используете страницу и хотите ее немного быстрее, избавитесь от autoeventwireup и привяжите обработчики событий вручную.

Вероятно, это будет пустой тратой памяти, чтобы сначала выгрузить xml в строку, но это зависит от размера xml, насколько вы заметили бы.

Как предложили другие, сохранение xml в выходной stream, вероятно, самый быстрый, я бы это сделал нормально, но если вы не уверены, протестируйте его, не полагайтесь на то, что вы читаете на interweb. Не просто верить всему, что я говорю.

Для другого подхода, если xml не так сильно изменится, вы можете просто записать его на диск и напрямую передать файл, что, скорее всего, будет довольно показательным, но, как и все в программировании, это зависит …

Я удивлен, что никто, кажется, никогда не упоминал, что вы можете использовать XDocument / XElement, которые доступны в .NET 4.0 и значительно упростить вывод XML.

Ниже приведен код на стороне сервера, который вызывается обработчиком и получает данные streamа и загружается в документ xml

  Stream stream = null; **Create a web request with the specified URL** WebRequest myWebRequest = WebRequest.Create(@"http://localhost/XMLProvider/XMLProcessorHandler.ashx"); **Senda a web request and wait for response.** WebResponse webResponse = myWebRequest.GetResponse(); **Get the stream object from response object** stream = webResponse.GetResponseStream(); XmlDocument xmlDoc = new XmlDocument(); **Load stream data into xml** xmlDoc.Load(stream); 

Ниже приведен способ, с помощью которого обработчик будет возвращать данные streamа, которые будут содержать XML-данные на стороне сервера.

Вот код обработчика, который возвращает данные.

  public void ProcessRequest(HttpContext context) { StringBuilder xmlBuilder = new StringBuilder(); xmlBuilder.Append(""); xmlBuilder.Append(""); xmlBuilder.Append("Sheo"); xmlBuilder.Append(""); xmlBuilder.Append(""); context.Response.ContentType = "application/octet-stream"; context.Response.BinaryWrite(Encoding.UTF8.GetBytes(xmlBuilder.ToString())); context.Response.End(); } 

Вы в основном ответили на все, и все уже, так что я не уверен, в чем дело?

FWIW Я бы использовал httphandler – кажется, нет смысла ссылаться на жизненный цикл страницы и иметь дело с отсечением бит viewstate и session и что у вас нет смысла для XML-документа. Это похоже на покупку автомобиля и снятие его на части, чтобы сделать ваш мотоцикл.

И контент-тип важен, так как запросчик знает, что делать с ответом.

  • Создание XML-файла с использованием java
  • NoClassDefFoundError в Eclipse
  • Запрос XPath для получения n-го экземпляра элемента
  • Как разбирать XML в Bash?
  • XSL xsl: template match = "/"
  • Как установить язык по умолчанию в Notepad ++
  • Android: добавление текстового представления в линейный макет программно
  • извлекать данные из raw html в R
  • Невозможно создать следующие classы: - android.support.v7.widget.Toolbar
  • Итерирование атрибутов элементов с помощью jQuery
  • Ошибка: «Узел должен быть вставлен из другого контекста документа»
  • Interesting Posts

    Как отформатировать диск, зашифрованный с помощью Bitlocker?

    Максимальное количество параметров в объявлении функции

    JPA OneToMany, не удаляющий ребенка

    Как заставить кнопки Google минимизировать, восстанавливать и закрывать кнопки Google, аналогичные другим программам?

    Как я могу получить или сделать USB-кабель питания SATA?

    Участок в штабеля в R

    Восстановление образа Windows 7 на другой жесткий диск

    Используйте LINQ для получения элементов в одном списке , которые не находятся в другом списке

    Angular2: проверка для не будет срабатывать при изменении файла для загрузки

    Использование дженериков в репозиториях Spring Data JPA

    Использование Cookie в Asp.Net Mvc 4

    Активность, AppCompatActivity, FragmentActivity и ActionBarActivity: когда использовать что?

    Утечка памяти WPF CreateBitmapSourceFromHBitmap ()

    Как я могу запустить проект с несколькими файлами в основном пакете?

    css3 переход анимации при загрузке?

    Давайте будем гением компьютера.