[如果我的问题标题没有准确描述我的问题,请道歉 - 如果你能想到一个更好的标题并且有权更改它,那么请随时改变它!]。
我认为我偶然发现了ASP.Net 3.5和4.0之间的细微变化。
[编辑:我已经确认twix 3.5和4.0的行为发生了变化 - 请参阅我的回答]
以下是该方案: -
我有一个ASP.Net 3.5 Web应用程序。 我有一个简单的用户控件{appRoot} /Controls/Widgets/MyPictureAndTextWidget.ascx,它基本上包含一些文本和另一个用户控件({appRoot} /Controls/Widgets/MyPicture.ascx)。
在大多数情况下,此控件以正常方式使用 - 即将其包含在其他页面的标记中,但我有一个实例,我需要使用Ajax获取要在客户端上呈现的HTML。
我实现这一目标的方法是编写一个asmx Web服务,以编程方式创建一个新的页面并动态地“LoadControl”用户控制,然后从字符串构建器中的页面呈现中捕获输出 - 特别是不优雅但是它有效!请参见底部的来源。
但是,在将项目升级到Asp.Net 4.0之后,上面的代码不再像过去那样工作了;渲染时的图像有src="../images/xxx.png
(注意不需要的'../')。
如果你想为自己运行它,我已经创建了一个小的演示应用程序http://cid-916198839f3e806c.office.live.com/self.aspx/Public/TestingImageWTF.zip。当您使用3.5编译应用程序时,它可以工作(即您在测试页面上看到2张蜘蛛图片)但是当您在4.0下编译并运行时,您只能看到1个蜘蛛(另一个图像的URL错误)。
我能想到的唯一解释是ResolveClientUrl
方法(Image控件将使用该方法来计算当前正在执行的页面中图像的相对路径)的行为方式不同。图像URL显示为“../ images/xxx.png”这一事实意味着图像控件“认为”它正在一个页面中执行,该页面在运行时具有类似“{appRoot} / folder / handler”的路径4.0以下,但它认为它是在3.5下的上下文“{appRoot} / handler”中运行。
我希望这对你有意义 - 如果我没有非常清楚或简明地描述问题,那就很抱歉。
任何人都可以告诉我们如何: -
恢复3.5行为(显然没有恢复到3.5框架!)
或者首先在Web服务中生成HTML的更好方法是什么?
可以从此处http://cid-916198839f3e806c.office.live.com/self.aspx/Public/TestingImageWTF.zip
下载完整的测试应用程序 [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;
}
以下是我的用户控件的内容
<%@ 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>
<%@ 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" />
答案 0 :(得分:5)
o如果答案是至少部分的话。
问题:ResolveClientUrl在ASP.Net 4和3.5中的工作方式是否有所不同?
答案:是。
行为的变化(我所知道的)是它以不同的方式对待PathInfo。
要进行演示,请进行以下页面。
<%@ 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>
在.Net4和.Net 3.5下运行。
你会看到3.5以下:
ResolveClientUrl(“〜/ PathInfoLinkTest.aspx / foo / bar”)=' PathInfoLinkTest.aspx / foo / bar '
而在4.0以下,你得到了 ResolveClientUrl(“〜/ PathInfoLinkTest.aspx / foo / bar”)=' bar '
这些变化似乎是针对这些人所遇到的问题的错误修复。
从本质上讲,3.5中的错误是如果您当前正在浏览网址http://host/app/page.aspx/foo/bar
并且想要链接到http://host/app/page2.aspx
,那么客户端上呈现的网址应为{{1} }。
Asp.Net 4是正确的!
Asp.Net 3.5没有 - 它将链接的URL输出为“../../page2.aspx
”(因此,点击后,浏览器将请求页面'{{ 1}}'。如果您在.Net 3.5中运行上述页面并多次点击第二个超链接,您可以看到此错误的表现形式 - 然后查看浏览器的地址栏!
不幸的是,错误修复破坏了我的代码 - 因为我的代码依赖于.Net 3.5的(不正确的)行为:Web服务请求始终具有Pathinfo(Web服务方法名称),因此当控件呈现自己时,调用到ResolveClientUrl(“〜/ xxx”)(正确)put返回“../ xxx”。
答案 1 :(得分:2)
我不确定ResolveClientUrl方法的更新,但我知道他们更新了.NET 4.0和3.5之间的控件呈现方式。您可能想尝试更新web.config以包含:
<pages controlRenderingCompatibilityVersion="3.5" />
退房:http://www.asp.net/learn/whitepapers/aspnet4/breaking-changes#0.1__Toc256770141
此外,您可以尝试在Web服务中使用RenderControl,如下所示:
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(tw);
control.RenderControl(hw);
return sb.ToString();
Rick Strahl有一篇文章可能有用:http://www.west-wind.com/weblog/posts/2004/Jun/08/Capturing-Output-from-ASPNet-Pages(可能有点过时了......)
希望这有帮助!
答案 2 :(得分:0)
尝试从ImageUrl值中删除前导波形符号。