Friday, May 28, 2010

Looking ahead to Q2 2010, Part 2

futureExit A few weeks ago, I started sharing with you highlights from the rapidly approaching July Q2 2010 Telerik release. We looked at the road maps for ASP.NET AJAX, ASP.NET MVC, and WinForms and I hand-picked a few of the updates for each product that should get you really excited about what’s coming in less than 8 weeks time. But this is 2010 and a Telerik release means updates to 9 developer products!

What else should you be looking forward to in Q2 2010? Here are some ideas:

  • RadControls for Silverlight/WPF
    • [!NOTE] Only SL4/WPF4 builds will get new controls (v3 will be bug fixes only)
    • [NEW CONTROL] RichTextBox (incredible, Word-like editor)
    • [NEW CONTROL] TreeListView
    • [NEW CONTROL] RadFilter
    • New BusyIndicator being added to all controls for auto remote-request UX
    • [RadGridView] New multi-cell selection (foundations for advanced copy/paste)
    • [RadCart] New annotations, exploding radial series, log axis
    • [RadScheduler] Improved perf (UI virtualization), improved rendering, grouping
    • New theme and animations
    • Improved VS2010 support (Collection Editor, SmartTag)
  • OpenAccess ORM
    • Support for WCF Ria & Data Services
    • New DataTransporterObjects (self-tracking entities)
    • DataAnnotations support
    • Improved RLINQ visual designer (support for reverse & forward mapping!)
    • [NEW DB SUPPORT] SQLite
  • JustCode
    • [NEW] Unit Test Runner!
    • Enhanced XAML navigation and refactoring support
    • New visual cues for easier access to all features
    • At least 3 new refactorings
    • Improved code navigation and code analysis engine
  • Telerik Reporting
    • [NEW] Interactive reports (hyperlinks for drill down, navigation, & external links)
    • New data source components for OpenAccess ORM and EF
    • Improved Silverlight support

On top of all that, Q2 will also introduce the first official release of JustMock (including basic JustMock integration with JustCode) and TeamPulse (our new team planning tool). Combine that with the list of new stuff from my last post, and once again you’ve got a huge release coming your way this summer.

Fortunately, betas for Q2 are just around the corner. Betas will start shipping as early as next week (with a JustCode beta) and then continue shipping throughout June. Keep your RSS reader locked here for more updates as we make our way to Q2.

Thursday, May 27, 2010

Improved, Easy Email Template “Engine” with Smarter ToString Extension

This blog often focuses on Telerik and Microsoft news, and rarely do I bring you much “original thought” code (especially lately). But this class is just too useful not to share.

Let me just lead with the scenario:

  1. You have a program that is going to send auto-generated emails
  2. You want templates for your emails that support value merging
  3. You want to maintain your templates as HTML files for easier editing
  4. You want something as easy to use as String.Format

While there are tons of templating engines for C#, I just wanted something simple and to the point. The solution Scott Hanselman provided a couple of years ago was very close to what I wanted, but it doesn’t support collections (very important for Master-MasterDetail type messages). So I added the tweak to support these scenarios.

Here’s how you use it:

//Create a simple template
string template = "Hello {FirstName}! You've ordered: <ul>{Items:<li>{Name}</li>}</ul>";

//Create your object with the template values (can by anonymous type)
//(Let's use some pseduo LINQ to get a customer with a specific ID)
var myTemplateValues = myObjects.Where(o => o.Id == id).Select(o => new
   {
       FirstName = o.FirstName,
       Items = o.Items //Assume each item in ICollection has Name property
   });

//Merge values with template 
string mergedTemplate = myTemplateValues.ToStringWithFormat(template);

The result of the above code should be a string that looks something like:

