Tag Archives: WebForms

AjaxControlToolkit version 7.0123 with .NET 4.5

Here’s my steps and workarounds from the very beginning (in Visual Studio 2012), hopefully some part of this will help fix whatever error you are encountering.

File -> New Project
.NET Framework 4.5
Visual C# -> Web
ASP.NET Web Forms Application
Add AjaxControlToolkit version 7.0123 (dll is actually 4.5.7.123 which is January 2013 I believe) via NuGet

Open Default.aspx
Add a calendar to the BodyContent / MainContent:

<asp:TextBox ID="myTextBox" runat="server" />
<ajaxToolkit:CalendarExtender ID="myCalendar" runat="server" TargetControlID="myTextBox" Format="dd/MM/yyyy" />

Run it up (F5 will do)

It might error about ASP.NET Ajax 4.0 scripts:
0x800a139e – JavaScript runtime error: AjaxControlToolkit requires ASP.NET Ajax 4.0 scripts. Ensure the correct version of the scripts are referenced. If you are using an ASP.NET ScriptManager, switch to the ToolkitScriptManager in AjaxControlToolkit.dll.

I’ve also seen it error about:
‘MsAjaxBundle’ is not a valid script name. The name must end in ‘.js’.

No bother, let’s remove that reference from the Site.Master, so:

    <asp:ScriptManager runat="server">
        <Scripts>
            <%--Framework Scripts--%>
            <asp:ScriptReference Name="MsAjaxBundle" />
            <asp:ScriptReference Name="jquery" />
            <asp:ScriptReference Name="jquery.ui.combined" />
            <asp:ScriptReference Name="WebForms.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebForms.js" />
            <asp:ScriptReference Name="WebUIValidation.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebUIValidation.js" />
            <asp:ScriptReference Name="MenuStandards.js" Assembly="System.Web" Path="~/Scripts/WebForms/MenuStandards.js" />
            <asp:ScriptReference Name="GridView.js" Assembly="System.Web" Path="~/Scripts/WebForms/GridView.js" />
            <asp:ScriptReference Name="DetailsView.js" Assembly="System.Web" Path="~/Scripts/WebForms/DetailsView.js" />
            <asp:ScriptReference Name="TreeView.js" Assembly="System.Web" Path="~/Scripts/WebForms/TreeView.js" />
            <asp:ScriptReference Name="WebParts.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebParts.js" />
            <asp:ScriptReference Name="Focus.js" Assembly="System.Web" Path="~/Scripts/WebForms/Focus.js" />
            <asp:ScriptReference Name="WebFormsBundle" />
            <%--Site Scripts--%>

        </Scripts>
    </asp:ScriptManager>

Now becomes:

    <asp:ScriptManager runat="server">
        <Scripts>
            <asp:ScriptReference Name="jquery" />
            <asp:ScriptReference Name="jquery.ui.combined" />
            <asp:ScriptReference Name="WebForms.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebForms.js" />
            <asp:ScriptReference Name="WebUIValidation.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebUIValidation.js" />
            <asp:ScriptReference Name="MenuStandards.js" Assembly="System.Web" Path="~/Scripts/WebForms/MenuStandards.js" />
            <asp:ScriptReference Name="GridView.js" Assembly="System.Web" Path="~/Scripts/WebForms/GridView.js" />
            <asp:ScriptReference Name="DetailsView.js" Assembly="System.Web" Path="~/Scripts/WebForms/DetailsView.js" />
            <asp:ScriptReference Name="TreeView.js" Assembly="System.Web" Path="~/Scripts/WebForms/TreeView.js" />
            <asp:ScriptReference Name="WebParts.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebParts.js" />
            <asp:ScriptReference Name="Focus.js" Assembly="System.Web" Path="~/Scripts/WebForms/Focus.js" />
            <asp:ScriptReference Name="WebFormsBundle" />
        </Scripts>
    </asp:ScriptManager>

