Tag Archives: .NET Framework 4.0

Improving the performance of multiple Inserts, Updates, and Deletes via the CRM 2011 Organization Service

UPDATE: Now that Polaris/UR12 are out, the new bulk API is available.  Check out Sonoma Partners blog post on a simple benchmark of the improvements.  Now you can Combine the ne bulk API with client side parallelism to achieve even better performance.  I’ll put that on my ever growing “to blog” list.  However, if you followed this post, then you should be able to figure it out yourself. 

UPDATE: Removed explicitly creating a ConnectionStringSettings object by calling CrmConnection.Parse().

If you are writing any .NET code that interacts with the Organization Service, any insert/update/delete performed happens one at a time, even if you call OrganizationServiceContext.SaveChanges().  This is a perfect candidate to improve performance using the Task Parallel Library.  Here’s a little code snippet to get you started:

var conn = CrmConnection.Parse("Url=https://YOURORG.crm.dynamics.com;Username=YOURUSERNAME;Password=YOURPASSWORD");
var ctx = new MyDataContext(new OrganizationService(conn));
var query = from a in ctx.AccountSet
            select new Account
                Id = a.Id,
                Name = a.Name,
                Address1_City = a.Address1_City
var tasks = new List<System.Threading.Tasks.Task>();
var accounts = query.ToList();
foreach (var account in accounts)
    // Parallelize each update until BulkAPI is released in UR12
    var task = System.Threading.Tasks.Task.Factory.StartNew(()=>{        
        account.Name += " - UPDATED";                
        account.Address1_City += " - UPDATED";    
        var newctx = new MyDataContext(new OrganizationService(conn));        
//Wait for all the updates executing in parallel to complete.

On my quad core laptop.  The serial version of this code takes a little over 5 seconds.   In comparison, the code above executes in less than a second.


Eliminating manual device registration

If you are connecting to CRM Online with a Live ID, you need to register a Device ID and Device Password when using the organization service from an outside caller.  I walk through this in my Connecting to CRM Online from an outside caller post.  Thanks to some internal discussions with folks on the SDK team, I discovered a simpler way that doesn’t require manually registering and putting the DeviceId /DevicePassword in the config file.  First you’ll have to download and use the Helper Code: DeviceIdManager Class from the SDK.  In addition to the references from the previous post, you’ll need to add references to System.Security.dll and System.ServiceModel.dll to get it to build.  Once you have done that, you can eliminate the DeviceId and DevicePassword settings from the connection string:


    <add name="CrmOnline" connectionString="Url=[YOUR_CRM_ORG_URL]; Username=[YOUR_LIVE_ID]; Password=[YOUR_PASSWORD];"/>


You can now connect to CRM Online like so:

var connection = new CrmConnection("CrmOnline");

connection.DeviceCredentials = DeviceIdManager.LoadOrRegisterDevice();

var context = new XrmServiceContext(connection);

DeviceIdManager.LoadOrRegisterDevice() automates the manual steps from the Connecting to CRM Online from an outside caller post.  I’m pretty sure it requires full trust, but haven’t taken the time to confirm.  If you have, leave me a comment to confirm/correct.


Geocoding and displaying a map for an address in CRM 2011

There are a few blog posts out there that cover this topic, but the ones I’ve found don’t take you through it step by step.  I will, however, make assumptions like you know how to create an entity, add web resources to a form, etc.  Here goes…

The overall solution is going to consist of:

If you are a “yea yea, blog blah blah, just give me the code” type then jump to the bottom of the postSmile.

Let’s get started.  First, you will need the Developer Toolkit for Microsoft Dynamics CRM 2011 and Microsoft Dynamics CRM Online and NuGet installed.  Let’s create an entity called GeocodeMapSample. As a habit, I tend to uncheck all the entity defaults after the Options for Entity section of the form.  You can always go back and turn additional features on as you need them after you create the entity.


Next create the following fields (all of type single line of text):

  • AddressLine1
  • AddressLine2
  • City
  • State
  • Zip
  • Latitude
  • Longitude

Yours should look like mine except you will have a different prefix than dkdt_.


Finally, put everything on the form:


Once you’ve done all this, go ahead and Publish your changes.  Next, create a new Dynamics CRM 2011 Package project called GeocodeMapSamplePackage:


Fill out the Connect to Dynamics CRM Server dialog:


If you are using CRM Online, then your discovery service is dev.crm.dynamics.com if you log in with a Live ID or disco.crm.dynamics.com if your org was provisioned through Office 365.  Make sure you select HTTPS as the protocol if necessary.  Add a Dynamics CRM 2011 Plug-in Library called GeocodMapSamplePlugins to the Visual Studio solution:


Find the GeocodeMapSample entity in the Entities node of CRM Explorer, right-click it and select Create Plug-in:


Make your dialog look like mine:


I am picking the Pre-Operation for the Pipeline Stage because I want to be able to throw an exception back to the caller and roll the transaction back if geocoding fails because my business requirement is that addresses must be valid.  Create another plug-in for the same entity.  This time, we want to do a few things differently.  First, set the value of Message to Update, but DO NOT click OK yet:


We only want this plug-in to fire when address related fields change.  Click the Filtering Attributes ellipsis (…) to bring up the following dialog:


Make sure you have deselected all of the fields, then ONLY selected items in the image.  In an update scenario, we want to make sure the plugin has the previous values from when the form was loaded.  Click the Parameters ellipsis (…) next to Pre Image Alias to bring up a similar dialog to before and select the same set of attributes.  We’re going to ask the Bing Maps REST service for JavaScript Object Notation (JSON) since it’s the fastest across the wire.  Add the DynamicJson package from NuGet to the plug-in project:



Now it’s time to generate some early-bound types.  The CRM SDK covers early-bound vs. late-bound here.  Most developers prefer the early bound approach unless they truly need a late-bound for writing very generic, reusable code.  This is because you become more productive and less error prone due to intellisense and compile time checking.  While the developer toolkit does have the ability to generate strongly typed classes:


…it does not give you any control over what classes get generated.  It just brute force creates one for each entity you have read permissions to.  Therefore, you end up generating a bunch of unnecessary code that bloats your codebase and makes your plugin WAY BIGGER than it needs to be.  Instead, I prefer to use this approach to generate the classes:


Which one you choose, is up to you.  Generate Wrapper is OK for now since you are just learning, but take my advice and learn the approach above for production codeSmile.  Add a new class to the plug-in project called GeocodeMapSampleCommon.cs.  Replace the entire contents of the class declaration with the following code:

using System;

using System.Net;

using System.Text;

using Codeplex.Data;

using GeocodeMapSamplePackage.GeocodeMapSamplePlugins.Entities;

using Microsoft.Xrm.Sdk;


namespace GeocodeMapSamplePackage.GeocodeMapSamplePlugins


    class GeocodeMapSampleCommon


        internal static void GeocodeAddress(Plugin.LocalPluginContext localContext, Entity preImageEntity)


            if (localContext == null)


                throw new ArgumentNullException("localContext");



            var pluginExecutionContext = localContext.PluginExecutionContext;

            var targetEntity = pluginExecutionContext.InputParameters["Target"] as Entity;


            if (targetEntity == null)


                throw new NullReferenceException("targetEntity");





                var targetGeocodeMapSampleEntity = targetEntity.ToEntity<dkdt_GeocodeMapSample>();

                var sb = new StringBuilder();


                // see http://dkdt.me/KH4roL for Bing Maps REST API reference

                const string restQueryStart = "https://dev.virtualearth.net/REST/v1/Locations/";

                const string noAddress = restQueryStart + ",,,,";

                var address1 = string.Empty;

                var address2 = string.Empty;

                var city = string.Empty;

                var state = string.Empty;

                var zip = string.Empty;




                if (preImageEntity != null)


                    var previousGeocodMapSampleEntity = preImageEntity.ToEntity<dkdt_GeocodeMapSample>();


                    if (targetGeocodeMapSampleEntity.dkdt_AddressLine1 == null && previousGeocodMapSampleEntity.dkdt_AddressLine1 != null)

                        address1 = previousGeocodMapSampleEntity.dkdt_AddressLine1;

                    if (targetGeocodeMapSampleEntity.dkdt_AddressLine2 == null && previousGeocodMapSampleEntity.dkdt_AddressLine2 != null)

                        address2 = previousGeocodMapSampleEntity.dkdt_AddressLine2;

                    if (targetGeocodeMapSampleEntity.dkdt_City == null && previousGeocodMapSampleEntity.dkdt_City != null)

                        city = previousGeocodMapSampleEntity.dkdt_City;

                    if (targetGeocodeMapSampleEntity.dkdt_State == null && previousGeocodMapSampleEntity.dkdt_State != null)

                        state = previousGeocodMapSampleEntity.dkdt_State;

                    if (targetGeocodeMapSampleEntity.dkdt_Zip == null && previousGeocodMapSampleEntity.dkdt_Zip != null)

                        zip = previousGeocodMapSampleEntity.dkdt_Zip;



                if (targetGeocodeMapSampleEntity.dkdt_AddressLine1 != null)

                    address1 = targetGeocodeMapSampleEntity.dkdt_AddressLine1.Trim();



                if (targetGeocodeMapSampleEntity.dkdt_AddressLine2 != null)

                    address2 = targetGeocodeMapSampleEntity.dkdt_AddressLine2.Trim();



                if (targetGeocodeMapSampleEntity.dkdt_City != null)

                    city = targetGeocodeMapSampleEntity.dkdt_City.Trim();



                if (targetGeocodeMapSampleEntity.dkdt_State != null)

                    state = targetGeocodeMapSampleEntity.dkdt_State.Trim();



                if (targetGeocodeMapSampleEntity.dkdt_Zip != null)

                    zip = targetGeocodeMapSampleEntity.dkdt_Zip.Trim();



                var restQuery = sb.ToString();


                if (restQuery == noAddress)





                // TODO: Move key to plugin configuration

                const string key = "?key=[INSERT_YOUR_BING_MAPS_KEY]";


                var webClient = new WebClient();


                var jsonString = webClient.DownloadString(restQuery + key);

                var response = DynamicJson.Parse(jsonString);


                if (response.statusCode != 200)


                    throw new InvalidPluginExecutionException("Bad address.  Please fix it and try again.");



                var coordinates = response.resourceSets[0].resources[0].point.coordinates;

                targetGeocodeMapSampleEntity.dkdt_Latitude = coordinates[0].ToString();

                targetGeocodeMapSampleEntity.dkdt_Longitude = coordinates[1].ToString();


            catch (Exception ex)


                throw new InvalidPluginExecutionException("Something went wrong in the plug-in.  This must be buggy sample code eh?", ex);





This code does all the geocoding work.  Your generated classes will have different prefix values than dkdt_, so fix the errors by replacing dkdt_ with your prefix.  You will also have to replace the [INSERT_YOUR_BING_MAPS_KEY] string with yours from http://dkdt.me/KH4pNx.  Because of the way I am sharing this class across multiple plugins we, need to make a slight tweak to the Plugin.cs class.  Change protected class Plugin : IPlugin to protected internal class Plugin : IPlugin.  Now is a good time to build.  If you get build errors, well fix em Smile.  It’s a blog post after all.  Assuming you got your build errors fixed, there are a couple more things to do.  Open PreGeocodeMapSampleCreate.cs and replace the contents of  the ExecutePreGeocodeMapSampleCreate method with:

GeocodeMapSampleCommon.GeocodeAddress(localContext, null);

Open PreGeocodeMapSampleCreate.cs and replace the contents of  the ExecutePreGeocodeMapSampleCreate method with:

if (localContext == null)


    throw new ArgumentNullException("localContext");



var context = localContext.PluginExecutionContext;


var preImageEntity = (context.PreEntityImages != null && context.PreEntityImages.Contains(preImageAlias)) ? context.PreEntityImages[preImageAlias] : null;


GeocodeMapSampleCommon.GeocodeAddress(localContext, preImageEntity);

Probably a good time to build and troubleshoot again.  If your build is successful, then sign the plug-in assembly:



Ok, now you should be able to right-click the package project and deploy:


This will register your plug-in and messages.  Now go create a new GeocodeMapSample entity through the CRM UI.  Save, but don’t save and close.  You will see Latitude and Longitude have values after the save.  So now we have to present this stuff on a map.  Let’s do the easy one first: static map image.  Go back to Visual Studio and add a new web resource to the package project:



Replace the contents of StaticMap.htm with the following:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">




        <script type="text/javascript">

   2:             function renderStaticMap() {

   3:                 // ReSharper disable InconsistentNaming

   4:                 var Xrm = window.parent.Xrm;

   5:                 // ReSharper restore InconsistentNaming


   7:                 var latitude = Xrm.Page.getAttribute("dkdt_latitude").getValue();

   8:                 var longitude = Xrm.Page.getAttribute("dkdt_longitude").getValue();


  10:                 if (latitude == null) {

  11:                     return;

  12:                 }

  13:                 if (longitude == null) {

  14:                     return;

  15:                 }


  17:                 // see http://dkdt.me/KH4roL for Bing Maps REST API reference

  18:                 var imageUrl = "http://dkdt.me/KH4rF4" +

  19:                 latitude + "," + longitude +

  20:                     "/18?key=[INSERT_YOUR_BING_MAPS_KEY]";

  21:                 document.getElementById("mapImage").setAttribute("src", imageUrl);

  22:             }




    <body onload="renderStaticMap();" style="BORDER-RIGHT-WIDTH: 0px; BACKGROUND-COLOR: rgb(246,248,250); MARGIN: 0px; PADDING-LEFT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">

        <img id="mapImage" alt="An map image of the current record" src=""/>



Again, replace dkdt_ with your prefix.  You will also have to replace the [INSERT_YOUR_BING_MAPS_KEY] string with yours from http://dkdt.me/KH4pNx.  Drop the web resource in the GeocodeMapSample entity form.  Publish it all and you should find a static map image on the form next time you load/refresh it.  Go through the same process to build a web resource named InteractiveMap.htm.  Replace the contents of the file with the following:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">




        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

        <script type="text/javascript" src="https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&s=1"></script>

   2:         <script type="text/javascript">

   3:         var _map;


   5:         function loadMap() {

   6:             _map = new Microsoft.Maps.Map(document.getElementById("map"), { credentials: "[INSERT_YOUR_BING_MAPS_KEY]" });


   8:             // ReSharper disable InconsistentNaming

   9:             var Xrm = window.parent.Xrm;

  10:             // ReSharper restore InconsistentNaming


  12:             var latitude = Xrm.Page.getAttribute("dkdt_latitude").getValue();

  13:             var longitude = Xrm.Page.getAttribute("dkdt_longitude").getValue();


  15:             if (latitude == null) {

  16:                 return;

  17:             }

  18:             if (longitude == null) {

  19:                 return;

  20:             }


  22:             var location = new Microsoft.Maps.Location(latitude, longitude);

  23:             var pushpin = new Microsoft.Maps.Pushpin(location);

  24:             _map.setView({ center: location, zoom: 10 });

  25:             _map.entities.push(pushpin);

  26:         }




    <body onload="loadMap();" style="BORDER-RIGHT-WIDTH: 0px; BACKGROUND-COLOR: rgb(246,248,250); MARGIN: 0px; PADDING-LEFT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px">

        <div id="map" style="position: relative; width: 100%; height: 100%"></div>



Again, replace dkdt_ with your prefix.  You will also have to replace the [INSERT_YOUR_BING_MAPS_KEY] string with yours from http://dkdt.me/KH4pNx.  Drop the web resource in the GeocodeMapSample entity form.  Drop the web resource in the GeocodeMapSample entity form.  Publish it all and you should find a static map image on the form next time you load/refresh it.  Finally, Latitude & Longitude really are just there for code interaction.  They don’t need to be visible on the form.  Go ahead and hide them.

That’s it!  If you made it through the whole post, you now know the fundamentals of using plug-ins, web resources, and the Bing Maps SDKs to add basic “geospatial” functionality to CRM 2011.  Of course, you probably won’t want to scatter your Bing Maps key through out your code, but I wanted to keep the walkthrough as simple to follow as possible.  You can grab the unmanaged solution and Visual Studio source code here:



Connecting to CRM Online from an outside caller

UPDATE: Thanks to some internal discussions with folks on the SDK team, I discovered a simpler way that doesn’t require manually putting the deviceid/devicepassword in the config file.  I decided to leave this post as-is for two reasons.  First, because the easier way requires full trust and won’t work for you if your hoster or IT department requires partial trust.  Second, so people understand what the easier way automates.  I’ve updated this post with a “you can skip this step” explanation. 


“I want to make calls to CRM from an ASP.NET page, .NET middle tier code, etc.  How do I do it with CRM Online?”

Simple answer right?  Maybe for the persistent developer who is happy to reverse engineer the steps from the SDK documentation.  However, I have to say the SDK doesn’t spell it out for you step by step. 

The following resources seem to help on the surface:

Walkthrough: Build a Web Application That Connects to Microsoft Dynamics CRM 2011 Using Developer Extensions

ASP.NET Web Forms and Data Binding

Create Early Bound Entity Classes with the Code Generation Tool (CrmSvcUtil.exe)

Simplified Connection to Microsoft Dynamics CRM

Sample: Authenticate Users with Microsoft Dynamics CRM Web Services

But there’s a little CRM Online nuance that sort of gets lost in the shuffle unless you connect the dots across some of these articles.  CRM Online, when using a Live ID, requires that you use a DeviceId and DevicePassword when connecting.  While the Simplified Connection to Microsoft Dynamics CRM article does explain this, it leaves it up to the reader to hunt down the whole Device ID setup process.  This post is my attempt to connect the dots in a step by step walkthrough of building a simple ASP.NET Web Forms page that connects to CRM Online using a Live ID.

Let’s start by creating a new ASP.NET Empty Web Application and call it CrmOnlineConnectedWebApp:


Add the following references from the SDKbin folder.

  • Microsoft.Xrm.Client.dll
  • Microsoft.Xrm.Sdk.dll

Add the following references from .NET.

  • System.Data.Services.dll
  • System.Data.Services.Client.dll
  • System.Runtime.Serialization.dll


You can skip this next step and jump to CREATE EARLY BOUND TYPES if you follow the enhancement in the Eliminating manual device registration post.

There’s a section titled “To Generate your individual device ID and password” in the Create Early Bound Entity Classes with the Code Generation Tool (CrmSvcUtil.exe), but it’s easy to miss.  Follow the instructions from that section:

  • Open and build the DeviceRegistration project: SDKToolsDeviceRegistrationDeviceRegistration.csproj.
  • Run the executable file from the command line. To register your device, set the /operation parameter to Register.
  • C:deviceregistration.exe /operation:Register
  • Copy the displayed device ID and password values and use them as the deviceid and devicepassword parameter values when you run the CrmSvcUtil tool.

The easiest way to copy the Device ID and the Device Password from the console is to right-click and select all:


…right-click again (this will copy the contents) and paste into notepad.  Then you can copy the actual values. 


Let’s create some early bound types as described in step one of Walkthrough: Build a Web Application That Connects to Microsoft Dynamics CRM 2011 Using Developer Extensions.  However, we need to remove the domain flag:

CrmSvcUtil.exe /codeCustomization:"Microsoft.Xrm.Client.CodeGeneration.CodeCustomization, Microsoft.Xrm.Client.CodeGeneration" /out:Xrm.cs /url:[YOUR_CRM_ROOT]/XRMServices/2011/Organization.svc /username:[YOUR_USERNAME] /password:[YOUR_PASSWORD] /namespace:Xrm /serviceContextName:XrmServiceContext

Now add the generated file to your Visual Studio project.  Now is a good time to build.  If the build fails, you are likely missing an assembly reference.  Now let’s add a Web Form called Default.aspx:


Add a GridView to the markup of Default.aspx:


The next steps are slightly different if you decided to use the approach in my Eliminating manual device registration post.  Switch to Default.aspx.cs and paste the following code into the Page_Load handler:

var connection = new CrmConnection("CrmOnline");

var context = new XrmServiceContext(connection);


var query = from a in context.AccountSet

            select new







GridView1.DataSource = query.ToList();


The final step is to put the CrmOnline connection string into your web.config:


    <add name="CrmOnline" connectionString="Url=[YOUR_CRM_ORG_URL]; Username=[YOUR_LIVE_ID]; Password=[YOUR_PASSWORD]; DeviceId=[DEVICE_ID_FROM_CONSOLE]; DevicePassword=[DEVICE_PWD_FROM_CONSOLE]"/>


You should be able to run the app now and see data in the GridView.


Help make Microsoft developer technologies better!

Follow devkeydet on Twitter

Ron Jacobs just blogged about how .NET developers can provide feature feedback and vote on WCF/WF features.


Many Microsoft product teams are doing this nowadays. It still surprises me how many .NET developers don’t realize these feature voting sites exist. In addition to WF/WCF, I am aware of these:























Let me know in the comments if I’ve missed any.  I’ll add them.

Multi-Touch Dev Dinner this week in Reston, Va

digg_url = “http://blogs.msdn.com/devkeydet/archive/2010/02/22/multi-touch-dev-dinner-this-week-in-reston-va.aspx&#8221;;digg_title = “Multi-Touch Dev Dinner this week in Reston, Va”;digg_bgcolor = “#555555”;digg_skin = “normal”;http://digg.com/tools/diggthis.jsdigg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;

In case you missed it through the DevDinner tag on my team blog (official place for Developer Dinner posts), MSDN Flash, or http://communitymegaphone.com

Timezone: Eastern Time

Start Time: 2/24/2010 6:00:00 PM

End Time: 2/24/2010 8:00:00 PM

Title: Microsoft Developer Dinner: Hands-on Natural User Interfaces: Multi-touch development with Silverlight and WPF 4

The Natural User Interface (NUI) is the next revolution of human-computer interaction. Microsoft Surface has shown the potential of multi-touch NUIs to uniquely engage users, and multi-touch tablets and displays are becoming more and more common. This talk is focused on how you can create multi-touch NUIs for these devices. You will learn the difference between manipulations and gestures, when to use each, and how to implement specific NUI design concepts with both Silverlight and the WPF 4 Touch API. The differences between the Silverlight and WPF 4 Touch APIs will be highlighted. You will hear about the roles of the Surface Toolkit for Windows Touch and the Microsoft Surface Manipulations and Inertia Sample for Silverlight and how you can use them to jump-start your applications. The open-source multi-touch Bing Maps 3-D WPF control, InfoStrat.VE, will also be demonstrated. If you are interested in rich, engaging multi-touch interfaces for the web or client, then you need to attend this talk!

Website: http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032440485&Culture=en-US

Event Type: Other (in-person)

12012 Sunset Hills Road
Reston, VA, 20190

Lat/Long: 38.954957, -77.358214

Audiences: Developer.

Entity Framework 4.0 Sneak Previews

If you haven’t been keeping up on the ADO.NET team blog, but you want to get up to speed with what’s coming in the next release of the Entity Framework (.NET 4.0), then now is the time to start monitoring their blog.  Since 5/11, they’ve cranked out seven posts on new features.  I like what they are doing.  The post on 5/11 gives you a high level update.  Then, they have followed it up with “Sneak Previews” of specific improvements.  Definitely worth the time to read through these posts!

jQuery & MicrosoftAjax “happy together”

I’ve been using jQuery quite a bit lately.  I’ve grown very fond of it.  At the same time, I have been digging into ASP.NET AJAX 4.0.  I just read a post from Bertand Le Roy that made me smile.  In his post, he shows how you can do the following:

<ul class="dv">

    <li>{{ $dataItem }}</li>


<script type="text/javascript">
   1:     $(".dv").dataView({ data: ["foo", "bar", "baz"] });


To me, being able to instantiate a DataView control using the jQuery plugin syntax is PRETTY COOL!  Check out the details of how all this works and download the sample at:


DevDinnerOnDemand: What’s new in ASP.NET 4.0

digg_url = “http://blogs.msdn.com/devkeydet/archive/2009/03/25/devdinnerondemand-what-s-new-in-asp-net-4-0.aspx&#8221;;digg_title = “DevDinnerOnDemand: What’s new in ASP.NET 4.0”;digg_bgcolor = “#555555”;digg_skin = “normal”;http://digg.com/tools/diggthis.jsdigg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;

I decided not to publish the last Developer Dinner in favor of pointing you to newer sessions last weeks MIX 09 conference.  These sessions basically cover everything I covered at the dinner and more.

Microsoft ASP.NET 4.0 : What’s Next?

Choosing between ASP.NET Web Forms and MVC

Microsoft ASP.NET: Taking AJAX to the Next Level

There are some other great sessions on ASP.NET & MVC as well.  You can check out all the ASP.NET content by going to https://content.visitmix.com/2009/sessions/default.aspx and selecting the ASP.NET tag on the left hand side just under the session/agenda selection tool.

REMINDER: The follow up post for this developer is at: