Welcome to ESRI Blogs

Using ASP.NET AJAX with the Web ADF

Bryan Baker of the .NET SDK team wrote this great article on integration ASP.NET AJAX with the Web ADF.   

 

Microsoft's new ASP.NET AJAX enables developers to refresh portions of a Web page in a relatively simple way. To enable a control to use AJAX, the developer can put the control inside an UpdatePanel. Then any events on the control are automatically handled via AJAX, and updates are passed back without refreshing the entire page. For example, a page might have two drop-down lists. The first lists types of features, such as Cities and Countries. When the user picks a value in the first drop-down, the second list is populated with new values corresponding to the first list's value, such as a list of cities.

Web ADF developers might want to use this approach to update the Map or other ADF controls. For example, when the user selects a city in the second drop-down list, the Map would zoom to the selected city. The problem is that ASP.NET AJAX was released after the 9.2 version of the Web ADF, and these new features were not available to be incorporated. Putting Web ADF controls inside an UpdatePanel will not work correctly, and is not supported. At 9.3 ESRI does plan to support Web ADF controls with ASP.NET AJAX.

You can have both Web ADF and ASP.NET AJAX controls on the page. The challenge is doing something like the example above, where controls in an UpdatePanel communicate with Web ADF controls. This post shows one approach for this. It turns out that it takes less than a dozen lines of code beyond what would have been needed had the Map been inside the UpdatePanel! You can follow along if you have installed Visual Studio 2005, the Web ADF, and the ASP.NET AJAX 1.0 extensions.

Note that the use of ASP.NET AJAX is not supported by ESRI for version 9.2 of the Web ADF. If you use ASP.NET AJAX, you must be prepared to resolve any issues you encounter with using the Web ADF. You may find help at the ESRI Forums, but ESRI Support will not be able to assist with development issues.

Add the controls

I first created a new website using the "ASP.NET AJAX-Enabled Web Site" template in Visual Studio. This creates a website and adds some extra items to support AJAX into both the Default.aspx page and the web.config file. You'll notice the ScriptManager control already added to the Default.aspx page, which is a non-visual control that handles the AJAX functionality. If you wanted to add ASP.NET AJAX into an existing page or website, you'd need to add these same items that the template adds in. See the ASP.NET AJAX documentation for details.

ASP.NET AJAX and Web ADF controls on the page On the Default.aspx page, I added an UpdatePanel from the AJAX Extensions toolbox tab. I dragged two standard DropDownList controls into the UpdatePanel. The first DropDownList will display a list of layers. We could obtain these from the Web ADF controls on page startup, but I just added them manually for now to the Items property. I added two items: Cities and Countries. I also set the AutoPostBack property for both DropDownList controls to True. We need to do this to trigger a postback (actually a "partial postback" as ASP.NET AJAX calls it) when the user changes the selection.

Next I added a Map control and a MapResourceManager control from the ArcGIS Web Controls. Tip: having a drop-down list just above the map inteferes with the drop-down's functioning, so I put the map above the drop-down lists for this demo. I set the MapResourceManager property of the Map, and I added a resource item (map service) to the MapResourceManager as required to enable the map to display the service. In my case I used a world map with cities and countries. My simple page looks like the example here.

Update DropDownList items with ASP.NET AJAX

When the user changes the first drop-down list, the second list should display a list of cities or countries. Using ASP.NET AJAX allows us to treat this like a standard postback event. Behind the scenes, ASP.NET AJAX handles the request using AJAX methods rather than a full postback. Fortunately we don't have to deal with those details here.

I double-clicked on the DropDownList1 on the design page, which creates the method to handle the user selection in the code-behind page. We need to also fill the second DropDownList at startup, so we'll create a separate method and call it from both the drop-down's change method and the Page load method (which we can create by double-clicking on the design page). The UpdatePlaceList method fills the second DropDownList with locations and coordinates that we'll use later for zooming the map. The code below is in VB; both C# and VB versions are available in the download link at the end of this post.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

If Not Page.IsPostBack Then

UpdatePlaceList()

End If

End Sub





Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)

UpdatePlaceList()

End Sub



Sub UpdatePlaceList()

DropDownList2.Items.Clear()

If DropDownList1.SelectedValue = "Cities" Then

DropDownList2.Items.Add(New ListItem("Cape Town", "17|-36|21|-32"))

DropDownList2.Items.Add(New ListItem("Oslo", "9|58|13|62"))

