Atlas:UpdatePanel + Template = Really Darned Kewl

I must say that ASP.NET Atlas, Microsoft’s free Ajax framework is pretty cool. Far and away my favorite feature is that it allows me, a Javascript challenged C# head, to build really slick, Ajaxy apps without leaving my server-side comfort zone. All that needed be done was write the application so that it worked within the normal ASP.NET lifecycle, events and parameters. Then slap some Atlas:UpdatePanels in there and let the framework do its thing.

Or so I thought. I tried to include those UpdatePanels in a templated control, such as a Repeater. And Atlas go boom. Now, this was not an insurmountable problem. One could always surround the entire repeater in an update panel. Or go back to classic, non-Atlas methods.Or actually learn Javascript and make your own plumbing. None of which are very appealing options.

Conveniently, the Atlas team also saw this as an fix-worthy issue. And, on 30 June, they released yet another CTP—creatively called the “Atlas” June CTP—to the public. It has a number of tweaks and bug fixes, one of which is near and dear to my heart:

UpdatePanels can be added to a page dynamically throughout the page lifecycle, including UpdatePanels inside templates. UpdatePanels now also work inside WebParts, and WebParts can be inside UpdatePanels.

So, I worked up a little demo of how handy the new functionality is. And, by inference, how cool Atlas can be.

Scenario: You have a list of contacts with four fields: Id, FirstName, LastName and Email. It is required that one cannot see an email address without clicking on a link instructing the application to show that address. An example of the dataset in Xml is posted at the end of this post for reference.

Now, one can go after this using two methods. First, one can rely upon a traditional postback and a full page refresh. Or one can embrace Web 2.0 and get their Atlas on. The really slick thing is that both methods could use the exact same codebehind file [ok, not exactly—you will need to change the class name to match your CodeFile reference in the .aspx file]. It looks like this:


private DataSet peopleDs;

protected DataTable People
{
	get
	{
		if (peopleDs == null)
		{
			peopleDs = new DataSet();
			peopleDs.ReadXml(Server.MapPath("~/App_Data/Data.xml"));
		}
		return peopleDs.Tables[0];
	}
}

protected void Page_Load(object sender, EventArgs e)
{
	if (!this.IsPostBack)
	{
		this.DataBind();
	}
}

protected void ItemButtonClicked(object sender, EventArgs e)
{
	Control csender = (Control)sender;
	Literal litid = (Literal)csender.NamingContainer.FindControl("PersonId");
	string email=getEmailAddress(litid.Text);
	HyperLink link = (HyperLink)csender.NamingContainer.FindControl("EmailAddress");
	link.NavigateUrl = string.Format("mailto:{0}", email);
	link.Text = email;
	csender.Visible = false;
	link.Visible = true;
}

private string getEmailAddress(string id)
{
	string ret = "NO EMAIL";
	DataRow[] match = People.Select("Id=" + id);
	if (match.Length > 0)
	{
		ret = (string)match[0]["Email"];
	}
	return ret;
}

Now, the traditional method for displaying this is very straightforward. See below for an example:


<form id="form1" runat="server">
	<div>
	<asp:Repeater runat="server" ID="PersonRepeater" DataSource="<%# People %>">
		<ItemTemplate>
			<div style="border: solid 1px black; padding: 5px">
				<asp:Literal ID="PersonId" runat="server" 
						Visible="false" Text='<%# DataBinder.Eval(Container.DataItem, "Id") %>' />
					First Name:
					<%# DataBinder.Eval(Container.DataItem, "FirstName") %>
					<br />
					Last Name:
					<%# DataBinder.Eval(Container.DataItem, "LastName") %>
					<br />
				<asp:LinkButton runat="server" ID="ShowEmail" OnClick="ItemButtonClicked" 
								Text="Show Contact Info" />
				<asp:HyperLink ID="EmailAddress" runat="server" Visible="False" />
			</div>
		</ItemTemplate>
	</asp:Repeater>
	</div>
