So I got requested to have the option to download/create an XML file from a Database. The table contains a column with the raw XML message in it. User needs to be able to save the XML Doc for viewing.
So I tested my download in a separate program, it works, downloads and creates XML Doc perfectly, but for some reason it WONT download/create in the actual program.
So I created a stored Proc to call the XML Message = to the QueueId.
The Button is located in a datagrid(We're using Telerik)
So I'm using MemoryStream and a streamwriter to write the XML to a document. Here's my code:
private void DownloadXml()
{
try
{
MemoryStream stream = null;
if (grdMessages.SelectedItems.Count > 0)
{
foreach (GridDataItem item in grdMessages.SelectedItems)
{
int queueId = int.Parse(item["QueueId"].Text);
ibis_GetXmlTextResult result = Client.IbisGetClient(Endpoint).ibis_GetXmlText(queueId);
stream = new MemoryStream();
var r = result.XmlMessage.ToString();
//r = "Hello this is my file:)"; //This was only to test it if worked
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(r);
writer.Flush();
}
WriteToPage(stream.ToArray(), "text/plain; charset=UTF-8", string.Format("{0}_ClientXml.xml", queueId));
//WriteToPage(stream.ToArray(), "text/xml; charset=UTF-8", "ClientXml.xml");
}
}
}
catch (Exception ex)
{
LogException(ex, "Demand Filter", "Well that didn't work. Check for error " + ex.StackTrace);
}
}
private void WriteToPage(byte[] data, string contentType, string fileName)
{
HttpResponse response = Page.Response;
response.Clear();
response.ClearContent();
response.ClearHeaders();
response.Buffer = true;
response.AddHeader("Content-Disposition", string.Format("Attachment; filename=\"{0}\"", fileName));
response.ContentType = contentType;
response.BinaryWrite(data);
response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
//response.End();
}
So I can see it gets the XML Message, but I get this error when I check the console, I get this error: https://i.sstatic.net/UyADZ.png
EDIT The Error Given:
Error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Details: Error parsing near ' < Test xmlns = " " / > < !D'.
In Fiddler I can see the raw XML Message, but 1.) It's not downloading, 2.) it's Adding a whole bunch of crap at the end of the XML Message which my separate program does not do.
So here's what I did to fix it
The problem was with my GridButtonColumn
private void DownloadXml()
{
try
{
MemoryStream stream = null;
if (grdMessages.SelectedItems.Count > 0)
{
foreach (GridDataItem item in grdMessages.SelectedItems)
{
int queueId = int.Parse(item["QueueId"].Text);
ibis_GetXmlTextResult result = Client.IbisGetClient(Endpoint).ibis_GetXmlText(queueId);
stream = new MemoryStream();
var r = result.XmlMessage.ToString();
//r = "Hello this is my file:)";
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(r);
writer.Flush();
}
WriteToPage(stream.ToArray(), "text/xml; charset=UTF-8", string.Format("{0}_ClientXml.xml", queueId));
}
}
catch (Exception ex)
{
LogException(ex, "Demand Filter", "Well that didn't work. Check for error " + ex.StackTrace);
}
}
And here is the WriteToPage()
private void WriteToPage(byte[] data, string contentType, string fileName)
{
HttpResponse response = Page.Response;
response.Clear();
response.ClearContent();
response.ClearHeaders();
response.Buffer = true;
response.AddHeader("Content-Disposition", string.Format("Attachment; filename=\"{0}\"", fileName));
response.ContentType = contentType;
response.BinaryWrite(data);
response.Flush();
response.End();
}
On my view I had to add a few things. For my script to work, I had to add this to my RadAjaxManager(Note I'm working with Telerik)
`
<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server" UpdatePanelsRenderMode ="Inline" DefaultLoadingPanelID="AjaxLoadingPanel">
<AjaxSettings>
<telerik:AjaxSetting AjaxControlID="RadGrid1">
<UpdatedControls>
<telerik:AjaxUpdatedControl ControlID="RadGrid1" />
</UpdatedControls>
</telerik:AjaxSetting>
</AjaxSettings>
</telerik:RadAjaxManager>
`
And here is the script I used in my View
`
<telerik:radscriptblock id="RadScriptBlock1" runat="server">
<script type="text/javascript">
function onTabSelecting(sender, args)
{
if (args.get_tab().get_pageViewID())
{
args.get_tab().set_postBack(false);
}
}
function RadGrid1_Command(sender, args)
{
var commandName = args.get_commandName();
if (commandName == "DownloadXml") {
$find("<%= RadAjaxManager1.ClientID %>").set_enableAJAX(false);
}
}
</script>
</telerik:radscriptblock>
`
And then here's the damn potato that bit me in the butt.
`protected void grdMessages_ItemCreated(object sender, GridItemEventArgs e)
{
if (e.Item is GridDataItem)
{
GridDataItem item = (GridDataItem)e.Item;
LinkButton btnXML = (LinkButton)item["DownloadXml"].Controls[0];
btnXML.Click += new EventHandler(btnXML_Click);
btnXML.Attributes.Add("OnClick", "DownloadXML(); return false;");
}
}
`
So the only thing I needed was the "return false;" at the Attributes.
Hopes this helps someone somewhere in the line. I looked everywhere for the damn answer, had to combine a crap ton of stuff to make it work. And yeah, there's MULTIPLE ways of doing it.
Goodluck and Happy Coding Flip - OUT