Minggu, 23 Januari 2011

AjaxWorld Talk: Building a Great Ajax application from Scratch


I had a great time today at AjaxWorld during my talk on building a great Ajax Application from Scratch. It was fun to get out from behind the powerpoint and show some real code!

For this demo, I only used freely available tools... In particular everything I show works in Visual Studio 2008 Web Developer Express.

Peter Galli posts on Microsoft's general presence at AjaxWorld.

The folks at sys-con already posted a quick story on my talk:

Presented A No-Slides, Code Only Session at AJAXWorld

Download the complete samples.

Part I: CSS and HTML Designer

First, I showed off what a great CSS and HTML designer Visual Studio 2008 is. For this part of the demo I didn't use any ASP.NET or .NET specific code... All of this works great with plain old HTML and CSS...

Download and Install Visual Web Developer Express (free)

File\New Project and select the ASP.NET Web Application

image

Then I dragged in some HTML to start with, and a directory of Image..

I showed off VS's split view... how you can type or highlight in the design view and have it show in the code view (and vice-versa).. This is an excellent feature for tracking down what markup corresponds what visual element.

image

OK - now what we really want is a nice grid-like display rather than the single list. To do this, let's use standards based CSS that works cleanly in any browser.

I'll use VS 2008's great new CSS support. I used the Manage Styles panel to create a new CSS Selector... Notice I use ".photolist li" this rule will apply to any li inside an element with the class photolist.

Also, notice we can select where to define the css rules in. I have selected in a new style sheet. VS will create the new style sheet and (optionally) reference it from the current page.

image

In this case, I create a new style sheet and VS automatically add a reference to it from my HTML document.

Then notice, back in the HTML editor I get great intellisense..

clip_image002

Now, I can open up the CSS file and see how clean it is? Also, notice I can do code-focused editing of the CSS rather than use the designers. Again, I get great help from VS.

clip_image002[5]

Next, in design view, I click on an image... notice the breadcrumb at the bottom of VS shows you where you are in the visual tree. Hit escape to navigate up the tree until the list item (li) is selected.

image

We want this to layout like a grid, so in the CSS Properties window, under Layout, set Display to "inline" and float to "left"

image

That looks pretty good, but we need a bit more padding, so let's use the grab-handles in the designer to give us a little more spacing...

image

Again, notice how all these edits are cleanly going into the attached CSS style sheet rather than gunking up our code.

image

Finally, let's make this look really nice by throwing it a MasterPage will will give a common look and feel across our site. We will do this by dragging in Site.master and Site.Master.cs.

image

And we are starting go have something that looks sort of nice!

image

Part II: Data access with Linq

OK, that was great, but in a real world site you don't deal with static images... you need to pull data out of a database. So let's change the site around a bit to pull data from a database.

First, I will drag in photos.mdb into App_Data, this is a SqlServer database that I created for this demo... I will use the free Sql Express to allow me to use it at development time.

As you can see it is a simple database.

clip_image002[9]

Now, as a .NET developer, I'd really like to operate against this database as a set of .NET types rather than having to remember and debug some T-Sql code in my .NET code. Luckily Linq solves this for me!

To add a Linq data model for this database... Add New Item, then select ADO.NET Entity Data Model

image

We select to work from a database, then the Entity Framework designer knows we have a Sql Express database in the project and defaults to using it. Notice EF support TONs of different databases including MySql and Orcale!

image

Then we select what tables we want to include in our model.

image

Then you see the design surface showing you what the designer created.

image

This is the view of your .NET types that represent your database. Notice VS picked up on the relationships between the tables. You can of course edit these names in this designer view as well.

Notice, while this will do direct CRUD operations against the database, it is very possible to encapsulate all access through stored procs if need be.

Now, let's go back to the UI and give us some place to put this data. I will show off the new ListView control in ASP.NET.

The way ListView works, is that you give it a layout template that defines exactly how you work the markup to look. In our case, we will just cut and pate that ul into the layout template and define a place holder of the li's

image

Now we just need to get some real data.

   1: protected void Page_Load(object sender, EventArgs e)


   2: {


   3:     int rating = 2;


   4:     var db = new PhotosEntities();


   5:     var q = from photo in db.PhotoSet


   6:             where photo.Rating > rating


   7:             orderby photo.Tags.FirstOrDefault().TagName descending


   8:             select photo;


   9:     this.lv.DataSource = q;


  10:     lv.DataBind();


  11: }




