我正在尝试实现类似于this或this的东西。
我创建了一个用户控件,一个Web服务和一个Web方法来返回控件的呈现的html,并通过jQuery执行ajax调用。
一切正常,但是如果我在用户控件中放置了使用相对路径的内容(在我的情况下为带有NavigateUrl =“〜/ mypage.aspx”的HyperLink),则相对路径的解析在我的开发服务器中将失败。
我期望: http:// localhost:999 / MyApp / mypage.aspx
但是我得到了: http:// localhost:999 / mypage.aspx
缺少“ MyApp” …
我认为问题在于用于加载控件的Page的创建:
Page page = new Page(); Control control = page.LoadControl(userControlVirtualPath); page.Controls.Add(control); ...
但我不知道为什么…
编辑 只是为了清楚
我的用户控件位于,~/ascx/mycontrol.ascx 并包含一个非常简单的结构:到目前为止,仅带有NavigateUrl之类的超链接"~/mypage.aspx"。而“ mypage.aspx”实际上位于根目录上。
~/ascx/mycontrol.ascx
"~/mypage.aspx"
然后,我组成了一个Web服务,以将部分呈现的控件返回给ajax:
[ScriptService] [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class wsAsynch : System.Web.Services.WebService { [WebMethod(EnableSession = true)] public string GetControl(int parma1, int param2) { /* ...do some stuff with params... */ Page pageHolder = new Page(); UserControl viewControl = (UserControl)pageHolder.LoadControl("~/ascx/mycontrol.ascx"); Type viewControlType = viewControl.GetType(); /* ...set control properties with reflection... */ pageHolder.Controls.Add(viewControl); StringWriter output = new StringWriter(); HttpContext.Current.Server.Execute(pageHolder, output, false); return output.ToString(); } }
正确渲染了html,但是超链接的NavigateUrl中的相对路径被错误地解析,因为当我从VS2008的开发服务器执行项目时,我的应用程序的根目录是
http:// localhost:999 / MyApp /
很好,但是NavigateUrl解析为
http:// localhost:999 / mypage.aspx
丢失/ MyApp /。当然,如果我将我的ascx放在真实的页面中,而不是用在ws中的pageHolder实例,则一切正常。
另一个奇怪的事情是,如果我设置,hl.NavigateUrl = Page.ResolveUrl("~/mypage.aspx")我将获得页面的正确URL: http:// localhost:999 / MyApp / mypage.aspx
hl.NavigateUrl = Page.ResolveUrl("~/mypage.aspx")
到现在为止,我会这样做,但是我会明白为什么它无法正常运行。任何想法?
问题在于,Page类并非旨在像这样进行实例化。如果启动Reflector,我们将很快看到在实例化Page类并将其作为IHttpHandler返回之后,Asp.Net内部设置了一个重要的属性。您将必须设置AppRelativeTemplateSourceDirectory。这是Control类上存在的一个属性,并且在内部设置了TemplateControlVirtualDirectory属性,HyperLink例如使用该属性来解析链接中“〜”的正确URL。
请务必在调用LoadControl方法之前设置此值,因为AppRelativeTemplateSourceDirectory的值会传递到“主”控件创建的控件上。
如何获得正确的值来设置您的财产?在HttpRuntime类上使用静态AppDomainAppVirtualPath。总结一下,这应该起作用。
[WebMethod(EnableSession = true)] public string GetControl(int parma1, int param2) { /* ...do some stuff with params... */ var pageHolder = new Page() { AppRelativeTemplateSourceDirectory = HttpRuntime.AppDomainAppVirtualPath }; var viewControl = (UserControl)pageHolder.LoadControl("~/ascx/mycontrol.ascx"); var viewControlType = viewControl.GetType(); /* ...set control properties with reflection... */ pageHolder.Controls.Add(viewControl); var output = new StringWriter(); HttpContext.Current.Server.Execute(pageHolder, output, false); return output.ToString(); }