Hello Todd! You’ve ordered: <ul><li>Item Name 1</li><li>Item Name 2</li></ul> You can, of course, add formatting to your objects in your template, too, such as: {Birthdate:dd MMM yyyy} But when you’ve got a collection, you can use the object format string to include nested property values, like this: {Customers:<li>{Birthdate:dd MM yyy}</li>} Pretty cool! It’s a nice balance between the templating engines that are super complex and a plain-jane String.Format. It doesn’t do everything you could ever want, but it does enough for many auto-email scenarios. In my own usage, I have a simple method that let’s me quickly merge my context values with my template when I’m ready to build an email’s body:
public static string GetMergedTemplate<T>(string template, T contextInstance)
{
   if (String.IsNullOrWhiteSpace(template))
       return null;

   return contextInstance.ToStringWithFormat(template);
} 
Which brings us to the implementation of ToStringWithFormat. This is a modified version of the extension method from Hanselman that gives us the extra power we desire:
/// <summary>
/// Returns a string and replaces named place holders with object values
/// </summary>
/// <remarks>Originally from Scott Hanselman's Blog: http://www.hanselman.com/blog/ASmarterOrPureEvilToStringWithExtensionMethods.aspx </remarks>
/// <param name="anObject"></param>
/// <param name="aFormat"></param>
/// <returns></returns>
public static string ToStringWithFormat(this object anObject, string aFormat)
{
   return StringExtensions.ToStringWithFormat(anObject, aFormat, null);
}

public static string ToStringWithFormat(this object anObject, string aFormat, IFormatProvider formatProvider)
{
   if (anObject == null)//Can't merge null object. Be nice and return original format string.
       return aFormat;

   StringBuilder sb = new StringBuilder();
   Type type = anObject.GetType();
   //Old pattern: @"({)([^}]+)(})" - Doesn't handle nested brackets
   //New pattern:"({)((?:[^{}]|{[^{}]*})*)(})" - Handles ONE LEVEL of nested brackets
   Regex reg = new Regex(@"({)((?:[^{}]|{[^{}]*})*)(})", RegexOptions.IgnoreCase);
   MatchCollection mc = reg.Matches(aFormat);
   int startIndex = 0;
   foreach (Match m in mc)
   {
       Group g = m.Groups[2]; //it's second in the match between { and }
       int length = g.Index - startIndex - 1;
       sb.Append(aFormat.Substring(startIndex, length));

       string toGet = String.Empty;
       string toFormat = String.Empty;
       int formatIndex = g.Value.IndexOf(":"); //formatting would be to the right of a :
       if (formatIndex == -1) //no formatting, no worries
       {
           toGet = g.Value;
       }
       else //pickup the formatting
       {
           toGet = g.Value.Substring(0, formatIndex);
           toFormat = g.Value.Substring(formatIndex + 1);
       }

       //first try properties
       PropertyInfo retrievedProperty = type.GetProperty(toGet);
       Type retrievedType = null;
       object retrievedObject = null;
       if (retrievedProperty != null)
       {
           retrievedType = retrievedProperty.PropertyType;
           retrievedObject = retrievedProperty.GetValue(anObject, null);
       }
       else //try fields
       {
           FieldInfo retrievedField = type.GetField(toGet);
           if (retrievedField != null)
           {
               retrievedType = retrievedField.FieldType;
               retrievedObject = retrievedField.GetValue(anObject);
           }
       }

       if (retrievedType != null) //Cool, we found something
       {
           string result = String.Empty;
           if (toFormat == String.Empty) //no format info
           {
               if (retrievedObject is ICollection)
               {
                   foreach (var item in (retrievedObject as ICollection))
                   {
                       //In this branch toFormat is blank, so just call toString on
                       //each object in collection (ex:{Items})
                       result += item.ToString();
                   }
               }
               else
                   result = retrievedObject.ToString();
           }
           else //format info
           {
               if (retrievedObject is ICollection) //Process first level collection
               {
                   foreach (var item in (retrievedObject as ICollection))
                   {
                       //In this branch toFormat contains nested property name, so
                       //make recursive call to ToStringWithFormat to process property value
                       //(ex: {Items: {PropertyName}})
                       result += item.ToStringWithFormat(toFormat);
                   }
               }
               else
                   result = String.Format(formatProvider, toFormat, retrievedObject);
           }
           sb.Append(result);
       }
       else //didn't find a property with that name, so be gracious and put it back
       {
           sb.Append("{");
           sb.Append(g.Value);
           sb.Append("}");
       }
       startIndex = g.Index + g.Length + 1;
   }
   if (startIndex < aFormat.Length) //include the rest (end) of the string
   {
       sb.Append(aFormat.Substring(startIndex));
   }
   return sb.ToString();
}
A key limit in this approach is the RegEx, which technically is not adept at finding nested bracket patterns. RegEx works fine if you accept a fixed number of supported nested levels, but it cannot dynamically handle unknown levels of nesting. A single level was fine for my needs and thus I left it at that, but this could be extend to provide even richer support for collections if RegEx were replaced.

