Scott Hanselman

Video Trip Report: If this is Tuesday, this must be Cairo

March 6, '10 Comments [11] Posted in ASP.NET | ASP.NET Ajax | ASP.NET MVC | Channel9 | Screencasts | Speaking | TechEd | Windows Client
Sponsored By

image

This last week over a 7 day period, I went to Munich, Cairo and Dubai. I presented in three keynotes and did a total of 10 sessions. I crossed 12 time zones and missed my kids. I talked to/with/at about 3000 people.

I'm utterly shattered.

I took some video while I was travelling with my Creative Vado HD and slapped it into Windows Live Movie Maker just now. Here's my trip montage.

You could call this either "The Glamourous Life of a Technical Speaker" or "If this is Tuesday, this must be Cairo" or "Scott needs to learn to say No."

It was great fun, I spoke at VSOne in Munich. I talked about .NET 4 and ASP.NET MVC. We also had a nice Nerd Dinnner. Then I headed over to Cairo Code Camp and the turnout was HUGE. Something like 700-800 folks showed up at the German University in Cairo. I also recorded a great podcast on Women in Technology in the Muslim World. Then I headed to Dubai for TechEd Middle East where I presented in three sessions and did the keynote demo for Soma. It's always a challenge for me to travel because of my diabetes, particularly because of the time zones but also sitting for 16 hours at a time in a plane and eating plane food is a problematic. However, I must say that everyone on this trip was incredibly kind and accommodating.

If you have the chance to go to Munich, Cairo, and/or Dubai, I highly recommend it. The people, the places and the technologists are all top-notch.

Enjoy.

P.S. Thanks to http://blog.bloggingitloud.com/ for the guerilla footage of the TechEdME Keynote.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

Demo Dashboard and IDE Extensions - Whirlwind Tour around .NET 4 (and Visual Studio 2010) Beta 1

May 21, '09 Comments [8] Posted in Open Source | Source Code | TechEd | Tools
Sponsored By

It's getting considerably easier to create and distribute Visual Studio Extensions.  With Visual Studio 2008, you can find extensions at the Visual Studio Gallery. There's also a very good VSX (Visual Studio Extensibility) Developer Center on MSDN that has a ridiculous amount of information on how to extend VS, and there are LOTS of great VS 2008 add-ins. The documentation is really well fleshed-out. It also includes info on the little-known, but totally awesome "VS Shell," but that's another post.

Visual Studio 2010 Beta 1 shows some new and interesting was to extend VS. One nice way to say it is "moving beyond add-ins." One example is that the Editor in VS2010 uses MEF (Managed Extensibility Framework) at its heart. It also uses Immutable Text Snapshots that make accessing the buffer from other threads easier. I talked to Noah Richards, one of the devs on the editor, in a recent episode of my podcast.

Terry Clancy points out how much easier it is. Seriously, the post is of epic length, check it out.

For the Visual Studio 2010 Shell, we’ve made targeted investments to the developer experience:

· No more complicated load keys! - Developers are no longer required to procure a Package Load Key (PLK) or a Shell Load Key (SLK) to develop Visual Studio 2010 Shell applications!

· No requirement for Registry. Packages can now be installed without requiring developers to update configuration settings in the Windows registry.  In many cases, this means that packages can now be x-copy deployed.

· Easier, more robust deployment – The redistributable shell installers have been updated to support Windows Installer source caching features, thus is during a repair, user’s won’t be required to point MSI to the original installation file or media.

· Improved SDK tooling – New templates have been added to make it easier to get started with the Visual Studio Shell, and create common types of extensions.  For Visual Studio Shell (Isolated Mode) developers, we’ve significantly improved performance of our F5 Debugging experience.

So what does a VS2010 extension look like?

Installing a VS2010 Extension with the Online Gallery and Extension Manager

