Ping Pong Pairing October Event

The October event for the Minneapolis/St. Paul .NET User Group was on Ping Pong Pair Programming, the combination of test-driven and pair-programming techniques in which one developer writes a unit test, a second developer writes application code to pass the test, and then they switch places.

I will be updating this post with the code written during the event, my short slide presentation, and possibly some other media.

Thanks again for attending my presentation, I hope you had a lot of fun. Please leave me any feedback on the event here, especially if you did or did not like the deviation from the standard lecture format of the group.

Presentation and Code

ASP.NET ViewState Compression and AJAX

There are many articles and blog posts out there that talk about ViewState in-depth and how to handle it when it becomes too large. A large ViewState slows down your user’s browsing experience due to larger page sizes. There are many ways to address this issue: decreasing your use of ViewState, storing the ViewState in Session or elsewhere, HTTP compression, and the topic of my post, compressing the ViewState hidden field value.

At my last project we had been using ViewState compression, and it had worked just fine for them for a couple of years. The client was using the same solution that I’m sure 90% of the community was, where you override the two Page methods:

LoadPageStateFromPersistenceMedium
SavePageStateToPersistenceMedium

and store the compressed ViewState in a hidden form field. Here’s an example from one such article:

public partial class MyPage : System.Web.UI.Page
{
	protected override object LoadPageStateFromPersistenceMedium()
	{
		string viewState = Request.Form["__VSTATE"];
		byte[] bytes = Convert.FromBase64String(viewState);
		bytes = Compressor.Decompress(bytes);
		LosFormatter formatter = new LosFormatter();
		return formatter.Deserialize(Convert.ToBase64String(bytes));
	}

	protected override void SavePageStateToPersistenceMedium(object viewState)
	{
		LosFormatter formatter = new LosFormatter();
		StringWriter writer = new StringWriter();
		formatter.Serialize(writer, viewState);
		string viewStateString = writer.ToString();
		byte[] bytes = Convert.FromBase64String(viewStateString);
		bytes = Compressor.Compress(bytes);
		ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
	}
}

Note that Compressor is a custom class that you would write to do the compression/decompression. See the article above for sample code using Microsoft’s built-in compression libraries.

On our new endeavor of using third-party controls that used AJAX we noticed a problem. It seems these controls do not like the ViewState being ‘moved’ to a different form field (here it was moved to __VSTATE instead of the standard __VIEWSTATE). There must be some hard-coded references to this field name, and they cannot properly track their own state. The controls loaded fine but most of the AJAX calls would not run all of the correct events on the server.

After some searching I came across a solution that still compresses the ViewState but does so in an AJAX-friendly manner by leaving it in the __VIEWSTATE field. Since it was a hard-to-find forum post I thought it warranted a little more visibility and discussion.

In ASP.NET 2.0, Microsoft added a class called PageStatePersister, which is also exposed a property on the Page class itself. The page events mentioned above are still there and used, but now they hand off the dirty work to the PageStatePersister. The PageStatePersister is responsible for loading and saving ViewState.

There are a couple of ways you can implement ViewState compression using these events and/or PageStatePersister. One way is that you could you write your own persister and override the PageStatePersister property on the Page to use your class instead.

In my case I decided to override the two Page events above and now work with the PageStatePersister within the events. First, let’s look at the LoadPageStateFromPersistenceMedium event:

protected override object LoadPageStateFromPersistenceMedium()
{
	String alteredViewState;
	byte[] bytes;
	Object rawViewState;
	LosFormatter fomatter = new LosFormatter();

	this.PageStatePersister.Load();

	alteredViewState = this.PageStatePersister.ViewState.ToString();

	bytes = Convert.FromBase64String(alteredViewState);
	bytes = Compressor.Decompress(bytes);

	rawViewState = fomatter.Deserialize(Convert.ToBase64String(bytes));

	return new Pair(this.PageStatePersister.ControlState, rawViewState);
}

You see we first tell the PageStatePersister to Load itself with the ViewState. We then decode it as a base64 string and decompress. It is then deserialized and placed into a Pair object with current control state. The Pair is what is returned.

And now for the SavePageStateToPersistenceMedium event:

