2

probably a simple oversight I've missed (though I vaguely recall some obscure blogpost about the inner workings of Response.Write not working as expected in some situations but I don't remember if this is one of them):

The situation is, I have a Link Button on a control running in SP2010, and if I don't use HttpContext.Response.Write(), everything works as expected (ie I can change the .Text value for a Label). However, if I call Context.Response.Write(), while I can debug and step through the code, nothing seems to happen any more (nothing is written back and changes to other controls do not appear). It's being run on an application page in _layouts, appearing in a modal dialog.

(basically, I'm trying to do this - http://acveer.wordpress.com/2011/01/25/using-the-sharepoint-2010-modal-dialog/ but it doesn't work. EDIT: If I change it to a asp:Button, it still doesn't work)

Here's some code if you're interested:

.aspx:

@ Page Language="C#" AutoEventWireup="true" ... 
<asp:LinkButton CssClass="button remove" runat="server" OnClick="remove_Click" Text="Remove" ID="remove"></asp:LinkButton>

.aspx.cs:

    public void remove_Click(object sender, EventArgs e)
    {
        ....

        //if successful
        HttpContext context = HttpContext.Current;
        if (HttpContext.Current.Request.QueryString["IsDlg"] != null)
        {
            testControl.Text = "test code";

            //doesn't work, and prevents line above from working
            Context.Response.Write("<script type='text/javascript'>alert('hi!');</script>");
            Context.Response.Flush();
            Context.Response.End();

           // context.Response.Write("<script type='text/javascript'>window.frameElement.commitPopup()</script>");
           // context.Response.Flush();
           // context.Response.End();
        }           
    }

Anyone come across something similar?

EDIT: some more interesting pieces that may help,

  • The button itself lies within an UpdatePanel
  • I do have a AsyncPostbackTrigger assigned
Henry C
  • 4,781
  • 4
  • 43
  • 83

3 Answers3

3

Using Response.Write from Web Forms code behind is problematic at best. As a rule of the thumb: never ever use Response.Write from a Web Forms page or user control.

The reason Response.Write is problematic, is because it is not part of the page's control tree, and rendering infrastructure. This means that when used within events in it will output the text outside of the normal page flow, and usually outside of the proper HTML page structure.

This is also why things go awry when you're using them in combination with UpdatePanels. As UpdatePanels are specifically designed to replace parts from a page, the infrastructure needs to know which parts. A Response.Write happens completely outside of this, and there's no real way of knowing where to render it. At best, the ScriptManager will perform a Response.Clear to wipe out your Response.Writes, at worst you'll break the UpdatePanel protocol body and you'll get a JavaScript error.

To top things off, any literal <script> tag will be ignored when you're performing a partial page update, as the browser's innerHTML feature used to fill in the HTML fragments sent by the server does not execute <script> tags.

Now, with all this theory out of the way -- is there no way to execute a piece of JavaScript code through an UpdatePanel? It turns out there is, and it's a lot cleaner than just executing a Response.Write: ScriptManager.RegisterClientScriptBlock and ScriptManager.RegisterStartupScript. For example:

ScriptManager.RegisterClientScriptBlock(
    theButton, // control or UpdatePanel that will be rendered
    typeof(YourPage), "UniqueKey", // makes your script uniquely identifiable
    "alert('Testing!');", true);

The important part is the first argument: now the ScriptManager will know when to execute your script. If you register it on a control that is not updated on a partial page refresh, your script will not execute. But if the UpdatePanel containing the control is refreshed, your script that is hooked up to it will also execute. And that's usually exactly what you want.

If you always want to execute your script, regardless of which panel updates, you'd call

ScriptManager.RegisterClientScriptBlock(Page, ... );
Ruben
  • 15,217
  • 2
  • 35
  • 45
3

@Ruben provided a very good answer, but I felt I could add useful content that doesn't fit in a comment.

There are a few occasions in SharePoint where you use a Response.Write - namely when dealing with webparts that are displayed within a SharePoint Modal popup and you want to do something cute with the callback when using window.frameElement.commitPopup().

The fact that you are using Response.Write within an update panel is actually part of your issue. When a postback that was generated with an update panel returns, the response is formatted with UpdatePanelId|Response Content where UpdatePanelId is the div associated with the update panel and Response Content is the new inner HTML of the div. When you use response.write, that format is lost, therefore the ScriptManager has no idea what to do with the response and should ignore it as erroneous. @Ruben provided you a method of registering scripts within an UpdatePanel.

Jaime Torres
  • 10,365
  • 1
  • 48
  • 56
2

Context.Response... should have a lower case context

ie:

context.Response.Flush()

etc

or am I missing the point?

podiluska
  • 50,950
  • 7
  • 98
  • 104
  • It compiles fine - I had HttpContext context = HttpContext.Current; above it - i've also tried Page.Context and this.Context.Current~ – Henry C Aug 08 '12 at 14:24
  • Yes, but you aren't referring to that `context` later, you're referring to a `Context`. Are you trying to make the script appear when you click the button? – podiluska Aug 08 '12 at 14:31
  • 1
    @podiluska You are correct, it just so happens that Context and HttpContext.Curret (which is now context) are the same object, so there is no negative affect on his code other than unreferenced variables and unnecessary redundancy. – Jaime Torres Aug 08 '12 at 15:18