Doing my talk on .NET 4 at TechEd this year, I got to use a new extension from the folks at Clarius Consulting called the Demo Dashboard. The idea is that while you're giving a talk at a conference like TechEd, the audience is using Twitter and a hash-tag that you set (I used #scottha) to give you real time feedback on your presentation. They can tell you if you're doing a good job, if your fonts are the right size, your speed, and they'll also give you a headcount of twitter users in your talk.

The code for the Demo Dashboard is up at Codeplex under Ms-PL while the extension itself is at the VS Gallery. It's actually a VS extension WITH extensions of it's own!

demo_dashboard

The plugin integrates with the Editor and hangs around (it can be collapsed) while you're giving your talk. For my talk, I used a debug build and just dropped it into the C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Components folder.

However, you can just go to the Extensions Manager and download it directly into Visual Studio:

Extension Manager (2)

If you download it manually from a website like the Visuals Studio Gallery, you'll notice the VSIX extension is associated with Visual Studio:

File Download (2)

You'll be warned that 'VSLauncher' is trying to run something, and if you accept it, the VSIXInstaller will do its thing. It's easier to just do it from inside the Extension Manager in Visual Studio.

The Demo Dashboard is entirely written in managed code and is actually a WPF app. Notice in this screenshot of the main XAML file that the plugin is actually running inside the WPF editor at the bottom of the split-screen view.

VsSpeakerCompanion - Microsoft Visual Studio (Administrator) (2)

They Demo Dashboard folks created a whole sub-plugin model you can use to extend this dashboard for your own conference. Using MEF (now built into .NET 4), they're pulling in a Twitter Service, and having Widget DLLs provide one or more widgets.

namespace CoolnessWidget
{
[Export(typeof(IWidgetProvider))]
[Widget(Name = "Cool Widget", After = "Font Size Widget")]
internal class CoolWidgetProvider : IWidgetProvider
{
IEnumerable<IWidget> IWidgetProvider.GetWidgets(Context context)
{
// creates an instance of our widget providing it the core context and twitter service to work with
CoolWidget widget = new CoolWidget(context, this.TwitterService);
return new List<IWidget> { widget };
}

[Import]
private TwitterService TwitterService { get; set; }
}
}

There's a lot of great examples in the code on clever ways to use MEF to make consumption of services easier by plugins. The WidgetManager class brings together a bunch or "hard to deal with" classes, then Exports them via MEF to make consumption easier by other classes and plugins downstream.

I think, however that it could be even MEFier. Remember, it's Ms-PL, and a CodePlex project, and there's a lot of TODO:'s marked in the comments, do we're free to change and improve the code. Go check it out.

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

C# 4 and the dynamic keyword - Whirlwind Tour around .NET 4 (and Visual Studio 2010) Beta 1

May 20, '09 Comments [15] Posted in DLR | Learning .NET | TechEd
Sponsored By

I've posted twice so far on .NET 4, first on ASP.NET 4, then on improvements in C# around dynamism and PIAs as well as the COM Binder. Now "dynamic."

So I asked this guy, what's up with the dynamic keyword, and what type was it exactly? I mean, C# isn't dynamic, right? He says:

"Oh, well it's statically-typed as a dynamic type."

Then my brain exploded and began to leak out my ears. Honestly, though, it took a second. Here's a good example from some of Ander's slides:

Calculator calc = GetCalculator();
int sum = calc.Add(10, 20);

That's the creation of an object, invokation of a method, and the collection of a return value. This is the exact same code, as the "var" type is figured out at compile time.

var calc = GetCalculator();
int sum = calc.Add(10, 20);

