Question

I have some other posts where I've been working with posting data to a UPnP printer. Basically creating a control point from scratch (this is still POC and I'll be implementing across multiple device types so I'm trying to get basic understanding first). So far I'm able to discover the printer, request a print job and get back a data sink url to post the content to be printed. At this point I attempt a POST with simple xhtml data, but the request seems to time out every time with the following exception:

The remote server returned an error: NotFound.
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.WebClient.GetWebResponse(WebRequest request, IAsyncResult result)
at System.Net.WebClient.DownloadBitsResponseCallback(IAsyncResult result)

If I hit the url in the browser, I get back HTTP 405 Method Not Allowed

I'm wondering if the server is ignoring the post due to bad data, or I'm missing headers or something along these lines.

I've already gone through the docs on upnp.org for the Printer Basic service, along with SOAP 1.1 UPnP Profile, both of which greatly helped get as far as I have.

does anybody have any thoughts?

Here's a copy of my xhtml:

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML-Print 1.0//EN\" \"http://www.w3.org/MarkUp/DTD/xhtml-print10.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\">
  <head>
    <title>test</title>
  </head>
  <body>
    <div>hello world</div>
  </body>
</html>

I'm using C# to create and send a HttpWebRequest. Here is the code that does that (I have a couple variations, another using WebClient)

    private void SendToPrinter(string printUri, string content)
    {
        var request = WebRequest.Create(new Uri(printUri)) as HttpWebRequest;
        request.Method = "POST";
        request.ContentType = "text/xml; charset=\"utf-8\"";
        request.ContentLength = content.Length;
        request.Headers[SoapHeaderName] = CreateJobHeader; // this probably isn't necessary

        request.BeginGetRequestStream(ar => 
        {
            var requestStream = request.EndGetRequestStream(ar);
            using (var sw = new StreamWriter(requestStream))
            {
                sw.Write(content);
                sw.Close();
            }

            request.BeginGetResponse(a =>
            {
                var response = request.EndGetResponse(a);
                var responseStream = response.GetResponseStream();
                using (var sr = new StreamReader(responseStream))
                {
                    var results = sr.ReadToEnd();
                }

            }, null);

        }, null);
    }

raw post data from fiddler

POST http://10.20.201.90/upnp/print/1d153438-1e90-1f0b-8b54-984be15df0fe HTTP/1.1
Content-Type: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:device:Printer:1#SendDocument"
Host: 10.20.201.90
Content-Length: 482
Expect: 100-continue

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;s:Envelope xmlns:s=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&gt;&lt;s:Body&gt;&lt;u:SendDocument xmlns:u=&quot;urn:schemas-upnp-org:device:Printer:1&quot;&gt;&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;head&gt;&lt;title&gt;test&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;div&gt;hello world&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;&lt;/u:SendDocument&gt;&lt;/s:Body&gt;&lt;/s:Envelope&gt;
Was it helpful?

Solution

One issue that kept me from printing was that the printer was set to ask which tray to print from. This blocked the message from being printed. Here's the final SOAP message. I did not escape it.

<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">
  <s:Body>
    <html xmlns=\"http://www.w3.org/1999/xhtml\">
      <head><title>test</title></head>
      <body><div>hello world</div></body>
    </html>
  </s:Body>
</s:Envelope>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top