protected override void SavePageStateToPersistenceMedium(object viewStateIn)
{
	LosFormatter fomatter = new LosFormatter();
	StringWriter writer = new StringWriter();
	Pair rawPair;
	Object rawViewState;
	String rawViewStateStr;
	String alteredViewState;
	byte[] bytes;

	if (viewStateIn is Pair)
	{
		rawPair = ((Pair)viewStateIn);
		this.PageStatePersister.ControlState = rawPair.First;
		rawViewState = rawPair.Second;
	}
	else
	{
		rawViewState = viewStateIn;
	}

	fomatter.Serialize(writer, rawViewState);
	rawViewStateStr = writer.ToString();

	bytes = Convert.FromBase64String(rawViewStateStr);
	bytes = Compressor.Compress(bytes);

	alteredViewState = Convert.ToBase64String(bytes);

	this.PageStatePersister.ViewState = alteredViewState;
	this.PageStatePersister.Save();
}

Here we take the viewStateIn, which is the normal ViewState and instead compress it before saving to the PageStatePersister.

Now our ViewState is compressed and stored in the standard __VIEWSTATE field and our AJAX-enabled controls should be happy!

Links and references:
ViewState Compression
Forum post - Ajax Beta 1, UpdatePanel and Viewstate issue
Get view state off __VIEWSTATE!

Aug08 Minneapolis Silverlight User Group

Tips and Tricks for Dealing with Data in Silverlight

Scott Davis

Ignition Point Solutions

Scott talked about why you may want to use Silverlight for line-of-business applications. He asks: Is anyone aware of any good reporting solutions written for Silverlight?

When planning your Silverlight application, a design consideration is that everything is done asyncronously. Scott has developed a technique which keeps his data updated using threaded services.

WCF full duplex communications do not work in Silverlight.

In the demonstrated WCF communication, the Silverlight client sends a request to the server that says, send me updates since the last time I came back. This is done independent of the UI and thus the UI stays updated.

Aug08 Silverlight User Group

Using System.Web.Routing with Castle MonoRail

Several folks have already posted about using System.Web.Routing with standard ASP.NET WebForms, and I’d like to extend the concept for use with MonoRail. The default MonoRail router is not terribly sophisticated. It works by using pairs of regular expressions to match and then rewrite a url into /area/controller/action/id format. Here is an example from the documentation:

<rule>
	<pattern>(/blog/posts/)(\d+)/(\d+)/(.)*$</pattern>
	<replace><![CDATA[ /blog/view.rails?year=$2&month=$3 ]]></replace>
</rule>

It’s functional, and you can achieve most any route that you’d like, but the syntax is awkward. System.Web.Routing provides a much cleaner solution:

routes.Map(
   "MonthlyArchives",
   "/blog/posts/{year}/{month}",
   new { controller = "blog", action = "view" }
);

ScottGu gives a good tutorial.

Before we can get started, we’ll need to examine how both MonoRail and System.Web.Routing perform routing and IHttpHandler creation. Unfortunatley, an explanation of ASP.NET handlers and modules is beyond the scope of this post. Although dated, there are some good overviews.

System.Web.Routing runs as an IHttpModule, examines incoming requests, matches them against registered routes, and, if a match is found, uses the IRouteHandler associated with the matched route to create an IHttpHandler, which will process the request.

MonoRail on the other hand has a straightforward IHttpHandlerFactory implementation, MonoRailHttpHandlerFactory, which parses the request url for /area/controller/action.extension/id syntax. If the MonoRail routing module is installed, that module will rewrite the url and create a RouteMatch object in the current HttpContext.Items collection.

Therefore a successful integration will need to use the existing MonoRailHttpHandlerFactory infrastructure–directly creating controllers requires far too much supporting context which the factory provides–yet allow System.Web.Routing to inform the controller/action selection using its much richer RouteData output.

We’ll start by subclassing the MonoRailHttpHandlerFactory and adding the IRouteHandler interface:

public class MonoRailRouteHandler : MonoRailHttpHandlerFactory, IRouteHandler
{
    #region IRouteHandler Members

    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        var context = HttpContext.Current;
        return GetHandler(
            context,
            context.Request.RequestType,
            context.Request.RawUrl,
            context.Request.PhysicalApplicationPath);
    }

    #endregion
}

This handler is clearly just a passthrough to the underlying MonoRail GetHandler factory method. We’ll need to somehow use the routing information from System.Web.Routing to tell GetHandler what to create. Fortunately, Castle is very flexible here, and has a dependency, IUrlTokenizer, which takes a url and returns a UrlInfo structure. UrlInfo contains area, controller, and action properties (amongst other less interesting properties). Next lets build a IUrlTokenizer that just provides whichever UrlInfo it’s told to:

public class MockUrlTokenizer : IUrlTokenizer
{
    [ThreadStatic]
    private static UrlInfo _currentUrlInfo;