If you wanted to do the exact same thing, except with Reflection (like if it were some other class, maybe old-COM interop, or something where the compiler didn't know a priori that Add() was available, etc) you'd do this:

object calc = GetCalculator();
Type calcType = calc.GetType();
object res = calcType.InvokeMember("Add",
BindingFlags.InvokeMethod, null,
new object[] { 10, 20 });
int sum = Convert.ToInt32(res);

It's pretty horrible to look at, of course. If the object is some dynamic thing (from any number of sources), we can do this:

dynamic calc = GetCalculator();
int sum = calc.Add(10, 20);

And get the dynamic method invocation and conversion of the return type. Basically it looks just like we're calling any other object.

Dynamism?

Here's the differences you see while coding. Hovering over the keyword gives me this nice tooltip.

image

When I hit the "." expecting intellisense to save me from my ignorance:

image 

I'm told this is a dynamic expression that will be resolved at runtime.

Here's a C# program calling a method in a python (.py) file:

ScriptRuntime py = Python.CreateRuntime();
dynamic random = py.UseFile("random.py");

//Make an array of numbers
var items = Enumerable.Range(1, 7).ToArray();

random.shuffle(items);

Here we're passing in an array if ints (System.Int32[]) into the Python 'shuffle' method and it works just fine.

image

The DLR basically enables everyone to talk to everyone. That includes not just Python and Ruby, but Silverlight, Office/COM, and others.

What price REPL?

John Lam has a great post about his TechEd talk where he took a spin on a traditional REPL (READ-EVAL-PRINT-LOOP) using the DLR. He even allows switching back and forth between languages, which is odd/interesting.

John's even put the code for his REPL up on GitHub. Why is this interesting? Well...

Screenshot of John Lam's REPL/editor

He took his REPL and embedded it into an example Open Source app, specifically Witty, a WPF Twitter Client. Why he didn't use BabySmash is beyond me. ;) Check it out, as well as the source code diff for Witty on John's blog.

It'll be nice to have this kind of dynamic stuff just baked in and waiting for me to use it.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

CLR and DLR and BCL, oh my! - Whirlwind Tour around .NET 4 (and Visual Studio 2010) Beta 1

May 20, '09 Comments [18] Posted in BCL | Learning .NET | TechEd
Sponsored By

Just got a great tweet from Jeremiah Morrill about .NET 4.

"Office and COM Interop that is actually fun to do" Show me! Until then, I'm calling shenanigans.

I love a challenge! In my first Whirlwind Tour post on ASP I mentioned how COM Interop and Office Interop was fun with 4.

I've done a lot of COM Interop with C# and a LOT of Office Automation. Once upon a time, I worked at a company called Chrome Data, and we created a Fax Server with a Digiboard. Folks would call into a number, and the person who took the order would pick the make/model/style/year of the car and "instantly" fax a complete report about the vehicle. It used VB3, SQL Server 4.21 and Word 6.0 and a magical thing called "OLE Automation."

Fast forward 15 years and I sent an email to Mads Torgerson, a PM on C# that said:

I’m doing a sample for a friend where I’m simply spinning through an Automation API over a Word Doc to get and change some CustomDocumentProperties.

I’m really surprised at how current C# sucks at this. Of course, it makes sense, given all the IDispatch code in Word, but still. Dim != var as they say. Fix it!

Well, everything except "fix it!" is true. I added that just now. ;) I did a post on this a while back showing how scary the C# code was. This is/was somewhere where Visual Basic truly excels. I vowed to only use VB for Office Automation code after this fiasco.

If you want to melt your brain, check out the old code. No joke. I've collapsed the block because it's too scary. See the "ref missings"? The reflection? The Get/Sets? Scandalous!

{
ApplicationClass WordApp = new ApplicationClass();
WordApp.Visible = true;
object missing = System.Reflection.Missing.Value;
object readOnly = false;
object isVisible = true;
object fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\NewTest.doc");
Microsoft.Office.Interop.Word.Document aDoc = WordApp.Documents.Open(
ref fileName,ref missing,ref readOnly,ref missing,
ref missing,ref missing,ref missing,ref missing,
ref missing,ref missing,ref missing,ref isVisible,
ref missing,ref missing,ref missing,ref missing);

aDoc.Activate();

string propertyValue = GetCustomPropertyValue(aDoc, "CustomProperty1");
SetCustomPropertyValue(aDoc, "CustomProperty1", "Hanselman");

foreach (Range r in aDoc.StoryRanges)
{
r.Fields.Update();
}
}