DropDownList2.Items.Add(New ListItem("Washington", "-79|37|-75|41"))

ElseIf DropDownList1.SelectedValue = "Countries" Then

DropDownList2.Items.Add(New ListItem("Australia", "112|-43|157|-10"))

DropDownList2.Items.Add(New ListItem("Brazil", "-73|-33|-31|6"))

DropDownList2.Items.Add(New ListItem("China", "75|16|136|55"))

End If



End Sub



Zoom the Map when user selects a place

When the user selects a place in the second DropDownList, we need to zoom the map to the coordinates of that place. The challenge is to have the map's new extent be communicated to the client. Since the Map control cannot be in the UpdatePanel, we have to use another approach to communicate the results of the extent change to the Map.

The user selection in DropDownList2 triggers another partial postback. To set up the code for this, I double-clicked on DropDownList2 in design mode to create the method to handle the selected-index change. Inside this new method, I obtained the coordinates to zoom to from the DropDownList2.SelectedValue property. I parsed this value into an array of coordinate values, created a new envelope, and set the envelope's extent to these coordinates. I then set the Map's extent to this new envelope. This changes the map extent on the server. However, the client won't be aware of the change and won't obtain a new map unless we tell it to.

To get the client to update the map, we use a feature in ASP.NET AJAX to pass information to the client. The ScriptManager.RegisterDataItem method adds information that will be passed back and evaluated on the client.

The Map's CallbackResults will have the information required to update the map on the client. We pass this information to the client using the RegisterDataItem method. We'll see shortly how the client uses this information to update the map.

The code below obtains the callback results and registers them with the ASP.NET AJAX RegisterDataItem method. The ScriptManager1.IsInAsyncPostBack property ensures that we're doing an AJAX partial postback rather than a full page postback.

Protected Sub DropDownList2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)



Dim zoomString As String = DropDownList2.SelectedValue

Dim coordArr() As String = zoomString.Split("|")



Dim new_extent As New ESRI.ArcGIS.ADF.Web.Geometry.Envelope

new_extent.XMin = Double.Parse(coordArr(0))

new_extent.YMin = Double.Parse(coordArr(1))

new_extent.XMax = Double.Parse(coordArr(2))

new_extent.YMax = Double.Parse(coordArr(3))

Map1.Extent = new_extent



If ScriptManager1.IsInAsyncPostBack Then

Dim callbackString As String = Map1.CallbackResults.ToString()

ScriptManager1.RegisterDataItem(Map1, callbackString)

End If



End Sub



Handle the results on the client

The results that we just registered with ScriptManager need to be handled on the client. ASP.NET AJAX has a handler approach to process items passed back to the client. I inserted the code below into the .aspx page, at a point below the asp:ScriptManager tag. This code registers a client-side handler, the PageLoadingHandler function, that will run when the page loads. This handler obtains the items registered on the server with RegisterDataItem, and checks whether any items for the map control are present.  Since our server-side code added an item for the map, the code runs the next line.

This next line calls processCallbackResult and passes it the callback results we registered on the server. The processCallbackResult function is part of the Web ADF JavaScript library, which is automatically downloaded when the page uses Web ADF controls. The processCallbackResult function applies the callback results on the client by retrieving a new map. One caveat: the objects and methods in the client-side library can change, so this method could change with future versions of the Web ADF.

<asp:ScriptManager ID="ScriptManager1" runat="server" />



<script type="text/javascript" language="javascript">



Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(PageLoadingHandler);





function PageLoadingHandler(sender, args) {

var dataItems = args.get_dataItems();

if (dataItems['Map1'] != null)

processCallbackResult(dataItems['Map1'], 'Map1');

}



</script>



With this code in place, when the user selects an item in the places drop-down list, the server sets the map extent to that place, and the map on the client gets notified to retrieve a new map.

Tip: be careful about dragging controls around the page in Design mode when script blocks are within the page body. Doing so caused Visual Studio to remove my script block, which disabled the map update since no handler was available on the client!

Conclusion

We've seen how you can use controls in an ASP.NET AJAX UpdatePanel to control a Map in the Web ADF. Although it takes more work than if the Web ADF controls were embedded in the UpdatePanel, it is possible to do these tasks now. In our case it required less than a dozen lines of additional code compared to when the controls are all inside the UpdatePanel.

