【问题标题】:Asp.Net single control render for AJAX calls用于 AJAX 调用的 Asp.Net 单一控件渲染
【发布时间】:2010-06-30 16:08:38
【问题描述】:

我正在尝试实现类似于this 或this 的东西。

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

一切正常,但是如果我在使用相对路径的用户控件中放置一些东西(在我的例子中是带有 NavigateUrl="~/mypage.aspx" 的超链接),则相对路径的解析在我的开发服务器中失败。

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

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

缺少“我的应用”...

我认为问题在于用于加载控件的页面的创建:

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

但我不知道为什么....

编辑 只是为了清楚

我的用户控件位于~/ascx/mycontrol.ascx 并包含一个非常简单的结构:现在只是一个带有 NavigateUrl 的超链接,例如"~/mypage.aspx"。 而“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"),我会得到正确的页面网址: http://localhost:999/MyApp/mypage.aspx

现在我会这样做,但我会明白为什么它不能以正常方式工作。 有什么想法吗?

【问题讨论】:

  • 您在页面/控件生命周期的哪个位置调用hl.NavigateUrl = Page.ResolveUrl("~/mypage.aspx")?在执行此操作之前,您是否只是在代码中的同一位置运行 hl.NavigateUrl = "~/mypage.aspx"?

标签: asp.net ajax user-controls relative-path


【解决方案1】:

问题是 Page-class 并不是为了像那样实例化。如果我们启动 Reflector,我们将很快看到 Asp.Net 内部在实例化 Page 类并将其作为 IHttpHandler 返回后设置了一个重要属性。您必须设置 AppRelativeTemplateSourceDirectory。这是一个存在于 Control 类中的属性,它在内部设置 TemplateControlVirtualDirectory 属性,例如 HyperLink 使用该属性来解析链接中“~”的正确 url。

在调用 LoadControl 方法之前设置此值很重要,因为 AppRelativeTemplateSourceDirectory 的值会传递给“主”控件创建的控件。

如何获得正确的值以设置您的属性?在 HttpRuntime 类上使用静态 AppDomainAppVirtualPath。 Soo,总结一下……这应该可行;

[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();
}

【讨论】:

    【解决方案2】:

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

    NavigateUrl="./whatever.aspx"
    

    编辑:
    这是一个可能也有帮助的链接...http://msdn.microsoft.com/en-us/library/ms178116.aspx

    【讨论】:

    • 但是我想要我的 url 上的应用程序路径,我需要它用于我的本地开发服务器。网址localhost:999/mypage.aspx 根本不存在。如果我把 ascx 放在一个页面上,所有的相对路径都被解析为localhost:999/MyApp/something.something ...这是正确的。
    • 您能否显示 ascx 的页面注册标记以及您网站结构的简单说明(页面位于何处,控件位于何处)?我感觉这是因为控件/页面位于不同的目录中。
    【解决方案3】:

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

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

    这一切都清楚了,当然,除非您尝试同时在开发 PC 上托管多个应用程序。

    【讨论】:

    • 问题是我已经为开发配置了很多应用程序......现在我已经使用 Page.ResolveUrl("~/mypage.aspx") 绕过了这个问题,但我真的会想了解为什么:)
    【解决方案4】:

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

    我的问题是为什么它适用于Page.ResolveUrl(...)。
    也许ResolveUrl 对用户控件的位置进行了更多调查,并据此解决。

    【讨论】:

      【解决方案5】:

      奇怪,我重新创建了这个例子。对于 ~/Default.aspx 的给定导航 url,超链接呈现为 <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;
          }
      }
      

      问候,

      【讨论】:

        【解决方案6】:

        如果不发布实际设置超链接的 URL 的行,很难说出您想要实现的目标,但我想我了解您的目录结构。

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

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

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

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

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

        如果这些都不起作用,您可能需要检查 IIS 设置以确保您的站点配置为应用程序。

        【讨论】:

        • 用户控件不从 Page 进行交互!?并且在 Page 对象上调用 Parent 会返回自身,因此不需要。
        • @BurningIce - 感谢您发现这一点。我的意思是使用用户控件的父级。我用更正更新了代码示例。
        • 但是您上面的代码仍然失败,因为请求的处理程序不会是 Page 类型,但很可能是 WebServiceHandler,因为 tanathos 请求的文档很可能具有扩展名 .asmx 或 .svc (不是 .aspx)。
        • @BurningIce - 请注意,OP 指定它是失败的用户控件。您是正确的,此代码在 Web 服务中不起作用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-20
        • 1970-01-01
        • 2021-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多