public string GetCustomPropertyValue(Document doc, string propertyName)
{
object oDocCustomProps = doc.CustomDocumentProperties;
Type typeDocCustomProps = oDocCustomProps.GetType();
object oCustomProp = typeDocCustomProps.InvokeMember("Item",
BindingFlags.Default |
BindingFlags.GetProperty,
null, oDocCustomProps,
new object[] { propertyName });

Type typePropertyValue = oCustomProp.GetType();
string propertyValue = typePropertyValue.InvokeMember("Value",
BindingFlags.Default |
BindingFlags.GetProperty,
null, oCustomProp,
new object[] { }).ToString();

return propertyValue;
}

public void SetCustomPropertyValue(Document doc, string propertyName, string propertyValue)
{
object oDocCustomProps = doc.CustomDocumentProperties;
Type typeDocCustomProps = oDocCustomProps.GetType();
typeDocCustomProps.InvokeMember("Item",
BindingFlags.Default |
BindingFlags.SetProperty,
null, oDocCustomProps,
new object[] { propertyName, propertyValue });
}

Fast forward to C# under .NET 4.

var WordApp = new ApplicationClass();
WordApp.Visible = true;
string fileName = @"NewTest.doc";
Document aDoc = WordApp.Documents.Open(fileName, ReadOnly: true, Visible: true);
aDoc.Activate();

string propertyValue = aDoc.CustomDocumentProperties["FISHORTNAME"].Value;
aDoc.CustomDocumentProperties["FISHORTNAME"].Value = "HanselBank";
string newPropertyValue = aDoc.CustomDocumentProperties["FISHORTNAME"].Value

foreach (Range r in aDoc.StoryRanges)
{
foreach (Field b in r.Fields)
{
b.Update();
}
}

See how all the crap that was originally reflection gets dispatched dynamically? But that's not even that great an example.

Word and Excel Automation with C# 4

That's just an example from Jonathan Carter and Jason Olson that gets running processes (using LINQ, woot) then makes a chart in Excel, then puts the chart in Word.

using System;
using System.Diagnostics;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;

namespace One.SimplifyingYourCodeWithCSharp
{
class Program
{
static void Main(string[] args)
{
GenerateChart(copyToWord: true);
}

static void GenerateChart(bool copyToWord = false)
{
var excel = new Excel.Application();
excel.Visible = true;
excel.Workbooks.Add();

excel.get_Range("A1").Value2 = "Process Name";
excel.get_Range("B1").Value2 = "Memory Usage";

var processes = Process.GetProcesses()
.OrderByDescending(p => p.WorkingSet64)
.Take(10);
int i = 2;
foreach (var p in processes)
{
excel.get_Range("A" + i).Value2 = p.ProcessName;
excel.get_Range("B" + i).Value2 = p.WorkingSet64;
i++;
}

Excel.Range range = excel.get_Range("A1");
Excel.Chart chart = (Excel.Chart)excel.ActiveWorkbook.Charts.Add(
After: excel.ActiveSheet);

chart.ChartWizard(Source: range.CurrentRegion,
Title: "Memory Usage in " + Environment.MachineName);

chart.ChartStyle = 45;
chart.CopyPicture(Excel.XlPictureAppearance.xlScreen,
Excel.XlCopyPictureFormat.xlBitmap,
Excel.XlPictureAppearance.xlScreen);

if (copyToWord)
{
var word = new Word.Application();
word.Visible = true;
word.Documents.Add();

word.Selection.Paste();
}
}
}
}

Notice the named parameters in C#, like 'Title: "whatever"' and "copyToWord: true"?

PIAs no long stand for Pain in the *ss - Type Equivalence and Embedded Interop Assemblies