In line 4, we create the data context... this is the logic connection string for our Linq data model.



In line 5, we are using C#'s new var keyword which allows us to fudge on the type of the express...the compiler will figure it out...



In line 6, we are doing a where clause, notice that I am capturing a local variable in that, clearly this example is trivial, but it is a powerful feature.



in line 7 notice i am ordering by the first tag name, notice how nice this reads? It would be much harder to do this in TSQL!



in line 9 and 10 and I doing the normal databinding.





image



Now we are really starting to look good!



image





Now, that is nice, but there are a ton of results here.. we really need a nice way to page through them.



I use the new DataPager control in ASP.NET 3.5.. Notice it can have filed that are simple Next\Prev or numeric or you can even build your own!



clip_image002[11]



Here is the complete code:





   1: <asp:DataPager runat="server" ID="dp"


   2:               PagedControlID="lv">


   3:   <Fields>


   4:       <asp:NumericPagerField />


   5:   </Fields>


   6: <asp:DataPager>




Now, we need to ensure that the ListView will show the correct items when the data pager changes. We do this by adding a PreRender() method to the page. A simplified view of the page lifecycle is Page_Load(), then the control events are raised, then Page_PreRender() is called. In our case the events from the pager need to be raised to change the page before we bind the list.





protected void Page_PreRender() { 


    lv.DataBind();


}




And notice it works great!



image





Part III: Server Side Ajax



Now it is time to add a little ajax fun to the site. Notice as I page through the items I am getting a little blink? That is because the page is doing a full post-back to the server when only the images are changing. It would be great if I could update only the part of the page that is changing!



And you can with UpdatePanel. Simply wrap the UpdatePanel's content template around the area of the page that you want to update separately. the runtime will turn any postbacks into XmlHttp calls, back the the server, get the right HTML and then bring in back and update only the part of the DOM effected. Simple. Powerful.



image



Oh, and don't forget to add ScriptManager to the top of the page. This "turns on" the ajax functionality in ASP.NET...



 


Now the page refreshes much more smoothly.



For the demo, we are running against localhost, but in the real world there is network load, congestion on the Internet, etc that may effect your page's responsiveness. But you want to give user's an immediate response to their actions... to let them know that something is happening.



You can use a Thread.Sleep (2000) in your page's load method to simulate this sort of load..



Enter UpdateProgress... This little control listens for calls over XmlHttp and shows a progress template as they go out and takes it down when they come back in... That plus a little animate gif gives users a great sense of "something happening".





<asp:UpdateProgress ID="UpdateProgress2" runat="server">


    <ProgressTemplate>


        <div id="UpdateProgressBox">


            <img id="Img2" runat="server" alt="Loading" src="~/Images/ajax-loader.gif" /></div>


    </ProgressTemplate>


</asp:UpdateProgress>




And now the site looks good!



image





Part IV: Client Side Ajax



Next we want to allow users to edit those titles, but in a smooth way that doesn't require form postback to the server.



We start by changing the rendering of the title to an input control





<input id="titleTextBox" 


       onchange="onTitleChange(this.value, <%#Eval("ID") %>);"


       value="<%#Eval("Title") %>" />




Now we need to go define the onTitleChange client side javascript method.  


We do this in the header content area our MasterPage has left us.





<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">


<script type="text/javascript">
   1:  
   2:  
   3:     function onTitleChange(title, id) {
   4:     
   5:     }
   6:  
</script>


 


</asp:Content>




Notice that VS 2008 has some great intellisense for JavaScript. We are actually running a JavaScript interpreter in the background, so we always know what type the objects are.



For example, here VS knows n is a Dom element.



clip_image002[15]



But we can easily change the type to a string... and VS keeps up!



clip_image004[6]



We know debugging in JavaScript can be hard... I know I have used alert() based debugging too many times! Well, VS2008 is here to help with full debugging support for client side javascript.



clip_image006[4]



Lots of cool stuff to show you here. Notice at the top right, full debugging controls, run, break, step over, step into, etc.

At the mid-left, notice the icon's for break point, and current executing line.


At the mid-right, notice the debugging views I get that show me exactly what the current value of all the locals and parameters are.


