views:

1873

answers:

3

I am working on an ASMX web service; trying to create a method that will download a document from a server and show the document in the browser (the calling .aspx web page). My service builds without error but I get the following error when I try to "Add Web Reference" in my Proxy class project:

System.Web.HttpResponse cannot be serialized because it does not have a parameterless constructor.

Here is a snippet of the code in .ASMX file:

public class FileService : System.Web.Services.WebService
{
    [WebMethod]
    public void DownloadDocument(string URI, HttpResponse httpResponse)
    {
        int DownloadChunkSize = (int)Properties.Settings.Default.DownloadChunkSize;
        // some more code here....
        using (httpResponse.OutputStream)
        {
            // more code here...
        }
    }
}

I see I am confused about how to send back an HttpResponse from a web service to a requesting web page. Could someone please give me a tip on how to do this? Thanks.

+1  A: 

That is not how standard ASMX web services work. If you want to make your own handler, or even use an ASPX page to deliver the doc, you are fine, but the standard ASMX web service method of doing this is to actually return the bits of the document as an encoded blob.

If you want to roll your own, consider this article: http://msdn.microsoft.com/en-us/magazine/cc163879.aspx

Gregory A Beamer
A: 

The web smethod (from asmx) returns an object, which can be serialized.

You need to create your method like:

[WbeMethod] public byte[] DownloadDocument(string URI)

Or if the content is some text - return string.

Sunny
+2  A: 

You should look into web handlers (.ashx). They are perfect for what you are trying to achieve.

For example:

public class Download : IHttpHandler, IRequiresSessionState {

    public void ProcessRequest(HttpContext context) {
     var pdfBytes = /* load the file here */
     context.Response.ContentType = @"Application/pdf";
     context.Response.BinaryWrite(pdfBytes);
     context.Response.End();
    }
}

UPDATE: An ashx handler is actually a replacement to aspx. Basically, it has no UI but still processes get / post requests just like an aspx page does. The point is to reduce the overhead generated by running a regular aspx page when all you need to do is return some simple content (like a file...) or perform a quick action.

The IRequiresSessionState interface allows you to use the SESSION object like any other page in your site can. If you don't need that, then leave it off.

This site has an interesting walk through on how to create one. Ignore Step 4 as you probably don't care about that.

Assuming that you have a regular page (aspx) that has a link to your document: The link in the aspx file would actually point directly to your ashx handler. for example:

<a href="/document.ashx?id=blah">Click Here</a>

Then the code in the ProcessRequest method of the ashx handler would do whatever calls it needed (like talk to your DLL) to locate the document then stream it back to the browser through the context.Response.BinaryWrite method call.

Chris Lively
Hey Chris, thank you. I am trying to get my head around this suggestion which sounds good (though I have a lot to study up on...). Where would this .ashx file go? At this point, I have an .aspx page referencing myProxyClass.DLL which calls my .asmx service. Is the .ashx an alternative to .asmx?
John Galt
Wow, between your clarifying UPDATE added yesterday and the link you provided, suddenly .ASHX suddenly became a lot more understandable. By the end of the day I had implemented my new .ASHX which calls my .ASMX just like my former attempt that failed the web service call from my .ASPX.
John Galt