Download the code for this demo (includes C# and VB)

Try it out here

Published Monday, April 02, 2007 7:21 AM by Jeremy
Filed under: , ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: Using ASP.NET AJAX with the Web ADF

We have noticed that if you place an OverView map control on the page and wire it up, all Ajax partial post-backs take a very long time to occur (15+ seconds). This only occurs with the OverView map control. Plus, the partial postbacks really begin to slow down anyway once you add a lot of controls, in our case ESRI ADF controls to the page outside of UpdatePanels.
Monday, April 02, 2007 3:07 PM by David

# Using ASP.NET AJAX with the Web ADF via ScriptManager

On the ArcGIS server development blog you&rsquo;ll find a much waited post; how to use ASP.NET AJAX and

Tuesday, April 03, 2007 9:01 PM by Community Blogs

# Updating associated Web ADF controls

A follow-up to my post: in the AJAX partial postback, you may need to tell other Web ADF controls to synch up with the Map. For instance, if you have an OverviewMap control that displays the Map's extent, you need to refresh the OverviewMap in the AJAX partial postback. This is easy to do: use the .Refresh command, and then copy the control's CallbackResults to the Map (the first line below is in the DropDownList2_SelectedIndexChanged method above):

Map1.Extent = new_extent

OverviewMap1.Refresh()

Map1.CallbackResults.CopyFrom(OverviewMap1.CallbackResults)

The same approach would apply to a Toc (table of contents) control.

Wednesday, April 04, 2007 10:47 AM by

# re: Using ASP.NET AJAX with the Web ADF

This is EXCELLENT material. Thanks Bryan for writing this up. We need more stuff like this, please. Now what I would really like to see is how to use the Map control as a trigger to update something in an Update Panel. Example: a user selects features on a map and a grid in an update panel gets updated with the new corresponding data. Thanks again Bryan.
Wednesday, April 04, 2007 2:05 PM by Chuck Tilly

# re: Using ASP.NET AJAX with the Web ADF

Im with Chuck- Its great to see MS Ajax components updating the map, but to really use MS Ajax we need to know how to make the map control and other ADF controls update MS Ajax controls also. This is a great start though! Very interesting about the Overview Map causing problems- that seems like a big issue! Thank you Bryan!
Thursday, April 05, 2007 8:41 AM by jxn

# re: Using ASP.NET AJAX with the Web ADF

This is really cool!!....Opens Up many gates of such developments!!
Saturday, April 07, 2007 10:23 PM by AbdulMannan

# re: Using ASP.NET AJAX with the Web ADF

thank you for this tip. very interesting.
Wednesday, April 11, 2007 6:48 PM by MichalGasparovic

# re: Using ASP.NET AJAX with the Web ADF

This is a great sample application and is really appreciated. Please showcase more material that demonstrations the use of the Web.ADF with AJAX or how about working with the ADF floating panel. Thank you Bryan.
Wednesday, April 11, 2007 10:58 PM by Scott

# 在esri-ajax环境中涮新asp.net显示控件的通用方法

原来一直在esri的server论坛潜水,刚到esri-chinaserver论坛来学习,发现有不少人被esri-ajax困惑。我以前也被这个问题搞得晕头转向,现在基本明白原理了。

(1)arc...

Monday, August 20, 2007 5:27 PM by kylinindotnet

# 在esri-ajax环境中涮新asp.net显示控件的通用方法

原来一直在esri的server论坛潜水,刚到esri-chinaserver论坛来学习,发现有不少人被esri-ajax困惑。我以前也被这个问题搞得晕头转向,现在基本明白原理了。

(1)arc...

Monday, August 20, 2007 5:28 PM by kylinindotnet

# re: Using ASP.NET AJAX with the Web ADF

TOC don't get refreshed. Overview works but not TOC. Anyone with work arounds??
Friday, September 28, 2007 10:23 AM by Don Kang

# re: Refreshing the Toc

Don - the Toc control wasn't really designed to be refreshed outside the ADF's inherent callback framework. This is a good illustration of the issues with more involved use of AJAX at 9.2. Sometimes it takes more work to get things done, though usually it can be done. I worked out a way to get the contents of the Toc refreshed. It's a bit messy, but seems to work. This isn't thoroughly tested, but should give some ideas. Add the function below into your page class, and call it within the section where you set the results into the ScriptManager, like this:
If ScriptManager1.IsInAsyncPostBack Then
    Dim tocCbr As _
        ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = _
       refreshToc(Toc1)
Map1.CallbackResults.Add(tocContentResult)
...
Here's the refresh function for the Toc, first in VB, then in C#:
' [VB:] Refresh the Toc, return CallbackResult
Private Function refreshToc(ByVal toc As ESRI.ArcGIS.ADF.Web.UI.WebControls.Toc) _
As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult
' Toc1.Refresh reloads the toc nodes, but doesn't actually
' generate a callback result content, which we'll do manually.
toc.Refresh()
' Set up the output writer for the Toc
Dim sw As System.IO.StringWriter = New System.IO.StringWriter()
Dim writer As System.Web.UI.HtmlTextWriter = New HtmlTextWriter(sw)
' We can't call Toc.Render because it adds extra content
' we don't need and which causes errors. Instead, we
' manually render each node in the Toc.
Dim node As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode
For Each node In toc.Nodes
node.Render(writer)
Next
' Grab the HTML-rendered content of the Toc nodes
Dim tocNodesHtml As String = sw.ToString()
sw.Close()
' Surround the nodes HTML with the DIV as in the current Toc
Dim tocInnerContent As String = String.Concat("<div>", tocNodesHtml, "</div>")
' Set this HTML content to replace the inner content of the Toc
' (this won't replace the <Toc> div, but the insides of it
Dim tocContentResult As _
New ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult( _
toc, "innercontent", tocInnerContent)
Return tocContentResult
End Function
// [C#:] Refresh the Toc, return CallbackResult
private ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult refreshToc(
ESRI.ArcGIS.ADF.Web.UI.WebControls.Toc toc)
{
// Toc1.Refresh reloads the toc nodes, but doesn't actually
// generate a callback result content, which we'll do manually.
toc.Refresh();
// Set up the output writer for the Toc
System.IO.StringWriter sw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter writer = new HtmlTextWriter(sw);
// We can't call Toc.Render because it adds extra content
// we don't need and which causes errors. Instead, we
// manually render each node in the Toc.
foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode node in toc.Nodes)
{
node.Render(writer);
}
// Grab the HTML-rendered content of the Toc nodes
string tocNodesHtml = sw.ToString();
sw.Close();
// Surround the nodes HTML with the DIV as in the current Toc
string tocInnerContent = String.Concat("<div>", tocNodesHtml, "</div>");
// Set this HTML content to replace the inner content of the Toc
// (this won't replace the <Toc> div, but the insides of it
ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult tocContentResult =
new ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult(
toc, "innercontent", tocInnerContent);
return tocContentResult;
}
Thursday, October 11, 2007 11:07 AM by Bryan Baker