I hope you enjoy this simple update on a classic. As commenters pointed out in Scott’s original post, this approach does create opportunity for “evil” when it comes to refactoring and performance, so there is still plenty of room to improve. But for a pragmatic solution, I’ve found this very useful.

Thursday, May 06, 2010

Telerik TV v2 beta now live!

ttv2-homepage As you know, video is increasingly becoming an important part of learning on the web, and at Telerik we’ve been embracing video for a while now. The current version of Telerik TV moves more than 2 terabytes of data every month and it continues to grow in popularity. It has served its purpose, but as we continue to add products and more videos, we recognized the need for a better portal.

The main goal for Phase One of Telerik TV v2 (or TTV2, as we call it) is to make it easier to find videos. In the current system, you have very limited options for finding videos, and often older videos are very difficult to locate. The system aims to resolve that by introducing multiple “paths” to a video so that people with all styles of browsing preference can find Telerik video content.

In the Phase One beta, you’ll find many new features, including:

  • Multiple featured videos on the home page (presented with Telerik’s Silverlight CoverFlow)
  • Video series (a collection of ordered, related videos)
  • Video ratings (tell us if you love or hate a video)
  • Video feedback (send us comments about a video)
  • TweetMeme and Facebook Like support (FB like is disabled in Beta)
  • Dedicated page for every Telerik product with helpful video resources (including “Getting Started” video series)
  • Progressive Enhancement tooltips (hover over a video to see more details)
  • Improved video search
  • Browse videos by Category and Tag

TTV2 is built on ASP.NET MVC 2 using the Telerik Extensions for ASP.NET MVC and OpenAccess ORM for data access. And, yes, we are still using Flash for video delivery, but that is changing in Phase Two (more on that in a moment).

Check-out the live Beta of Telerik TV 2 now and let us know what you think!

What’s Next

We don’t plan a long beta for TTV2. In fact, we are primarily running this beta to make sure there are no major issues and to make sure all configuration of the new site is complete (we already know a few areas need some more attention). If everything looks good, we’ll be taking TTV2 to production as early as next week.

Phase Two
After Phase One ships, we’ll be working quickly to prepare Phase Two. Some of the things we hope to achieve in Phase Two with TTV2 are:

  • Silverlight-based media encoding and delivery (with uncompromised delivery performance)
    • With the possible addition of HTML5 video playback to enable TTV viewing on iPads and iPhones
  • Chapters in videos
  • Enhanced video analytics (so we know more about how you’re using videos, and then make them better)

Post-Phase Two
We also recognize that the future is not just video. It’s multimedia- or “transmedia” as it’s now being termed. So as we look past Phase Two and in to Phase Three for TTV2, we will be delivering innovative web-based experiences that blend code snippets and text, synchronized with video, in an immersive online learning experience. Similar to the innovation already found in our Telerik Trainer, but made more accessible through the web. Our goal is to provide the best web-based learning experience available for software products.

For now, enjoy the beta and send us your feedback. We hope that these changes help make your lives as developers even easier.

Tuesday, May 04, 2010

Code Converter (finally) updated, Still in Beta

