ResolveClientUrl works differently in ASP.Net 4 and 3.5

[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" /> 
+4
source share
3 answers

oSo here, at least part if the answer.

Question: Does ResolveClientUrl work differently in ASP.Net 4 and 3.5?

Answer: Yes .

And the change in behavior (which I know) is that it treats PathInfo differently.

To demonstrate, do the following page.

 <%@ Page Language="C#" AutoEventWireup="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <body> <form id="form1" runat="server"> DateTime.Now.Ticks: <%= DateTime.Now.Ticks %> <br /> <asp:HyperLink runat="server" NavigateUrl="~/PathInfoLinkTest.aspx">This links to ~/PathInfoLinkTest.aspx</asp:HyperLink> <br /> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/PathInfoLinkTest.aspx/foo/bar">This links to ~/PathInfoLinkTest.aspx/foo/bar</asp:HyperLink> <br /> ResolveClientUrl("~/PathInfoLinkTest.aspx/foo/bar") = <%= ResolveClientUrl("~/PathInfoLinkTest.aspx/foo/bar") %> </form> </body> </html> 

And run under .Net4 and .Net 3.5.

You will see that in section 3.5:
ResolveClientUrl ("~ / PathInfoLinkTest.aspx / foo / bar") = ' PathInfoLinkTest.aspx / foo / bar '

whereas under 4.0 you get
ResolveClientUrl ("~ / PathInfoLinkTest.aspx / foo / bar") = ' bar '

The change seems to be a bug fix in response to the problems these people have encountered.

Essentially, error 3.5 is that if you look at the URL http://host/app/page.aspx/foo/bar and want to go to http://host/app/page2.aspx , then the URL the address displayed on the client should be ../../page2.aspx .

Asp.Net 4 does it right!
Asp.Net 3.5 does not show - it displays the link URL as ' page2.aspx ' (therefore, when you click on the browser, the page ' http://host/app/page.aspx/foo/bar/page2.aspx ' is http://host/app/page.aspx/foo/bar/page2.aspx . You can see manifestation of this error, if you run the above page in .Net 3.5 and several times click on the second hyperlink - then look in the address bar of the browser!

Unfortunately, the bug fix broke my code - because my code relied on (incorrect) .Net 3.5 behavior: The web service request always has Pathinfo (the name of the web service method), and therefore, when the controls display themselves, calls to ResolveClientUrl ("~ / xxx") (correctly) returns "../xxx".

+5
source

I'm not sure about the updates to the ResolveClientUrl method, but I know that they made updates on how the controls display between .NET 4.0 and 3.5. You can try updating your web.config to include:

 <pages controlRenderingCompatibilityVersion="3.5" /> 

Check out: http://www.asp.net/learn/whitepapers/aspnet4/breaking-changes#0.1__Toc256770141

Alternatively, you can try using RenderControl as follows in your web service:

 StringBuilder sb = new StringBuilder(); StringWriter tw = new StringWriter(sb); HtmlTextWriter hw = new HtmlTextWriter(tw); control.RenderControl(hw); return sb.ToString(); 

Rick Strahl has an article that may be useful: http://www.west-wind.com/weblog/posts/2004/Jun/08/Capturing-Output-from-ASPNet-Pages (may be somewhat given, however .. .)

Hope this helps!

+2
source

Try removing the main tilde character from the ImageUrl value.

0
source

All Articles