    public static UrlInfo CurrentUrlInfo
    {
        get { return _currentUrlInfo;}
        set { _currentUrlInfo = value; }
    }

    public void AddDefaultRule(string url, string area, string controller, string action)
    {
        throw new NotImplementedException();
    }

    public UrlInfo TokenizeUrl(string filePath, string pathInfo, Uri uri, bool isLocal, string appVirtualDir)
    {
        return CurrentUrlInfo;
    }
}

Finally we’ll modify our IRouteHandler to use the new UrlTokenizer as well as convert the System.Web.Routing RouteData to a MonoRail RouteMatch:

public class MonoRailRouteHandler : MonoRailHttpHandlerFactory, IRouteHandler
{
    public MonoRailRouteHandler()
    {
        UrlTokenizer = new MockUrlTokenizer();
    }

    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        var context = HttpContext.Current;

        // parse urlinfo from the s.w.routing data
        var values = requestContext.RouteData.Values;
        MockUrlTokenizer.CurrentUrlInfo = new UrlInfo(
            context.Request.Url.Host,
            context.Request.Url.Host,
            context.Request.ApplicationPath,
            context.Request.Url.Scheme,
            context.Request.Url.Port,
            context.Request.RawUrl,
            values.ContainsKey("area") ? (string)values["area"] : String.Empty,
            values.ContainsKey("controller") ? (string)values["controller"] : String.Empty,
            values.ContainsKey("action") ? (string)values["action"] : String.Empty,
            String.Empty,
            context.Request.Url.Query
        );

        // create a monorail routematch
        var match = new RouteMatch();
        foreach (var pair in values)
        {
            match.Parameters.Add(pair.Key, pair.Value as string);
        }
        context.Items[RouteMatch.RouteMatchKey] = match;

        // allow standard monorail handler to proceed
        return GetHandler(
            context,
            context.Request.RequestType,
            context.Request.RawUrl,
            context.Request.PhysicalApplicationPath);
    }
}

Now you can simply register routes normally, using the new MonoRailRouteHandler.

Go ahead and grab the source file which includes a couple of extras:
MonoRailRouteHandler.cs.

Quote of the day: The quick and the dead

I have recently started a habit of writing interesting quotes on my white board. I didn’t think much of it at first but it drove a healthy amount of reactions from various folks at ilm. One thing let to another and I found myself writing a new quote every other week or so. Then it occurred to me that since I spend so much time discussing these quotes, I might as well publish them in my blog. Feel free to comment with your thoughts. I am always eager to hear new opinions.

There will be two kinds of companies in the future, the quick and the dead.

I picked this quote from a book I recently read and it immediately made my mind wonder. Luna and I have been running ilm for slightly over 6 years and have been successful in building a specialty firm from scratch. Considering that we started in 2002–in-arguably the worst economic year for IT consulting–without any prior IT leadership experience or business relationships with IT decision makers, we think we did alright. 

What transpired during the 6 years after ilm’s inception is the story of the quick and the dead. Luna and I might not have been the most experienced entreprenuers but we knew that we must do everything quickly or face extinction. As a result, we were the first in the Twin Cities to start the Executive.NET seminar series. Started in 2002, this series offered plain and simple truths about the shinny new .NET framework and VS.NET to the executive audience.

Microsoft did such a poor job positioning .NET to decision makers that almost all of them decided to wait and see how early adopters utilized the technology. This approach might work for some old fashioned consulting firms who can afford to sit around for couple of years while their customers get educated properly, and in fact there were firms in the Twin Cities that did take the wait and see approach. We didn’t have that luxury. We were running under the quick and the dead mindset. So, we put together a series of on-site seminars at the local Microsoft office and started spreading the word.

Our first event registered over 20 IT decision makers, most of whom were the ones we didn’t know. They got to meet us and saw us as experts in this technology. We did 12 of these sessions over the course of 2 years. Our mindset of being “quick” with our initiatives and our fear of being “dead” by sitting around propelled our growth. ilm has been averaging over 40% growth year after year since then.

Now, I must confess where we went wrong. 2007 was probably the worse year for ilm because we finished the whole year without a single new initiative. Yes, we organized and sponsored the largest .NET developers conference in Minnesota that year, but that can’t be considered a new initiative for 2007. The Minnesota Developers Conference (MDC) was envisioned in 2006 by leaders at ilm. Once again, we worked very very quickly to take this event from vision to completion in about 8 weeks. While MDC 06 attracted a sold out crowd of 275 attendees and put our name on the top of the IT consulting game in the Twin Cities, MDC 07 was bigger and better and it met all its objectives by attracting over 375 attendees. Yet it still was a re-occurrence of the concept from the previous year.