Primary Interop Assemblies are .NET assemblies that bridge the gap between a .NET app and a COM server. They are also a PIA, ahem. When there's articles about your technology on the web called "Common Pitfalls With ______" you know there's trouble.

Typically you reference these Interop assemblies in Visual Studio and they show up, predictably, as references in your assembly. Here's a screenshot with the project on the right, and the assembly under Reflector on the left.

image

This means that those PIAs better be deployed on the end user's machine. Some PIAs can be as large as 20 megs or more! That's because for each COM interface, struct, enum, etc, there is a managed equivalent for marshalling data. That sucks, especially if I just want to make a chart and I'm not using any other types. It's great that Office has thousands of types, but don't make me carry them all around.

However, now I can click on Properties for these references and click Embed Interop Types = true. Now, check the screenshot. The references are gone and new types have appeared.

 image

Just the types I was using are now embedded within my application. However, since the types are equivalent, the runtime handles this fact and we don't have to do anything.

This all adds up to Office and COM Interop that is actually fun to do. Ok, maybe not fun, but better than a really bad paper cut. Huh, Jeremiah? ;)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

ASP 4 - Whirlwind Tour around .NET 4 (and Visual Studio 2010) Beta 1

May 19, '09 Comments [14] Posted in ASP.NET | ASP.NET Dynamic Data | ASP.NET MVC | TechEd
Sponsored By

Hey, we released Visual Studio 2010 Beta 1. JasonZ has a great post with piles of details and a metric crapload of screenshots. Definitely take a moment (or eight) and check out his very detailed post. You can get it NOW if you're an MSDN Subscriber, or after the general announcement on Weds if you're not.

UPDATE: My bad, of course it's called ASP.NET 4 and not ASP 4. Sorry, typo.

Should You Freak Out?

I don't think so. There's a lot of stuff that's new and added in .NET 4, but not in that "overwhelming-I-need-to-relearn-everything" way. More in that, "oh, this is way easier/simpler now" way. Like, moving data around with ADO.NET DataServices is easy, binding with client templates is easy, there's F# if you need it, the "dynamic" keyword if you need it, Silverlight's already installed, oh, and the parallel stuff will freak you out, but in a good way.

I'll do a series of posts on what I think is cool with lots of details. I'll put code samples up also as I can. I will also point out where you can already do much of this with 3.5 SP1, as well.

Here's a general outline of a small part of the goodness:

  • New Shell, new File|New, new Extensions Manager
  • Lots of focus on "Code First" (TDD-friendly, etc)
  • Office and COM Interop that is actually fun to do.
  • Automatic Properties for VB, no more "_" for multi-line, inline subs, collection initializers
  • C# gets the dynamic keyword
  • F# is included out of the box
  • WPF Databinding in the Designer
  • Silverlight included out of the box
  • Piles of HTML Snippets for non-designer people
  • Better JavaScript Intellisense
  • MSBuild for C++
  • UML for VS Team Architecture
  • TFS Branch and Changeset visualizers
  • Parallel computing
  • Workflow speedup, new designer
  • SharePoint tooling

Rather than try to top Jason with a laundry list of what's new and what not, here's some details on a few things that I find particularly interesting. They may be obscure to you, and perhaps not deeply interesting, but they were interesting enough to me that I used them for demos at TechEd last week (with a hat tip to Jonathan Carter and Jason Olson).

This is just a smattering of the features (hence: "Whirlwind" although "totally random cool stuff" would have also worked) coming in .NET 4. These are features I'm interested in because they've solved problems I've had in the past.

I'm realizing I'll definitely do these as separate posts because they're going to get long. First, ASP.NET and Ajax.

ASP.NET 4

There is an excellent whitepaper at http://www.asp.net/learn/whitepapers/aspnet40/ with a lot of detail on the changes in ASP.NET 4.