CodeChangerLogo Over three years ago, in my first days as an “official” Telerik employee, I created a small little project as a simple way of showing-off some of Telerik’s RadControls for ASP.NET (this was pre-Prometheus days). The project, Code Converter, is a simple tool for converting code between C# and VB.NET, and it has steadily grown in popularity over the years and is now used by thousands of developers every day.

Today, the conversion approach used by Code Converter got much better! We’re still using the NRefactory open source libraries to power our conversions, but there are three significant improvements:

  1. We updated the NRefactory libraries to the latest available version (4.0.0.5757)
  2. We changed the way code snippet processing is handled, abandoning the old “dummy class wrapper” approach and instead using the more efficient approach described by Fabien in the Code Converter forums.
  3. We added some additional RegEx-based “clean-up” parsing to the conversion to try to fix a few of the errors that NRefactory currently lets slip when converting code. In particular, when converting something like Session(“key”) from VB to C#, our conversion output will correctly change the parenthesis to brackets, or Session[“key”]. No other online converter is doing that today.

The end result of these back-end changes is more accurate conversions. Many of the bugs that have been reported in the Code Converter forums are now fixed by this update. For example, converting this C#:

for (int x = 1; x <= 100; x++) {
int a;
a = x;
}

Now correctly outputs this VB:

For x As Integer = 1 To 100
Dim a As Integer
a = x
Next

No more of the dreaded System.Math.Max(System.Threading.Interlocked.Increment(i),i - 1)! Other scenarios that now convert correctly:

  • Regions (C# to VB)
  • Using statements in a namespace (C# to VB)
  • Type conversions (VB to C#)
  • Lambda expressions (C# to VB)
  • RaiseEvent (C# to VB)

There are, of course, still limits imposed by the underlying NRefactory engine. Among the limits most likely to affect your conversions:

  • No support for converting LINQ syntax
  • No support (yet) for .NET 4 language features

As soon as NRefactory supports these language features, we’ll try to improve our support. In the mean time, enjoy the improved conversion engine and let us know what you think. There are lots of things that could be done with Code Converter in the future, but we want to hear your voice. What would make Code Converter an even more valuable tool for you?

Toronto Code Camp wrap-up

toronto-code-camp So, yeah…in my busy haste to finish 1,001 tasks last week, prep a brand new HTML5 session for the Toronto Code Camp, speak at the South Houston .NET Users Group, and join Carl Franklin and Richard Campbell for their Houston .NET Rocks! Road Trip stop, I kinda sorta ran out of time to actually mention that I was going to Toronto this weekend to speak. So, to kill two birds with one blog post, this is both your “heads-up” post that I’m speaking at the Toronto Code Camp 2010 and the wrap-up!

I presented two sessions this weekend, and I was pleased that they were two of the most popular sessions at the entire event. It always amazes me that people are willing to stand for 75 minutes to watch a session when a room is full. You guys are hardcore and get bonus points in my book. Thanks to everyone that attended the sessions, though! I hope you took away at least one useful bit of info.

My sessions at this event were:

  • Maximizing Ajax Performance – Not new, but always useful for people to see how Ajax really works and what you can do as an ASP.NET developer to get the most out of Ajax. Unfortunately, I was a bit rusty delivering this session in Toronto because I was prepping the next session…
  • The Rich Standard: Getting Familiar with HTML5 – Brand new for Toronto Code Camp, I’ll be doing this session a lot this summer and fall. This is your primer to HTML5 and a must see if you A) care about standards, or B) are a web developer.

Slides for both sessions are available below. The slide notes contain a lot of links to additional resources, so be sure to check them out if you’re trying to dive deep on these topics (especially HTML5). I’ll post code soon, but it needs some tidying before it’s “download ready.”

Overall, it was a great event and more than 600 developers ventured-out for the day of learning. Other than a more than frustrating experience with Canadian immigration cops, I had a great time and would encourage anyone to attend this event in the future!

The Rich Standard: Getting Familiar with HTML5
[Slides (PPTX)]

Maximizing Ajax Performance
[Slides (PPTX)]

[Picture courtesy of Joey DeVilla’s Code Camp Flickr set]