</form>
	

But, what if your client demanded that his site be Ajax enabled? It is disturbingly easy—just add a little bit of Atlas plumbing and an update panel. Oh, and don’t forget the Atlas:UpdateProgress so you can justify the bill.


<form id="form1" runat="server">
	<atlas:ScriptManager ID="TheScriptManager" runat="server" EnablePartialRendering="true" />
	<div>
		<atlas:UpdateProgress ID="UpdateProgress" runat="server">
			<ProgressTemplate>
				<span style="position: absolute; top: 0; left: 0; height: 15px; color: White; background-color: Red;
					width: 50px">UPDATING</span>
			</ProgressTemplate>
		</atlas:UpdateProgress>
		<asp:Repeater runat="server" ID="PersonRepeater" DataSource="<%# People %>">
			<ItemTemplate>
				<div style="border: solid 1px black; padding: 5px">
					<asp:Literal ID="PersonId" runat="server" 
						Visible="false" Text='<%# DataBinder.Eval(Container.DataItem, "Id") %>' />
					First Name:
					<%# DataBinder.Eval(Container.DataItem, "FirstName") %>
					<br />
					Last Name:
					<%# DataBinder.Eval(Container.DataItem, "LastName") %>
					<br />
					<atlas:UpdatePanel ID="RepeaterUpdatePanel" runat="Server" Mode="conditional">
						<Triggers>
							<atlas:ControlEventTrigger ControlID="ShowEmail" EventName="Click" />
						</Triggers>
						<ContentTemplate>
							<asp:LinkButton runat="server" ID="ShowEmail" OnClick="ItemButtonClicked" 
								Text="Show Contact Info" />
							<asp:HyperLink ID="EmailAddress" runat="server" Visible="False" />
						</ContentTemplate> 
					</atlas:UpdatePanel>
				 </div> 
			</ItemTemplate>
		</asp:Repeater>
	</div>
</form>

The first thing to note above are the new Atlas:SomeControlName tags. The ScriptManager runs the show; it is required to “Atlas enable” a page. The UpdateProgress control is a visual flourish—it allows one to tell the user that an update is in progress, much like the “LOADING” one sees in the top-right on Gmail.

That leads us to the Atlas:UpdatePanel. This is a very slick control that lets one allow a page to be partially rendered and fire back updates based on registered events. In this case, we provide a template—containing our LinkButton and the HyperLink it interacts with—and a single Trigger. This trigger is what Atlas uses to fire off the update. And a panel can have multiple triggers. In our case we needed but one—our LinkButton’s click event. And, as the code sample shows, that event behaves nearly identically to a standard, full-page postback.

Zero to Web 2.0 in 6.4 minutes. Without writing one character of Javascript nor modifying your C#.

Appendix: The Xml File


<Persons>
  <Person>
    <Id>1</Id>
    <FirstName>Donald</FirstName>
    <LastName>Duck</LastName>
    <Email>DonaldDuck@disney.com</Email>
  </Person>
  <Person>
    <Id>2</Id>
    <FirstName>Mickey</FirstName>
    <LastName>Mouse</LastName>
    <Email>MickeyMouse@disney.com</Email>
  </Person>
  <Person>
    <Id>3</Id>
    <FirstName>Peter</FirstName>
    <LastName>Pan</LastName>
    <Email>Peter@neverland.net</Email>
  </Person>
  <Person>
    <Id>4</Id>
    <FirstName>Captain</FirstName>
    <LastName>Hook</LastName>
    <Email>CapHook@neverland.net</Email>
  </Person>
</Persons>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.ilovecode.com ses5909

    That is great for someone like me who is just awful with and really has no interest in client-side code. I can quit paing someone else to do it :)

  • Pingback: ilovecode » SitePoint has a new .NET blogger

  • http://www.squarefootball.net amelvin1968

    Is there any indication as to when Atlas will move out of CTP and into a fully supported product?