There's lots new in ASP.NET 4, but at TechEd09 I showed two. First was control over my controls' client ids. Rather than getting a generated ID like ctl09_list45_whatever99, I can make my control ids more predictable.

More Control over ClientIDs in WebForms

For example, here's a ListView (ol/li) of Television shows. It uses jQuery to be sortable. Notice the new attributes in asp:ListView, specifically ClientIDRowSuffix and ClientIDMode.

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Television Series Picker</title>
<link href="Default.css" rel="stylesheet" type="text/css" />
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="ui.core.js" type="text/javascript"></script>
<script src="ui.sortable.js" type="text/javascript"></script>
<script type="text/javascript">

$(document).ready(function() {
$("#televisionList li").append("<div><span>Click</span></div>");
$("#televisionList").sortable({ handle: $("#televisionList li div") });
});
</script>
</head>
<body>
<form runat="server">
<h1>Television Series Picker</h1>
<p>Order the following television series' based on which you think is most awesome:</p>
<asp:ListView
DataSourceID="televisionDataSource"
ClientIDRowSuffix="ID"
ClientIDMode="Predictable"
runat="server">
<LayoutTemplate>
<ol id="televisionList">
<asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
</ol>
</LayoutTemplate>
<ItemTemplate>
<li id="televisionItem" runat="server">
<%# Eval("Name") %>
</li>
</ItemTemplate>
</asp:ListView>
<asp:ObjectDataSource
ID="televisionDataSource"
TypeName="_01_ClientId.TelevisionDataProvider"
SelectMethod="GetTelevisionSeries"
runat="server" />
</form>
</body>
</html>

The list is populated using an ObjectDataSource and I want the client id's to be created with a suffix using the ID property from the Television object.

Routing and WebForms

You probably know that System.Web.Routing is a big part of ASP.NET MVC, and you may know it's in .NET 3.5 SP1 as well. In .NET 4 it'll be even more easy to use with better support for WebForms. For example:

public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add("Product",
new Route("Products/{category}",
new PageRouteHandler("~/Products.aspx")));
}
}

Here I'm setting update a route such that /Products/SomeCategory routes to the /Products.aspx WebForms Page. The Category parameter is a RouteParameter and can be retrieved (of course) and used. System.Web.UI.Page has a RouteData parameter now, or you can refer to RouteValues in your ASPX markup. For example:

<p>The following are all the products within this category:</p>
<h2><asp:Literal Text="<%$ RouteValue:Category %>" runat="server" /></h2>

or into a Data Source via <RouteParameter>:

<asp:EntityDataSource
ID="productsDataSource"
ContextTypeName="AdventureWorksLTEntities"
EntitySetName="Products"
OrderBy="it.Name"
Where="it.Category.Name = @Category"
runat="server">
<WhereParameters>
<asp:RouteParameter
Name="Category"
RouteKey="Category"
Type="String" />
</WhereParameters>
</asp:EntityDataSource>

There will also be Routing Extension Methods like GetUrlForRoute or the like, in Beta 2, as well as IgnoreRoute. Basically anything that makes it simple, simple, simple to use Routes with WebForms. This'll be nice for hybrid WebForms/MVC apps as well.

Ajax 4

The Client Templates stuff in Ajax 4 is pretty sweet. This allows for 2-way data-binding using only JavaScript. For example, this template pulls from a JSON DataService at customers.svc. The JavaScript is below. We create a DataContext pointing to that endpoint, two DataViews that take the "customers-template" and "customer-template" HTML elements and creates a binding between them.