# re: Using ASP.NET AJAX with the Web ADF

Excellent material. The examples have enabled me to greatly improve the user experience in my web app. Does anyone have experience using these techniques with ESRI Floating Panels? I have an ESRI Floating Panel that I place query results in and would like this to occur asynchronously. I have attempted to use RenderControl (FloatingPanel1.RenderControl(writer)) on the FP to set up my CallbackResult similar to the TOC example. However, I continue to receive an error stating: "Control 'FloatingPanel1_hfHeight' of type 'HiddenField' must be placed inside a form tag with runat=server." Any suggestions?
Wednesday, November 07, 2007 9:47 AM by TM

# re: Using ASP.NET AJAX with the Web ADF

I am also getting the same error about the control needing to be placed inside a for tag with runat=server although it clearly is. Any ideas?
Thursday, November 08, 2007 9:08 AM by AJ

# re: Using ASP.NET AJAX with the Web ADF

I actually found a workaround that got rid of the error by performing these steps. 1. Added the following subroutine to my Default.aspx.vb page: Public Overloads Overrides Sub VerifyRenderingInServerForm(ByVal control As Control) ' Confirms that an HtmlForm control is rendered for the ' specified ASP.NET server control at run time. ' No code required here. End Sub 2. Added the following line to the "<@ Page" line of my Default.aspx page: EnableEventValidation="false" Sources: -http://www.pcreview.co.uk/forums/thread-1259153.php -http://geekswithblogs.net/azamsharp/archive/2005/12/21/63845.aspx These code additions get me around the error and work for my page. I am not sure how they would affect a more complex page. Thanks.
Friday, November 09, 2007 1:55 PM by TM

# re: Using ASP.NET AJAX with the Web ADF


Today I found a way to use the ASP.AJAX's UpdateTable with some ToolAction. The goal was to display the selected points in a GridView.
I tried to do this with javascript codes and _doPostBack methods, but it didn't work well. Until I find out that the ScriptManager object is the key.
So briefly here are may solution:

