2010-06-30 60 views
6

我試圖實現類似於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

回答

4

問題是,頁面類不是像這樣實例化的。如果我們啓動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

0

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

0

我發現/ MyApp/root會導致各種問題。它並沒有真正回答你'爲什麼不能正常工作'的問題,但是你是否意識到你可以擺脫/ MyApp /並將你的網站託管在http:/ localhost/...?

只需在網站屬性中將「虛擬路徑」設置爲「/」即可。

這清除了所有的東西,除非你正試圖在開發PC上同時託管多個應用程序。

+0

問題是我有很多應用程序配置爲開發...現在我已經繞過這個問題使用Page.ResolveUrl(「〜/ mypage.aspx」),但我真的想明白爲什麼:) – tanathos 2010-07-09 16:25:03

0

可能是因爲新的頁面對象沒有「MyApp」作爲根目錄,所以它被默認解析爲服務器根目錄。

我的問題是它爲什麼與Page.ResolveUrl(...)一起使用。
也許ResolveUrl做了一些關於用戶控件的位置的調查,並基於此來解決。

0

奇怪,我重新創建了這個例子。該超鏈接對〜/ 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; 
    } 
} 

問候,

0

這是很難告訴你正在努力實現,而無需繳納,實際上將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