At the bottom right, notice my the results of my call to Sys.Debug.Trace() are beging displayed in the output window.
And finally at the bottom right, notice I have full control to use the immediate window to evaluate results in the current context.



Ok, cool, but now we want to actually go change the datamodel on the server... How do I do that?



Well, first define a WCF-Ajax service. This well expose JSON calls that is very ajax friendly. Add, New Item, Ajax-enabled WCF service.



clip_image008



Now, we need to implement a web services that will update our data model.




function onTitleChange(title, id) {
Sys.Debug.trace(title + id);
PhotoService.SetPhotoTitle(title, id, onComplete);

}
function onComplete(results) {
Sys.Debug.trace(results);
}



Then we just need to call it from client side javascript. To do that, we need to add a reference in ScriptManager.




<asp:ScriptManager runat="server" ID="sm">
<Services>
<asp:ServiceReference Path="~/PhotoService.svc" />
</Services>
</asp:ScriptManager>



 


Then, we can directly access the SetPhotoTitle method from JavaScript. Notice we even get auto-completion.



clip_image010



Because the is Ajax, we need to be asynchronous... which means we need to define a callback method to get the results.





function onTitleChange(title, id) {


    Sys.Debug.trace(title + id);


    PhotoService.SetPhotoTitle(title, id, onComplete);


 


}


function onComplete(results) {


    Sys.Debug.trace(results);


}




OK... let's run this in FireFox and use FireBug to check out the network traffic.



First thing to notice is that the Sys.Debug.Trace() calls are making their way to firefox's console window. Very helpful in debugging.



image



Next, we will expand that node and notice the request is in JSON format



image



As is the response..



image



Part V: The Ajax Control Toolkit





Now the fact that you can build this is great ajax components is great, but is it even better that we have a large number of pre-built component, ready for you to use. Check out this toolbox, all free and part of VS!



image



Check out the live demo of all these controls -- Oh, and check them out from Firefox or Safari.. they work the same everywhere!



http://www.asp.net/AJAX/AjaxControlToolkit/samples/



image





Part VI: ASP.NET Ajax Templates and JQuery



Everything I showed thus far as been shipped and very stable and ready to use... I thought I'd show you some up and coming work.



Check out the ASP.NET AJAX Templates work and the announcement about shipping the very popular Ajax library JQuery with Visual Studio.



First thing let's do is is establish some initial data... In many real world apps, you might use data from a web service call, etc.




var employees = [
{ FirstName: 'Omar', LastName: 'Khan', Email: 'omark@microsoft.com', Photo: 'omar.jpg', Title: 'Product Unit Manager' },
{ FirstName: 'Jeff', LastName: 'King', Email: 'jking@microsoft.com', Photo: 'jeff.jpg', Title: 'Program Manager' },
{ FirstName: 'Pete', LastName: 'LePage', Email: 'plepage@microsoft.com', Photo: 'pete.jpg', Title: 'Product Manager' },
{ FirstName: 'Bertrand', LastName: 'Le Roy', Email: 'bleroy@microsoft.com', Photo: 'bertrand.jpg', Title: 'Program Manager' },
{ FirstName: 'Scott', LastName: 'Guthrie', Email: 'scottgu@microsoft.com', Photo: 'scott.jpg', Title: 'Corporate VP' },
{ FirstName: 'Steve', LastName: 'Ballmer', Email: 'steveb@microsoft.com', Photo: null, Title: 'CEO' }
];



Add the first column, very simply just display the data... This template will repeat for each item in the list.





<div id="column1">
<ul id="simpletemplate" class="sys-template">
<li><b>{binding FirstName}</b><br />
(<span>{binding Title}</span>)</li>
</ul>
</div>



Now we just wire it up




Sys.Application.add_init(
function() {
var simple = $create(Sys.UI.DataView, {}, {}, {}, $get('simpletemplate'));
simple.set_data(employees);

}
);



image



Now, that is pretty simple, let's try something a bit more fancy.




<div id="fancytemplate" class="sys-template">
<div class="card">
<img sys:src="{{ 'jpg/' + Photo }}" class="icon" />
<b>{binding FirstName}</b> <b>{binding LastName}</b><br />
<span>{binding Title}</span><br /><br />
<a href="{{ 'mailto:' + Email }}">{{ Email }}</a><br />
</div>
</div>



image



