1

I am attempting to trigger a download of an XML file stream from a PageMethod. I followed the documentation here

[WebMethod]
public static bool Export()
{
    bool successful = false;

    try
    {
        HttpContext.Current.Response.ContentType = "text/xml";
        HttpContext.Current.Response.ClearHeaders();
        HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=Dashboard.xml");

        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.BufferOutput = true;

        SerializableDictionary<string, string> dataToSave = new SerializableDictionary<string, string>();

        foreach( var state in StateManager.StateDictionary)
        {
            var sessionItem = SessionRepository.Instance.GetSession(state.Value);
            if (Equals(sessionItem, null)) continue;

            using( MemoryStream memoryStream = new MemoryStream())
            {
                XmlSerializer serializer = new XmlSerializer(sessionItem.GetType());
                serializer.Serialize(memoryStream, sessionItem);
                dataToSave.Add(state.Value, Convert.ToBase64String(memoryStream.ToArray()));
            }
        }

        XmlSerializer xmlSerializer = new XmlSerializer(dataToSave.GetType());

        using( MemoryStream memoryStream = new MemoryStream())
        {
            xmlSerializer.Serialize(memoryStream, dataToSave);
            HttpContext.Current.Response.AppendHeader("Content-Length", memoryStream.Length.ToString());

            memoryStream.Position = 0;

            using( StreamReader streamReader = new StreamReader(memoryStream))
            {
                HttpContext.Current.Response.Write(streamReader.ReadToEnd());
            }
        }

        HttpContext.Current.Response.Flush();

        successful = true;
    }
    catch (Exception exception)
    {
        _logger.ErrorFormat("Unable to serialize session. Reason: {0}", exception.Message);
    }

    return successful;
}

I receive no warnings or errors. Just finishes successfully with no download.

EDIT: I've tried application/xml and text/plain as ContentTypes, as well.

Sean Anderson
  • 27,963
  • 30
  • 126
  • 237

1 Answers1

1

You need to set the response headers:

Response.AddHeader("content-disposition","attachment; filename=fname.ext")
Response.AddHeader("Content-Length", data.Length.ToString())
gislikonrad
  • 3,401
  • 2
  • 22
  • 24
  • Ahh.. that would explain how I could name the file, too. Lemme try it out! – Sean Anderson Aug 19 '11 at 22:08
  • Is there a way to get the length of the stream? Look at the line where I serialize dataToSave to a stream. OutputStream.Length isn't accessible, I beleive. – Sean Anderson Aug 19 '11 at 22:23
  • IIRC, you can serialize the data to a string, get the length of the string and then write the string to the response using Response.Write. Flushing should then complete the response. – gislikonrad Aug 19 '11 at 22:25
  • Do you know if reading the MemoryStream's length property would be acceptable? I've implemented the other way and am checking it now, was just curious if there was any difference between MemoryStream length and the string length derived from the MemoryStream. – Sean Anderson Aug 19 '11 at 22:38
  • Not sure.. Couldn't hurt to try... I would try it out myself, but I'm using my home mac atm... :P – gislikonrad Aug 19 '11 at 22:41
  • Haha it's all good. I did try it out. Still no download, though! Going to post my updated code, 1 second. – Sean Anderson Aug 19 '11 at 22:43
  • Another approach would be to serialize it to string, convert to bytes and the do Response.BinaryWrite(byte[]) – gislikonrad Aug 19 '11 at 22:44
  • The method of serialization shouldn't have any affect on how the browser processes it, yeah? Seems like the issue is somewhere else. I'm wondering if I can do this inside of a page method? – Sean Anderson Aug 19 '11 at 22:57
  • WOW! I'm such a dunce... You're right... WebMethod is not the right way to do this. I didn't even notice the attribute... Using a handler (ashx) would be the correct type to use. – gislikonrad Aug 19 '11 at 23:00
  • Let me check that out. Thanks! – Sean Anderson Aug 19 '11 at 23:04
  • Do you know if it will be possible to target/call/whatever this ASHX file from client-side? That's why I was using a PageMethod in the first place. – Sean Anderson Aug 19 '11 at 23:07
  • Session is null inside of the ASHX? :( Got it :) – Sean Anderson Aug 19 '11 at 23:53
  • http://stackoverflow.com/questions/1058568/asp-net-how-to-access-session-from-handler I AM on top if things... :) – gislikonrad Aug 20 '11 at 00:08