title: ResolveClientUrl works differently in ASP.Net 4 and 3.5
body: <p>[Apologies if my question title does not accurately describe my problem- if you can think of a better title and have the permissions to change this then  please feel free to change it!].</p>
  
  <p>I think that I have stumbled upon a minor breaking change between ASP.Net 3.5 and 4.0.</p>
  
  <p>[Edit: I have confirmed that there is a change in behaviour twix 3.5 and 4.0 - see my answer]</p>
  
  <p>Here is the scenario: -</p>
  
  <p>I have a ASP.Net 3.5 web application.
  I have a trivial user control {appRoot}/Controls/Widgets/MyPictureAndTextWidget.ascx that essentially contains some text and another user control ({appRoot}/Controls/Widgets/MyPicture.ascx).</p>
  
  <p>For the most part, this control is used in the normal fashion - i.e. including it in the mark up of other pages but I have one instance where I need to obtain the HTML to render on the client using Ajax.  </p>
  
  <p>The way I achieved this was to write an asmx web service that programmatically created a new Page and dynamically `LoadControl' the user controls and then captured the output from the rendering of the page in a string builder - particulary inelegant but it worked!  See bottom for the source.  </p>
  
  <p>However, after upgrading the project to Asp.Net 4.0, the above code no longer works as it used to; the image, when rendered has <code>src="../images/xxx.png</code> (note the '../' which is not wanted).</p>
  
  <p>I have created a little demo app <a href="http://cid-916198839f3e806c.office.live.com/self.aspx/Public/TestingImageWTF.zip" rel="nofollow">http://cid-916198839f3e806c.office.live.com/self.aspx/Public/TestingImageWTF.zip</a>  if you want to run it for yourselves.  When you compile the app using 3.5, it works (i.e. you see 2 pictures of a spider on the test page) but when you compile and run under 4.0, you only see 1 spider (the other image has the wrong URL).</p>
  
  <p>The only explanation that I can come up with is that the <code>ResolveClientUrl</code> method (which the Image control will use in order to work out what is the relative path to the image from the currently executing page) is behaving differently.  The fact that the image url is coming out as "../images/xxx.png" means that the Image control 'thinks' it is executing in a page that has a path like '{appRoot}/folder/handler' when running under 4.0 but it thinks  it is running in a context '{appRoot}/handler' under 3.5.</p>
  
  <p>I hope this is making sense to you - sorry if I am not describing the problem very clearly or concisely.</p>
  
  <p>Can anyone either tell us how: -</p>
  
  <ul>
  <li><p>to restore the 3.5 behaviour (without reverting to the 3.5 framework obviously!)</p></li>
  <li><p>or a better way of generating the HTML in the web service in the first place?  </p></li>
  </ul>
  
  <h1>The source</h1>
  
  <p>A full test application can be downloaded from here <a href="http://cid-916198839f3e806c.office.live.com/self.aspx/Public/TestingImageWTF.zip" rel="nofollow">http://cid-916198839f3e806c.office.live.com/self.aspx/Public/TestingImageWTF.zip</a> </p>
  
  <h2>Web Service</h2>
  
  <pre><code>    [WebMethod]
      [ScriptMethod]
      public string GetWidgetHtml(int number)
      {
          var pageHolder = new Page
                               {
                                           //AppRelativeVirtualPath = "~/" // I tried playing with this but it made no difference!
                               };
          for (int i = 0; i &lt; number; i++)
          {
              var viewControl = (MyPictureAndTextWidget) pageHolder.LoadControl(@"~/Controls/Widgets/MyPictureAndTextWidget.ascx");
              pageHolder.Controls.Add(viewControl);
          }
  
          var output = new StringWriter();
  
          HttpContext.Current.Server.Execute(pageHolder, output, false);
  
          StringBuilder sb = output.GetStringBuilder();
          string fulloutput = sb.ToString();
          return fulloutput;
      }
  </code></pre>
  
  <p>Here are the contents of my user controls</p>
  
  <h2>Controls/Widgets/MyPictureAndTextWidget.ascx</h2>
  
  <pre><code>    &lt;%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyPictureAndTextWidget.ascx.cs" Inherits="TestingImageWTF.Controls.Widgets.MyPictureAndTextWidget" %&gt;
      &lt;%@ Register TagName="Picture" TagPrefix="widget" Src="~/Controls/Widgets/MyPictureWidget.ascx" %&gt;
  
      &lt;div style="background:#EEEEEE; border:1px dashed;"&gt;
          &lt;h4&gt;My control&lt;/h4&gt;
          Some text from the widget ....: 
          &lt;br /&gt;&lt;widget:Picture runat="server" /&gt;
      &lt;/div&gt;
  </code></pre>
  
  <h2>Controls/Widgets/MyPictureWidget.ascx</h2>
  
  <pre><code>    &lt;%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyPictureWidget.ascx.cs" Inherits="TestingImageWTF.Controls.Widgets.MyWidget" %&gt;
  
      &lt;script runat="server"&gt;
          protected void Page_Load(object sender, EventArgs e)
          {
              image.ImageUrl = "~/images/spider.png";
          }
      &lt;/script&gt;
      &lt;asp:Image ID="image" runat="server" /&gt;
  </code></pre>