We were getting too comfortable with our process, our format, and our service offerings. This lack of initiatives in 2007 caused the excitement level to reduce at ilm, allowed the competition to launch their own community initiatives, and risked our position as one of the technology consulting leaders in this city.

We started 2008 with a lot of frustration amongst ilm’s decision makers. After many discussions and disputes, we put forward a strategy of getting back to our roots. We have optimized our various business processes for efficiency, optimized our recruiting team and processes for un-compromised rigor, re-structured how we sell, and take the leadership initiatives among the developers community.

Now 2008 is proving to be among the most exciting year at ilm. We have formed and successfully launched the SilverLight user group, started the executive series of seminars once again, launched the IGC (ilm generated content) initiative, hired a dedicated consulting manager, started the Team System and SilverLight practices, only to name a few.

We are once again running with the mindset of being “quick” and it is very exciting.

Volunteers needed for the new website

Ok, Ok, I know. The web sites for both user groups look hidous, so last century. Actually, if the internet was invented in the 16th century then that is how those websites would have looked like. :-)

So, it is time for you to stop complaining and start contributing. :-) We have setup a subversion source control at ilm (hush, don’t tell anyone at Microsoft, and yes we do have Team System practice at ilm and do use TFS for internal source control). However, we feel that Subversion is a better tool of choice for open source and community based development, because its free!!!

I would like to kick start the project ASAP. Help us by spending a few extra hours a week. I will buy you a nice dinner at the completion of the project. My way of saying thanks :-) You can volunteer by writing comment to this blog entry and explaining a little bit about your .NET and ASP.NET expertise.

Seeking speakers for the .NET and the SilverLight User Groups

This has been yet another exciting year for the developers community initiatives at ILM. The .NET User Group has held successful events this year on ASP.NET MVC, Identity Federation, Share Point CMS, Model based Testing, and WCF/WF working together. The SilverLight user group held its first three events attracting over 100 attendees for the first two events and around 45 for the third event. The first two events were focused on broad topics, whereas, the third event was focused on a specialty topic of search engine optimization.

I am now working to finalizing the speakers and sessions for the next few events. I am reaching out to all technology enthusiasts like you in the Twin Cities, Minnesota area, with the hope that you would be willing to contribute to these user groups by speaking at one of the upcoming events.

The sessions are generally 1 to 1.5 hours long and are usually given to a large audience in a seminar setting. I am very open to alternative ideas, however.

The .NET user group focuses on everything .NET and targets mid-level to expert level audience.

The SilverLight user group focuses on both developers and designers. I will be thrilled to see a few upcoming events on the designer focused topics. So, if you have something cool to show about your expertise with SilverLight, WPF, Expressions, or XAML I will be happy to talk to you about it.

If you are interested in speaking at either user group, please write a comment to this blog entry and specify the user group, the topic, and the approximate date that works for you. The .NET user group meets every first Thursday of the month from 5-7pm and the SilverLight user group meets every third Tuesday of the month from 12-2pm. You can visit both of the user groups at http://www.ilmservice.com/twincitiesnet and http://www.ilmservice.com/silverlight respectively.

Announcing Ask the Expert (ATE) sessions for the Twin Cities .NET User Group

I am very happy to announce the introduction of the Ask the Expert (ATE) sessions for the Twin Cities .NET User Group. I have been seeking for a while to diversify the user group’s format to be more than just speaker driven presentations, and this format came highly recommended by many members, friends, and co-workers.

This blog entry is intended to solicit questions that you would like to ask an expert. There are no strict guidelines. You can feel free to ask a technical questions regarding any area of the .NET framework, languages, developer tools, or just about anything that can make you a better developer.

You can enter your questions by simply writing a comment to this blog entry. The more questions you ask, the more succesful the user group events will become. I will continously scan your questions and seek experts in the Twin Cities area, who would be willing to visit the user group events, and answer these questions.

I am also dedicating the first 20-30 minutes of all future user group events to conducting the ATE sessions. There will undoubtly be some sessions where we will only get to answer a couple of questions, and then there will be sessions where we will be able to answer a lot more.

These sessions are your opportunity to engage the experts and enhance your skills.

July08 Minneapolis Silverlight User Group

Today was the Minneapolis Silverlight User Group. It was my first user group presentation, so kind of glitchy! All the GUYS (ok there were Four women this time) were very kind and attentive.  No one got up and walked out - so I'm a happy camper.