Next is ToolkitScriptManager, the snippet above now becomes:

    <ajaxToolkit:ToolkitScriptManager runat="server">
        <Scripts>
            <asp:ScriptReference Name="jquery" />
            <asp:ScriptReference Name="jquery.ui.combined" />
            <asp:ScriptReference Name="WebForms.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebForms.js" />
            <asp:ScriptReference Name="WebUIValidation.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebUIValidation.js" />
            <asp:ScriptReference Name="MenuStandards.js" Assembly="System.Web" Path="~/Scripts/WebForms/MenuStandards.js" />
            <asp:ScriptReference Name="GridView.js" Assembly="System.Web" Path="~/Scripts/WebForms/GridView.js" />
            <asp:ScriptReference Name="DetailsView.js" Assembly="System.Web" Path="~/Scripts/WebForms/DetailsView.js" />
            <asp:ScriptReference Name="TreeView.js" Assembly="System.Web" Path="~/Scripts/WebForms/TreeView.js" />
            <asp:ScriptReference Name="WebParts.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebParts.js" />
            <asp:ScriptReference Name="Focus.js" Assembly="System.Web" Path="~/Scripts/WebForms/Focus.js" />
            <asp:ScriptReference Name="WebFormsBundle" />
        </Scripts>
    </ajaxToolkit:ToolkitScriptManager>

But of course this fails with:
Could not load file or assembly ‘System.Web’ or one of its dependencies. The system cannot find the file specified.

Remove the Assembly=”System.Web” part from the ScriptReference so we have have:

    <ajaxToolkit:ToolkitScriptManager runat="server">
        <Scripts>
            <asp:ScriptReference Name="jquery" />
            <asp:ScriptReference Name="jquery.ui.combined" />
            <asp:ScriptReference Name="WebForms.js" Path="~/Scripts/WebForms/WebForms.js" />
            <asp:ScriptReference Name="WebUIValidation.js" Path="~/Scripts/WebForms/WebUIValidation.js" />
            <asp:ScriptReference Name="MenuStandards.js" Path="~/Scripts/WebForms/MenuStandards.js" />
            <asp:ScriptReference Name="GridView.js" Path="~/Scripts/WebForms/GridView.js" />
            <asp:ScriptReference Name="DetailsView.js" Path="~/Scripts/WebForms/DetailsView.js" />
            <asp:ScriptReference Name="TreeView.js" Path="~/Scripts/WebForms/TreeView.js" />
            <asp:ScriptReference Name="WebParts.js" Path="~/Scripts/WebForms/WebParts.js" />
            <asp:ScriptReference Name="Focus.js" Path="~/Scripts/WebForms/Focus.js" />
            <asp:ScriptReference Name="WebFormsBundle" />
        </Scripts>
    </ajaxToolkit:ToolkitScriptManager>

It seems the new web forms project template adds ‘Microsoft.AspNet.ScriptManager.MSAjax 4.5.6’ package, this appears to conflict with the toolkit, so remove this via “Manage NuGet Packages”
Visual Studio might still leave the dll in your bin directory even after a clean, make sure you manually clean that out.

So there we are, works for me, best of luck.

EDIT:

Silly me, I forgot, remove the Name too (e.g. Name=”WebForms.js” ) for each that have a Path. If you don’t you will get errors like so:
The assembly ‘AjaxControlToolkit, Version=4.5.7.123, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e’ does not contain a Web resource that has the name ‘WebForms.js’. Make sure that the resource name is spelled correctly.

ASP.NET Web Forms Response.Write in an UpdatePanel #dev #web

I recently had a problem at work where I wanted to use some code that writes to the Response.Output TextWriter, this works fine until you stick an UpdatePanel around the line that writes to it. Various searches on the internet didn’t reveal any clues as to how to do this, all that I found suggested alternatives and used words like “doesn’t work” and use “PostBackTrigger” (which, by the way, negates the whole point of an UpdatePanel).

For fear of being labelled a hack-it together guy, I came up with two solutions, one is rock solid, the other is less so, but works wonderfully until they change how UpdatePanels work (which is unlikely given the fact that Web Forms is a dying technology, if you disagree then we will never be friends).

The basis of the solution