Now, this is good, but I am missing a photo of Steve... Rather than showing a broken image, it would be nice to use a stock image of any pictures that are missing... Let's change up the template a bit. (Notice we are moving away from source code in comments format... stay tuned




<!--* if (Photo) { *-->
<img sys:src="{{ 'jpg/' + Photo }}" class="icon" />
<!--* } else { *-->
<img sys:src="jpg/anon.jpg" class="icon" />
<!--* }*-->



and the results..



image



Now, for real fun, let's make the data editable...




<table id="edittemplatecontainer">
<thead>
<tr><td>First Name</td><td>Last Name</td><td>Title</td></tr>
</thead>
<tbody id="edittemplate" class="sys-template">
<tr>
<td><input type="text" value="{binding FirstName}" class="short" /></td>
<td><input type="text" value="{binding LastName}" class="short" /></td>
<td><input type="text" value="{binding Title}" class="medium" /></td>
</tr>
</tbody>
</table>



and, of course, we wire this one up too.






var edit = $create(Sys.UI.DataView, {}, {}, {}, $get('edittemplate'));
edit.set_data(employees);



Now, check it out, because of the magic of databding, as I change the values in one view, they show up in all the other views..



image



In fact, to make the change more obvious, let's do a little color effect on change. And of course we will use JQuery for this.




<script src="js/jquery-1.2.6.debug.js" type="text/javascript"></script>



Then let's define a method to do the color change..




function flashTarget(value, binding) {
var target = binding.get_target();

$(target).parent()
.css('backgroundColor', 'orange')
.animate({ backgroundColor: 'red' }, 500)
.animate({ backgroundColor: 'yellow' }, 1000)
.animate({ backgroundColor: 'white' }, 500);
return value;
}



Notice I get JavaScript intelliense even on JQuery, even in the "chaining"..



image



Now we just write up this method to each of the bindings... for example:




<li><b>{binding FirstName, convert=flashTarget}</b><br />
(<span>{binding Title, convert=flashTarget}</span>)</li>



image





Wow -- What a talk! You can find all the demo code here.



Let me know what you think!

AjaxWorld Talk: Building Rich Internet Applications Using Microsoft Silverlight 2


It was another fun day AjaxWorld. I had a good time during my talk Silverlight 2.

Silverlight is a cross-browser, cross-platform, cross-device. Plug-in for building and delivering the next generation of .NET based media experiences and rich interactive applications for the Web.

Silverlight does not require Windows, .NET or IIS on the server.

image

Silverlight 2 just shipped a few days ago, and already we have some great customers going live.

NBC Olympics - NBC hosted the Olympics live on nbcolympics.com and served up 1.3 billion page views, 70 million video streams, and 600 million minutes of video content - making it the largest ever media event on the web. Users visiting the site spent an average of 27 minutes on the site when they watched a video - an unprecedented number for online traffic.

Notice the use of immediate seek to anywhere in the stream and adaptive streaming that gives you just the right bit-rate content for your connection.

image

Democratic National Convention - In August, the Democratic National Convention was streamed live using Silverlight, and broadcast a 2Mbit live video feed of the event and speeches - receiving outstanding feedback from audiences watching it.

This video was delivered live to millions of viewers all over the world at higher quality and bit rate than traditional TV. Now, all the content is available for viewing on demand.

image

Hard Rock - The folks at Hard Rock have the world's largest collection of Rock-and-roll memorial in the world. They hired the good folks at vertigo to build. Notice how the gigabytes of images are easy to zoom into and pan around. All streaming download of images...

image image

Health Care Demonstrator - This is an example app that shows how to build a great line of business application with Silverlight.

image

Quake Game - Check out this very cool Quake game in Silverlight. Look at the frame rate... even in full screen!

image

Next I showed the latest progress on Moonlight with a Linux openSUSE 11.0 VPC (thanks Miguel!)

image

image

image

Next, I built a very simple Silverlight 2 application in Eclipse using the Eclipse Tools for Silverlight.

First we create a new Silverlight project in Eclipse.

image

Now, we just drag the button from the toolbox in Eclipse

image

Notice we get autocompletion in the source view in Eclipse

image

Then we can easily handle the click event in Eclipse

image

Then in code view, we get auto completion and error reporting in C# in Eclipse.

image

Next I built a simple Silverlight 2 application from scratch in the free VS2008...