In the ServerAction method after query is done put the results into the Session:

HttpContext.Current.Session["MapResultTable"] = table;  

Call some javascript function:
string javascriptString = "updateFromMap();";
CallbackResult cr = new CallbackResult(null, null, "javascript", javascriptString);
MapInstance.CallbackResults.Add(cr);

Somewhere on the page we need some javascript code:
<script type="text/javascript" language="javascript">
        function updateFromMap() {
            __doPostBack('<%= FromMapBtn.ClientID %>', '');
        }
</script>

In an UpdatePanel let's hide a button:
<asp:UpdatePanel ID="UpdateFromMap" runat="server" UpdateMode="Conditional">
	<ContentTemplate>
		<asp:Button ID="FromMapBtn" runat="server" Text="From Map" Style="display:none"/>
        </ContentTemplate>
</asp:UpdatePanel>

In the Page_Load method do something like this:
ScriptManager sM = ScriptManager.GetCurrent(this);
if (sM.IsInAsyncPostBack) {
        if (sM.AsyncPostBackSourceElementID == TerkeprolBtn.ClientID) {
                //Bind the data to a GridView
                DataTable src = Session["MapResultTable"] as DataTable;
                _resultGV.DataSource = dt;
                _resultGV.DataBind();
                //refresh the GridView's UpdatePanel
                _updateResultGV.Update();
                //clear the data from the Session
                Session["MapResultTable"] = null;                
        }
}

And it might work for you as well ;)
Tuesday, December 11, 2007 7:26 AM by tomidny

# re: Using ASP.NET AJAX with the Web ADF

A small comment from an outside observer just glancing over these posts : wasn't asp.net and ajax supposed to simplify life? I'm not sure any other aspect of web development involves so much hoop jumping as working with esri controls.
Thursday, January 03, 2008 11:34 AM by Joe Blow

# re: Using ASP.NET AJAX with the Web ADF

hi, i am using scriptmanager & update panle to show adrotator on my map. But it casus problem in map result when i use pan tool. It showing wrong tile result. when i remove scriptmanager & update panel it works fine. Any idea how can i display correct result. Thanks
Tuesday, January 08, 2008 5:22 AM by Pragnesh

# re: Using ASP.NET AJAX with the Web ADF

I'd really like to be able to zoom to a feature selected from a drop-down, but I'd like the list of features to be populated dynamically. I was hoping there would be a way to pull the spatial extent for the feature without hard-coding coordinates. I have a list of buildings that is quite long and I don't want to have rewrite code every time my layer is edited. Is this possible in 9.2.4?
Tuesday, April 08, 2008 12:22 PM by Renee

# re: Using ASP.NET AJAX with the Web ADF

Has any found a solution to the Pragnesh discovered? I'm having the issue with pan something is not in sync with Feature Layer and Graphic Layer when using the pan tool?
Tuesday, May 06, 2008 3:04 PM by Jared A

# re: Using ASP.NET AJAX with the Web ADF

Dear All, I have one specific problem in 9.3 using .NET with respect to refreshing TOC. I am moving layer up on clikcing an item 'Move Layer Up' in context menu of TOC. Code works fine. But when I do second time Treeview Plus node become null protected void ContextMenu1_ItemClicked(object sender, ContextMenuItemEventArgs args) { ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode pNode = Toc1.Nodes.FindByNodeID(args.Context); //Here pNode value is null for second time clicking on layer in TOC. On Debugging TOC contains nodes but ID is not matched so it returns null. } How to Update TOC. Function given above doesnot helps. case "Move Layer UP": MoveLayerUP(pNode.Text); Map1.Refresh(); ContextMenu1.CallbackResults.CopyFrom(Map1.CallbackResults); Toc1.Refresh(); SetUpContextMenu(); ContextMenu1.CallbackResults.Add(RefreshControlHTML(Toc1)); //Referesh Control FUnction COde private ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult RefreshControlHTML(Control control) { try { System.IO.StringWriter strWriter = new System.IO.StringWriter(); HtmlTextWriter htmlWriter = new HtmlTextWriter(strWriter); control.RenderControl(htmlWriter); string htmlContent = strWriter.ToString(); strWriter.Close(); return new CallbackResult(control, "content", htmlContent); } catch (Exception ex) { callErrorPage(ex.Message, null); return null; } }
Saturday, July 05, 2008 3:51 AM by laksh

Leave a Comment

(required) 
required 
(required)