We talked about Search Engine Optimization and how to enable applications that use Silverlight to keep Search Engine Rankings as high as possible.  Those topics are discussed freely on the web and I pulled a lot of the content from Nathan Buggia's Mix08 talk and Nikhil Kothari's blog.  So thanks you guys. 

But, the sample code is mine, at least.  It's a minimal Ecommerce site demo which is based off of an actual ecommerce site that is in development.  So I hope it's helpful.  I may pull some of the relevant pieces out of the app and write up some details - why it's there, it's operation, it's purpose.

Some of the features in the sample application are:  web.Sitemap to Silverlight menu, WrapPanel for category listing, a sample of how to use the same .xap file for multiple page areas (those are the islands, look in app.xaml), registering your url (for deep linking)  and turning off the html when javascript is enabled. 

To see the page as a search engine would just turn off your javascript and the html formatting will be there.

Those links are at the top. Have a great day!

June08 Minneapolis Silverlight User Group

The third Tuesday in June, 2008 was the second Silverlight User Group at Microsoft offices in Edina.  Wow.  Lots of Men there!   ( OK, I counted three women, 123 men inside the presentation area.  But that’s a topic for another blog post.)

Doug Nelson presented to us and very skillfully demonstrated how Silverlight controls can interact with the browser.  Doug’s source code for the presentation will be here, I promise.  I have to corral him first, so give me a few.

Here are some notes I took while there, I apologize if my observations are not quite on topic - I’m a presenter in training , I get to give the next talk and I have a lot to learn.

Doug used a special coloring scheme for his Visual Studio environment which was nicely visible from the back of the room where I sat.  I noted the colors ( I don’t know why)

SCREEN COLORS:  Black background, white regular writing, neon green comments.  blue keywords, pink class names.

The presentation title was “Kiss Your Javascript Goodbye”. This is catchy, but to me it was more of a great tutorial on how the browser and Silverlight applications interact with each other. It was very ugly, but that’s ok because all the functionality we needed to know about was discussed.

Here’s just a simple list of how the topics flowed:

  1. How Silverlight applications are structured, what they look like in Visual Studio.
  2. What is App.xaml and what purpose does it serve.
  3. The use of Window.Eval in the application error for error reporting (security - this is just a demo.)
  4. Page.xaml. How is it constructed. How you hook into browser events.
  5. Presentation Slide.
    1. a. Page, Window, Document
    2. HtmlPage
      1. Browser Information
      2. Document
      3. Window
  6. Html Document
  7. DEEP LINKING!
  8. NavigateToBookmark!
  9. HtmlWindow
    1. Alert, Confirm
    2. Submit
  10. Demo again. The bookmark is updating the url in the browser address bar. This is what I need to support deep linking.
  11. HttpUtility
    1. a. HtmlPage.Window.NavigateToBookmrk
  12. HtmlElementEventArgs
    1. Stop Propagation - Prevent bubbling
    2. Key State, Key Code
    3. Mouse Button
    4. Screen Offset Window Coordinate Info
  13. Flying Div: the use of SetStyleAttributes to change pieces of the CSS in the html.
    1. Sets a DispatcherTimer - EventHandler. TimeSpan(0,0,0,0,10)
    2. Using{} cleans out the resources when no longer used
      1. Delete Service Proxy.Dll - Reinstall to replace it.
      • Notes: WCF Service gave some issues.
      • Silverlight Enabled WCF Service - Default Binding set for What Silverlight Supports.
        If you installed the Beta2 bits early on, you should check your SDK size. If your SilverLight Tools Install size is 1.14 or under, you should uninstall it and bring it down again from the download site. You want to see something the size of 1.17. This is what you want, not 1.13 or 1.14.
  14. When building WCF services, inside Visual Studio you’ll be able to use Tabs to build your stubs to save typing.
  15. Talk about how MVC fits in
  16. X-Domain, show clientaccessplicy.xml
  17. The root is clientbin folder when loading from WebClient.
  18. Isolated Storage Demo
  19. Types for creating and using Virtual File System
  20. Exists on Client between Browser Sessions
  21. Clearing Cookies and Deleting Temporary Files doesn’t delete these files.
  22. Mechanism for examining contents Of isolated Storage. Yes. It allows us to iterate the file system. Allows disconnected storage
  23. Finding the Isolated Data store on the disk. Local Storage. Appsettings / microsoft, isolated storage.
  24. Promotes code reuse for data validation

Attendees




Creative Commons Attribution 3.0 United States
Creative Commons Attribution 3.0 United States