A control (anything inheriting from WebControl) is given a TextWriter on RenderBeginTag, RenderEndTag, … etc. Ah (ching, the penny drops), maybe this is different from Response.Output when we are processing an Async Postback? Indeed it is!

An example where Response.Output.Write doesn’t work

This is the standard Web Forms template application with the content removed.

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ResponseWriteUpdatePanel._Default" %>
<asp:Content runat="server" ID="FeaturedContent" ContentPlaceHolderID="FeaturedContent">
</asp:Content>
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
    <asp:UpdatePanel runat="server">
        <ContentTemplate>
            <% Response.Output.Write("Hello"); %>
            <asp:TextBox Text="Text Here" ID="MyTextBox" runat="server" />
            <asp:Button Text="Button" ID="MyButton" runat="server" />
        </ContentTemplate>
    </asp:UpdatePanel>
</asp:Content>

Click the button and the Response.Output.Write destroys the response:

Unhandled exception at line 1, column 126350 in http://localhost:49213/bundles/MsAjaxJs?v=J4joXQqg80Lks57qbGfUAfRLic3bXKGafmR6wE4CFtc1

0x800a139e – JavaScript runtime error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.

Details: Error parsing near ‘1|#||4|Hello245|updatePanel’.

Here’s a server control that captures the TextWriter and sticks it into the Response.Output (this is the less so option):

using System.Web.UI;
using System.Web.UI.WebControls;

namespace ResponseWriteUpdatePanel
{
    public class MyResponseHelper : WebControl
    {
        public override void RenderBeginTag(HtmlTextWriter output)
        {
            this.Page.Response.Output = output;
        }

        public override void RenderEndTag(HtmlTextWriter output)
        {
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
        }
    }
}

Then add to the page, like so:

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ResponseWriteUpdatePanel._Default" %>
<%@ Register TagPrefix="tim" Namespace="ResponseWriteUpdatePanel" Assembly="ResponseWriteUpdatePanel" %>
<asp:Content runat="server" ID="FeaturedContent" ContentPlaceHolderID="FeaturedContent">
</asp:Content>
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
    <asp:UpdatePanel runat="server">
        <ContentTemplate>
            <tim:MyResponseHelper ID="MyOutput" runat="server"></tim:MyResponseHelper>
            <% Response.Output.Write("Hello"); %>
            <asp:TextBox Text="Text Here" ID="MyTextBox" runat="server" />
            <asp:Button Text="Button" ID="MyButton" runat="server" />
        </ContentTemplate>
    </asp:UpdatePanel>
</asp:Content>

Voila, it works.

Next, the more rock solid solution which avoids tinkering with the Response.Output:

using System.Web.UI;
using System.Web.UI.WebControls;

namespace ResponseWriteUpdatePanel
{
    public class MyResponseHelper : WebControl
    {
        public HtmlTextWriter Output { get; set; }

        public override void RenderBeginTag(HtmlTextWriter output)
        {
            Output = output;
        }

        public override void RenderEndTag(HtmlTextWriter output)
        {
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
        }
    }
}

And the page directly uses the TextWriter from the control instead of the Response.Output, like so:

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ResponseWriteUpdatePanel._Default" %>
<%@ Register TagPrefix="tim" Namespace="ResponseWriteUpdatePanel" Assembly="ResponseWriteUpdatePanel" %>
<asp:Content runat="server" ID="FeaturedContent" ContentPlaceHolderID="FeaturedContent">
</asp:Content>
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
    <asp:UpdatePanel runat="server">
        <ContentTemplate>
            <tim:MyResponseHelper ID="MyOutput" runat="server"></tim:MyResponseHelper>
            <% MyOutput.Output.Write("Hello"); %>
            <asp:TextBox Text="Text Here" ID="MyTextBox" runat="server" />
            <asp:Button Text="Button" ID="MyButton" runat="server" />
        </ContentTemplate>
    </asp:UpdatePanel>
</asp:Content>

Of course, should you have two UpdatePanels on the same page then you would use a MyResponseHelper within each and use that instance.