[Sorry if my question does not accurately describe my problem - if you can think of a better name and have permission to change it, please feel free to change it!].
I think I came across a minor violation between ASP.Net 3.5 and 4.0.
[Edit: I confirmed that there are changes in the behavior of twix 3.5 and 4.0 - see my answer]
Here is the scenario: -
I have an ASP.Net 3.5 web application. I have a trivial user control {appRoot} /Controls/Widgets/MyPictureAndTextWidget.ascx, which essentially contains some text and another user control ({appRoot} /Controls/Widgets/MyPicture.ascx).
For the most part, this control is used in the usual way - that is, including it in the layout of other pages, but I have one instance where I need to get HTML to render on the client using Ajax.
The way I accomplished this was to write an asmx web service that programmatically created a new page and dynamically "LoadControl", which the user controls and then grabbed the output from the page rendering in the line builder - especially not elegant, but it works ! See bottom of source.
However, after upgrading the project to Asp.Net 4.0, the above code no longer works the way it was used; image when rendering has src="../images/xxx.png (pay attention to" ../ ", which is not needed).
I created a small demo application http://cid-916198839f3e806c.office.live.com/self.aspx/Public/TestingImageWTF.zip if you want to run it for yourself. When you compile the application using 3.5, it works (i.e. you see 2 spider images 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).
The only explanation I can come up with is that the ResolveClientUrl method (which the Image control will use to determine what is the relative path to the image from the current executable page) behaves differently. The fact that the image URL is displayed as "../images/xxx.png" means that the image control "thinks" that it is running on a page that has a path like "{appRoot] / folder / handler "when running below 4.0, but he believes that it is running in the context of the {appRoot} / handler under 3.5.
I hope this makes sense to you - sorry if I don't describe the problem very clearly or succinctly.
Can someone tell us how: -
to restore 3.5 behavior (without resorting to 3.5 structure, obviously!)
or is the best way to generate HTML in a web service in the first place?
A source
The full test application can be downloaded here http://cid-916198839f3e806c.office.live.com/self.aspx/Public/TestingImageWTF.zip
Web service
[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 < 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; }
Here are the contents of my user controls
Controls / Widgets / MyPictureAndTextWidget.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyPictureAndTextWidget.ascx.cs" Inherits="TestingImageWTF.Controls.Widgets.MyPictureAndTextWidget" %> <%@ Register TagName="Picture" TagPrefix="widget" Src="~/Controls/Widgets/MyPictureWidget.ascx" %> <div style="background:#EEEEEE; border:1px dashed;"> <h4>My control</h4> Some text from the widget ....: <br /><widget:Picture runat="server" /> </div>
Controls / Widgets / MyPictureWidget.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyPictureWidget.ascx.cs" Inherits="TestingImageWTF.Controls.Widgets.MyWidget" %> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { image.ImageUrl = "~/images/spider.png"; } </script> <asp:Image ID="image" runat="server" />