Sys.Application.add_init(function()
{
var dataContext = $create(Sys.Data.AdoNetDataContext,
{
serviceUri: "Customers.svc"
});

var customersTemplate = $create(Sys.UI.DataView,
{
dataProvider: dataContext,
fetchOperation: "Customers",
fetchParameters: { $top: 20, $orderby: "FirstName", $expand: "Orders" },
initialSelectedIndex: 0,
selectedItemClass: "selected"
},
null, null,
$get("customers-template"));

var customerTemplate = $create(Sys.UI.DataView,
null, null, null,
$get("customer-template"));

// This imperatively creates the binding
// between the customer grid and the customer
// detail form. When you select a record in
// the grid, it will automatically re-bind
// the detail view as well.
$create(Sys.Binding,
{
defaultValue: null,
source: customersTemplate,
path: "selectedData",
target: customerTemplate,
targetProperty: "data"
});

// This uses jQuery live event bindings to hook up
// the click event for the update button that will be
// "generated" when the customer detail form is bound.
$("#update-button").live("click", function()
{
dataContext.saveChanges();
});
});

Then we use jQuery live events, and then save the changes back to the dataContext. The changes that are made on the client side are tracked automatically, and those changes are sent back via JSON and commited. Note the source: and target: in the $create() call above that sets the master/detail relationship between customers and customer (singular.)

The client-side templates are similar to the server-side templates you probably already know how to use. You can even use expressions like to conditionally apply CSS.

image

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AdventureWorks AJAX</title>
<link href="Content/Styles/reset-min.css" rel="stylesheet" type="text/css" />
<link href="Content/Styles/Default.css" rel="stylesheet" type="text/css" />

<script src="Content/Scripts/MicrosoftAjax.debug.js" type="text/javascript"></script>
<script src="Content/Scripts/MicrosoftAjaxTemplates.debug.js" type="text/javascript"></script>
<script src="Content/Scripts/MicrosoftAjaxAdoNet.debug.js" type="text/javascript"></script>
<script src="Content/Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>

<script src="Content/Scripts/Default.js" type="text/javascript"></script>
</head>
<body
xmlns:sys="javascript:Sys"
xmlns:class="http://schemas.microsoft.com/aspnet/class">
<h1>Customer Directory</h1>
<table cellspacing="0">
<thead>
<tr>
<th>Title</th>
<th>First Name</th>
<th>Middle Name</th>
<th>Last Name</th>
<th>Suffix</th>
</tr>
</thead>
<tbody id="customers-template" class="sys-template">
<tr sys:command="select" class:odd="{{ $index % 2 != 0 }}">
<td>{binding Title, defaultValue=}</td>
<td>{binding FirstName}</td>
<td>{binding MiddleName, defaultValue=}</td>
<td>{binding LastName}</td>
<td>{binding Suffix, defaultValue=}</td>
</tr>
</tbody>
</table>
<fieldset id="customer-template" class="sys-template">
<legend>{{ FirstName + " " + LastName }}</legend>
<label for="first-name">
<span>First Name:</span>
<input type="text" id="first-name" value="{binding FirstName}" />
</label>
<label for="middle-name">
<span>Middle Name:</span>
<input type="text" id="middle-name" value="{binding MiddleName, defaultValue=}" />
</label>
<label for="last-name">
<span>Last Name:</span>
<input type="text" id="last-name" value="{binding LastName}" />
</label>
<input id="update-button" type="button" value="Update" />
</fieldset>
</body>
</html>

This exact scenario can also be done declaratively with you having to write ANY JavaScript at all. The "declarations" from the JavaScript file above are replaced with declarative namespace statements like:

<fieldset
class="sys-template"
sys:attach="dataview"
dataview:data="{binding selectedData, source={{customersTemplate}}}"
dataview:sys-key="customerTemplate">
<legend>{{ FirstName + " " + LastName }}</legend>
...

And the result is the same as above:

image

It's important to point out that while you can go get the VS 2010 Beta 1, you can also play with this stuff TODAY running on .NET 3.5 SP1. Go over to the ASP.NET 4 Ajax Preview site on CodePlex.

Also, don't freak out that ASP.NET MVC isn't baked into VS2010 Beta 1. Phil explains here.

Related Links

Have fun!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Page 1 of 26 in the TechEd category Next Page

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.