title: Rendering HTML+Javascript server-side
body: <p>I need to render an HTML page server-side and "extract" the raw bytes of a canvas element so I can save it to a PNG. Problem is, the canvas element is created from javascript (I'm using jquery's Flot to generate a chart, basically). So I guess I need a way to "host" the DOM+Javascript functionality from a browser without actually using the browser. I settled on mshtml (but open to any and all suggestions) as it seems that it should be able to to exactly that. This is an ASP.NET MVC project. </p>
  
  <p>I've searched far and wide and haven't seen anything conclusive. </p>
  
  <p>So I have this simple HTML - example kept as simple as possible to demonstrate the problem - </p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
      &lt;title&gt;Wow&lt;/title&gt;
      &lt;script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js" type="text/javascript"&gt;&lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
      &lt;div id="hello"&gt;
      &lt;/div&gt;
      &lt;script type="text/javascript"&gt;
          function simple() 
          {
              $("#hello").append("&lt;p&gt;Hello&lt;/p&gt;");
          }                    
      &lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>which produces the expected output when run from a browser. </p>
  
  <p>I want to be able to load the original HTML into memory, execute the javascript function, then manipulate the final DOM tree. I cannot use any System.Windows.WebBrowser-like class, as my code needs to run in a service environment. </p>
  
  <p>So here's my code:</p>
  
  <pre><code>IHTMLDocument2 domRoot = (IHTMLDocument2)new HTMLDocument();
  
          using (WebClient wc = new WebClient())
          {
              using (var stream = new StreamReader(wc.OpenRead((string)url)))
              {
                  string html = stream.ReadToEnd();
                  domRoot.write(html);
                  domRoot.close();
              }
          }
  
          while (domRoot.readyState != "complete")
              Thread.Sleep(SleepTime);
  
          string beforeScript = domRoot.body.outerHTML;
  
          IHTMLWindow2 parentWin = domRoot.parentWindow;            
          parentWin.execScript("simple");
  
          while (domRoot.readyState != "complete")
              Thread.Sleep(SleepTime);
  
  
          string afterScript = domRoot.body.outerHTML;
  
          System.Runtime.InteropServices.Marshal.FinalReleaseComObject(domRoot);
          domRoot = null;
  </code></pre>
  
  <p>The problem is, "beforeScript" and "afterScript" are exactly the same. The IHTMLDocument2 instance goes through the normal "uninitialized", "loading", "complete" cycle, no errors are thrown, nothing.</p>
  
  <p>Anybody have any ideas on what I'm doing wrong? Completely lost here.  </p>