Asp.Net AJAX调用的单控制呈现

Asp.Net AJAX调用的单控制呈现

问题描述:

我试图实现类似于thisthis的东西。Asp.Net AJAX调用的单控制呈现

我创建了一个用户控件,一个web服务和一个web方法来返回控件的呈现html,通过jQuery执行ajax调用。

所有的工作都很好,但是如果我在使用相对路径的用户控件(在我的情况下是一个带有NavigateUrl =“〜/ mypage.aspx”的HyperLink)的东西放在我的开发服务器的相对路径的解析失败。

我期待: http://localhost:999/MyApp/mypage.aspx

,但我得到: http://localhost:999/mypage.aspx

缺少 'MyApp的' ......

我认为这个问题是用来加载生成页的控制:

Page page = new Page(); 
Control control = page.LoadControl(userControlVirtualPath); 
page.Controls.Add(control); 
... 

但我不明白为什么....

编辑 只是为了清楚起见

我的用户控件位于~/ascx/mycontrol.ascx ,并包含一个非常简单的结构:由现在只是一个像"~/mypage.aspx"与NavigateUrl超链接。 而“mypage.aspx”确实位于根目录下。

然后我做了一个Web服务,返回阿贾克斯部分呈现的控制:

[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

lost/MyApp /。 当然,如果我把我的ascx放在一个真实的页面中,而不是ws中使用的pageHolder实例,所有工作都正常。

另一个奇怪的事情是,如果我设置hl.NavigateUrl = Page.ResolveUrl("~/mypage.aspx")我得到的页面的正确网址: http://localhost:999/MyApp/mypage.aspx

而现在我会做到这一点,但我想明白为什么它不工作正常的方式。 有什么想法?

+0

在页面/控件生命周期中,你会调用'hl.NavigateUrl = Page.ResolveUrl(“〜/ mypage.aspx”)'?在这之前,你是否在代码中的同一个地方运行'hl.NavigateUrl =“〜/ mypage.aspx”'? – awe 2010-09-15 07:10:08

问题是,页面类不是像这样实例化的。如果我们启动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(); 
} 
+0

太好了,我喜欢这种方式! – tanathos 2010-10-21 12:01:48

tildy pust是应用程序根目录中的路径,因此它会生成您所看到的结果。您将要使用:

NavigateUrl="./whatever.aspx" 

编辑:
这里是一个链接,也可能证明是有益的?http://msdn.microsoft.com/en-us/library/ms178116.aspx

+0

但我想要我的网址上的应用程序路径,我需要它为我的本地开发服务器。 url http:// localhost:999/mypage.aspx根本不存在。如果我把ascx放在页面上,所有的相对路径都被解析为http:// localhost:999/MyApp/something.something ...并且它是正确的。 – tanathos 2010-06-30 16:29:17

+0

你可以为ascx的页面注册显示标记,也可以简单地解释你的站点结构(页面驻留在哪里,控件位于何处)?我有一种感觉,这是因为控件/页面在不同的目录中。 – AGoodDisplayName 2010-06-30 16:38:12

我发现/ MyApp/root会导致各种问题。它并没有真正回答你'为什么不能正常工作'的问题,但是你是否意识到你可以摆脱/ MyApp /并将你的网站托管在http:/ localhost/...?

只需在网站属性中将“虚拟路径”设置为“/”即可。

这清除了所有的东西,除非你正试图在开发PC上同时托管多个应用程序。

+0

问题是我有很多应用程序配置为开发...现在我已经绕过这个问题使用Page.ResolveUrl(“〜/ mypage.aspx”),但我真的想明白为什么:) – tanathos 2010-07-09 16:25:03

可能是因为新的页面对象没有“MyApp”作为根目录,所以它被默认解析为服务器根目录。

我的问题是它为什么与Page.ResolveUrl(...)一起使用。
也许ResolveUrl做了一些关于用户控件的位置的调查,并基于此来解决。

奇怪,我重新创建了这个例子。该超链接对〜/ Default.aspx的给定导航网址呈现为<a id="ctl00_hlRawr" href="Default.aspx"></a>。我的猜测是它与RequestMethod有关。在常规页面上是“GET”,但在web服务调用中它是“POST”。

我无法通过hl.NavigateUrl = Page.ResolveUrl("~/mypage.aspx") 重新创建结果该控件总是呈现为给定虚拟路径的<a id="ctl00_hlRawr" href="Default.aspx"></a>。 (Page.ResolveUrl给我“〜/ Default.aspx”)

我会建议做这样的事情,以避免在未来的麻烦。

protected void Page_Load(object sender, EventArgs e) 
{ 
    hlRawr.NavigateUrl = FullyQualifiedApplicationPath + "/Default.aspx"; 
} 

public static string FullyQualifiedApplicationPath 
{ 
    get 
    { 
     //Return variable declaration 
     string appPath = null; 

     //Getting the current context of HTTP request 
     HttpContext context = HttpContext.Current; 

     //Checking the current context content 
     if (context != null) 
     { 
      //Formatting the fully qualified website url/name 
      appPath = string.Format("{0}://{1}{2}{3}", 
      context.Request.Url.Scheme, 
      context.Request.Url.Host, 
      (context.Request.Url.Port == 80 ? string.Empty : ":" + context.Request.Url.Port), 
      context.Request.ApplicationPath); 
     } 

     return appPath; 
    } 
} 

问候,

这是很难告诉你正在努力实现,而无需缴纳,实际上将URL超链接的线什么的,但我想我明白你的目录结构。

但是,我从来没有遇到过使用ResolveUrl()方法无法以某种方式解决的情况。建议不要在生产中使用的临时路径的字符串解析,因为它会增加项目的复杂性。

此代码将在从页面继承的任何对象解决(包括用户控件):

Page page = (Page)Context.Handler; 
string Url = page.ResolveUrl("~/Anything.aspx"); 

你可以尝试的另一件事情是这样的:

Me.Parent.ResolveUrl("~/Anything.aspx"); 

如果这些都不是工作,你可能想检查你的IIS设置,以确保你的网站被配置为一个应用程序。

+0

用户控件不会从页面中插入!并且在页面对象上调用父对象会自动返回,所以不需要。 – 2010-10-19 20:54:54

+0

@BurningIce - 感谢您的发现。我打算使用usercontrol的Parent。我用更正更新了代码示例。 – NightOwl888 2010-10-20 06:22:47

+0

,但仍然失败,因为然后处理程序的请求不会是类型页面,但最有可能的WebServiceHandler,因为文件tanathos请求最有可能具有扩展名.asmx或.svc(不.aspx)。 – 2010-10-20 16:08:37