views:

225

answers:

3

Hi,

We are rendering usercontrols dynamically like this:

public string RenderControl(string pathcontrol)
{
    string html;

    var page = new Page();
    var control = page.LoadControl(path);            
    page.Controls.Add(control);

    // do stuff to the control (give it some data to work on)

    using (var writer = new StringWriter())
    {
        HttpContext.Current.Server.Execute(page, writer, false);
        html = writer.ToString();
    }

    return html;
}

This lets us the same user controls when rendering pages normally as we do when rendering responses to ajax calls. However, when adding controls which themselves contain a scriptmanagerProxy we run into the problem that the newed up Page object doesn't contain either a ScriptManager or the HtmlForm in which the ScriptManager needs to run.

Is there any way around this?

Yours Andreas

+1  A: 

Can you do something like this:

page.Form.Controls.AddAt(0, New ScriptManager())

Edit: I think you'd also need to add your control to the page's form, not just to the page itself, right? It's my understanding that the form is created with the page, but if not you should be able to just do:

page.Form = new HtmlForm()

You may also need to do something like:

page.Controls.Add(page.Form)
tloflin
page.Form is null on the page, page.Form is not settable (only has a getter)
AndreasKnudsen
A: 

Sure, the trick is to add it in a page's Init event handler. You can use:

Page.Init += delegate {

  // check for script manager
  if( ScriptManager.GetCurrent(Page) == null ) {

    ScriptManager m = new ScriptManager();
    m.ScriptMode = ScriptMode.Release;
    Page.Form.Controls.AddAt(0, m);

  }

}

I'd recommend avoiding dynamically adding forms to your page if you can. For example, the above code snippet assumes a form is already present on the page.

Update

Sure, thanks for pointing that out Andreas. Here's an update. So, there is no setter for Page.Form - but you are correct in that you can add a new HtmlForm to the Controls collection. Once added, the Page.Form property is no longer null. That will allow you to add the ScriptManager dynamically as seen above. Here is a code sample that shows this working (ASPX file is a simple page without a server side form):

public partial class Pages_Test_DynamicFormSample : Page {

    protected void Page_Init(object sender, EventArgs e) {

        Controls.Add( new HtmlForm() );

        ScriptManager m = new ScriptManager();
        m.ScriptMode = ScriptMode.Release;
        Form.Controls.AddAt(0, m);

    }

    protected void Page_Load(object sender, EventArgs e) {

        // ScriptManager test
        var t1 = new System.Web.UI.WebControls.TextBox();
        var t2 = new System.Web.UI.WebControls.TextBox();
        Form.Controls.Add( t1 );
        Form.Controls.Add( t2 );

        ScriptManager.GetCurrent(Page).SetFocus( t2 );

    }

}

Enjoy - btw, setting the ScriptManager's ScriptMode to Release obviously isn't required. We do it just to avoid some JavaScript bugs found in the Debug version of the ASP.NET script runtime.

sean2078
when newing up a Page in code as we do here, the problem is that there isn't a Form on that page, so the assumption in your snippet is false.
AndreasKnudsen
+2  A: 

As others have said you can add a ScriptManger dynamically easily enough [ http://stackoverflow.com/questions/183950/add-scriptmanager-to-page-programmatically if your Page object is complete.

Can you try using BuildManager.CreateInstanceFromVirtualPath() to create the Page object instead? You issue may be how you create that object. There's a bit more to creating a new page than newing up the Page object.

Eg.

Page page 
       = BuildManager.CreateInstanceFromVirtualPath("~/Test.aspx", typeof(Page))

See also http://www.west-wind.com/weblog/posts/120530.aspx for a little more background.

kervin
thanks! I got this to work, but in the end the rendered output now contains <form><div><input id="__VIEWSTATE" .... etc. for every control outputed in this way, which isn't doing it for me. In the end I ended up not relying on scriptmanagerproxies in the controls being dynamically rendered by services.
AndreasKnudsen