For this demo, I only used freely available tools... In particular everything I show works in Visual Studio 2008 Web Developer Express and the Silverlight Tools for Visual Studio 2008.

Download the complete sample.

File, New Project

image

Next you can select what server side project to associated your Silverlight app with. Notice you can even have one dyamically generated for you. Also, notice you don't need .NET on the server, in fact you can deploy Silverlight from a Linux server.. all you need is http.

image

image

Notice the client and web project in the same solution and the Xaml view and the preview view.

image

Notice the great Xaml intellisense.

image

Now we get to write client side C# code... we can even do breakpoints, etc.

private void btn1_Click(object sender, RoutedEventArgs e)
{
btn1.Content = "Oach!";
}



Now, check out the server project, it includes ClientBin with a Silverlight.xap file that includes our clientside code... The cool thing is this is just a zip file... so you can see inside it easily.



image





Run it and check it out! works perfectly.



image





But this is Silverlight, let's see if we can make it a little more sexy. Let's open it up in Express Blend.



image



Notice Blend is built for Designers...



image



Let's make the design surface a little bigger then do some gradients



image



and finally a motion path..



image



The great thing is the project just refreshes in VS



image



Now we need to get some real data into this app.



First we add a datagrid (we put it and the button in a StackPanel)




<StackPanel>
<Button x:Name="btn1" Width="100" Height="50" Content="Push Me!" Click="btn1_Click" Margin="49,73,0,0" d:LayoutOverrides="Width, Height" VerticalAlignment="Top" HorizontalAlignment="Left" RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-49.157"/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
</Button>

<data:DataGrid Name="datagrid1"></data:DataGrid>
<StackPanel>



Then we go to the server project and add some data.. In this case an Entity Framework data model. This let's us use LINQ to get access to the data rather than doing queries in code rather than in T-SQL.



image



Select the employees tables we need then, you get this view in the designer. Notice the Photo filed is too big to pass to the client, so we can just remove it here.



image



Now let's add a web service to pass this to data to the client. Let's add a Silverlight-enabled WCF service.



image




[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class NorthwindService
{
[OperationContract]
public IEnumerable<Employee> GetEmployees(string nameContains)
{
var db = new NORTHWNDEntities();
var q = from emp in db.EmployeeSet
where emp.FirstName.Contains(nameContains)
orderby emp.LastName ascending
select emp;
return q.ToList();
}

}



image




private void btn1_Click(object sender, RoutedEventArgs e)
{
var client = new ServiceReference1.NorthwindServiceClient();
client.GetEmployeesCompleted +=
new EventHandler<GetEmployeesCompletedEventArgs>(client_GetEmployeesCompleted);
client.GetEmployeesAsync("b");

btn1.Content = "Oach!";
Storyboard1.Begin();

}

void client_GetEmployeesCompleted(object sender, GetEmployeesCompletedEventArgs e)
{
datagrid1.ItemsSource = e.Result;
}



Notice the column reordering, editable cells, sorting, etc.



image





Hope you enjoyed it! Here is the completed sample.

Framework Design Guidelines slides from PDC2008 Talk


Yesterday, Krys and I did a talk on Framework Design Guidelines and how they changed from when we started in 1998 to now in 2008.

They should have the video of the talk up soon, I will post a link when it comes up... in the meantime, check out the slides on SlideShare... Or just grab the slides directly.

image

Enjoy!

BTW -- if you made it to PDC2008 , please take a minute to fill out the eval for sessions that you attended, we'd love to have your feedback!

Session Evaluation
You can access evaluations easily by locating the () icon next to each specific session in the PDC Timeline.

thanks!

.NET Framework 4 Poster


We created a very cool poster that shows off the new stuff in .NET Framework 3.5 SP1 and .NET Framework 4. Thanks to Kit George for running this effort to get a very cool view of .NET Framework 4 and for the great folks at Addison Wesley for helping with the creative end and the printing costs!

PDC2008-NETFX4

And of course, here is the DeepZoom version! (use your mouse wheel or click and control-click to zoom in and out)

Download the .NET Framework 4 Poster PDF for high quality printing.

Enjoy! We'd love to hear what you think!

If you are at PDC08 please drop by the Addison Wesley booth in the Big Room and get your copy... You can just tell them I sent you ;-)

Oh, and if you are a Microsoft employee in Redmond, drop KitG an email, he has a few he can give out.