I gave a "lunch and learn" presentation to my company today on ASP.Net MVC and the glorious environment it can create for you.  I titled the presentation "How your world just got turned upside-down" but I should have called it "How your world just got turned right-side-up" 

Needless to say I am enamored with the benefits and straight forwardness of the MVC framework.  For some reason, it clicks quite well for me.  I'm still learning and experiencing its benefits but so far so good.

Here is the presentation and video demos that I presented today:

Technorati Tags: ,

As you may have read in my previous post on Rick, WPF, and Google Reader, I have created an open source project (Google Reader Desktop) that will notify a user of new reader items in their Google Reader account.

Well, with that, I am using WPF for the first time and trying to handle some common problems.  While searching for an answer to a recent question, I was not able to find one quickly.  So I figured, I'd post the answer here.

First the problem:

I have a WPF application that when it starts up, does an action that takes a long time to execute.  I'd prefer to not hold the user back from interacting with my application while this process is executing.  I'd like process it asynchronously and then update the UI when it's complete.

Here's an example UI:

image

You can see I have a button and a label.  The idea is to update my label after the async action that the button kicks off completes.

Subsequent problems:

My initial thought was to solve the problem like this:

namespace MyAsyncWPFApp
{
    /// <summary>
    ///
Interaction logic for Window1.xaml
   
/// </summary>
   
public partial class Window1
   
{
        public Window1()
        {
            InitializeComponent();
        }

        private void btnAction_Click(object sender, RoutedEventArgs e)
        {
            MyActionTaker taker = new MyActionTaker();
            AsyncCallback asyncCallback = taker.HighTimeDurationMethod;
            //Make an Asynchronous Call
            asyncCallback.BeginInvoke(null, RefreshUI, null);
            lblStatus.Content = "Started Long Method";
        }

        private void RefreshUI(IAsyncResult ar)
        {
            lblStatus.Content = "Finished Long Method";
        }
    }

    public class MyActionTaker
   
{
        public void HighTimeDurationMethod(IAsyncResult ar)
        {
            Thread.Sleep(10000);
        }
    }
}

The result of this was the following: (InvalidOperationException: "The calling thread cannot access this object because a different thread owns it."

image

The solution:

I changed the implementation of the RefreshUI method to be the following:

private void RefreshUI(IAsyncResult ar)
{
    Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                       (DispatcherOperationCallback) delegate(object arg)
                                                         {
                                                             lblStatus.Content = "Finished Long Method";
                                                             return null;
                                                         }, null);
}

If you want to leverage my last post on lambda expressions:

private void RefreshUI(IAsyncResult ar)
{
    Dispatcher.BeginInvoke(DispatcherPriority.Normal,
             (DispatcherOperationCallback) (arg =>
             {
                 lblStatus.Content = "Finished Long Method";
                 return null;
             }), null);
}

The Dispatcher object from the instance of the window keeps track of the "owner" thread and tells it to make the change I'm requesting.

This morning I started the day with a single goal: "Grok lambda expressions in C#."  The lambda is that funny "=>" phrase you see in advanced code that you gloss over thinking it will go away at some point and you'll be able to get back to your standard way of programming.  Well I don't think it's going away and it's time to get on board.  I started with the biggest tie-in with lambdas that I was aware of, LINQ.  Well that was too big and complicated to truly understand lambda expressions explicitly.  So I decided to take a step back and just focus on the basis for the lambda expression, anonymous methods declared inline in an easier way to present the function.  Here's the anonymous method I started out with:

</PRE< P>

image 

Anonymous methods are an easy way to get into lambda expressions.  It seems like a natural progression.  The explicitly identified anonymous method above is easy to read.  We have a new delegate instance that has to conform to the "del" delegate so we know it will return an integer and take two integers as parameters.  Then the delegate instance has a straight forward way of expressing its implementation "return x*y".  Since we are assigning the delegate instance to a local variable "myDel", we know that when we call "myDel(5, 6)" later it will execute the "return x * y" where x is 5 and y is 6.

Now if we were to express the functionality above as a lambda expression, it would look like this:

image 

Note the differences.  The explicit anonymous method declares an inline delegate that takes two integers  and returns the product of those integers.  The lambda edition of the same logic should read as "x and y go into x * y".  That's how you read the yellow highlighted section of code.  The result of that whole highlighted part is assigned to the "myDel" variable.  Because of this we know that the result is a delegate that conforms to the "del" delegate type.  Because of this we know that x and y are the inputs and therefore are implicitly typed as integers.  We also know that when myDel(x, y) is called later we will return the result of x * y.  In this case we call myDel(5, 6) and we'll get the result of 30.

Just to break it down a little bit more.  Consider the following:

image

The lambda expression is the operator that splits the phrase.  The left side is the list of parameters; the right side is the implementation of functionality.  You can consider the entire phrase to be an entity in of itself.  Therefore the result can be assigned to a variable of a delegate type as long as the lambda'd phrase follows the signature of the delegate you are assigning it to.  We know above that the "del" delegate returns an integer and takes two integers as parameters.  For this reason, we can assign the lambda expression to a variable of the delegate "del".

I attended a presentation by Chris Long today about JQuery and its advantages to web developers.  I must say that it is a truly amazing framework. 

Some takeaways from the meeting:

  • JQuery is awesome
  • JQuery makes javascript fun to work with
  • JQuery (and its related plug-ins) make a site interactive and useable

If you develop on the web and haven't started using JQuery, you should consider it.  For more information on JQuery take a look at their website.

Here are some links to the presentation:

My Problem (specifically with RSS Reading...):

Recently, I switched over to Google Reader as an RSS feed reader.  The interface is just about as good as I could expect for a web application.  My biggest issue with it is that I completely forget about it and I quickly amass hundreds of unread items.  Typically if I get over 100 items that are unread, I will just mark them all as read and start over hoping that I didn't miss anything critical.  Over the past two weeks, I have done this about 10 times.  Unfortunately, I know there are things I am missing out on.  Before Google Reader, I was using Microsoft Outlook 2007.  The Interface was exactly what I need.  I typically have Microsoft Outlook running and up at all times.  Outlook reports how many items I have unread and I usually catch up every few hours so that I can spend a reasonable amount of broken up time reading through my feeds.  The problem was that I would occasionally mess something up and my feeds would quit updating without me knowing.  I figured this out when I realized I hadn't read a post from the GU in over 3 months.

My Solution:

I did a quick search and couldn't find an easy to use app that would announce my new unread blog post in a way that I thought was convenient.  I supposed I didn't spend very much time searching because subconsciously I wanted to create my own little application that would do this for me. 

While searching, I did happen to stumble upon a .Net API Wrapper for the Google Reader API on CodePlex called GReader.  Simply stated, this helps me do some RAD to get my new application off the ground. 

What I did was created a quick WPF Application that leverages the GReader library to pull down a user's reader account and display the number unread items for each subscription.  I have called this new application "Google Reader Desktop" but I'm guessing that there are some copyright issues there and I'll have to eventually change it.  Here are a few screen shots:

The login page:

image

The main Page:

image

The notification mechanism:

image

Stay tuned for more updates in coming weeks!

Help Me:

If you're interested in participating in a sweet little application, let me know.  I have a few tasks out on the CodePlex project and you can help me get this thing written and stable.

Yes, I know that 3.5 isn't very new but for some people it is some stuff that they haven't seen.  I put together a presentation that touched *briefly* on the most of the new features of the .Net 3.5 language and new features in Visual Studio 2008.  I promised to publish the content here so here ya go.

I uploaded the demos and Power Point to my Skydrive here:

Technorati Tags: ,,

I recently answered a question to a colleague that deserves its own blog posting.  The question simply stated is:

I have two webservices that share types:

webSvc1 at http://myServer/WS/webSvc1.asmx
webSvc2 at http://myServer/WS/webSvc2.asmx

When I generate the proxy for these two services I use:

wsdl /sharetypes http://myServer/WS/webSvc1.asmx http://myServer/WS/webSvc2.asmx /appsettingurlkey: MyOrgNamespace.MyAppName URL /n:MyOrgNS.Proxy /o:"C:\MyWebApp\App_Code\MyProxy.cs" /l:CS

The problem is that the appsettingurlkey is the same for each service
in the proxy file. I want to be able to specify multiple
appsettingurlkey parameters. How is this accomplished. I figure
since the /sharetypes parameter became available, there should be a
solution for specifying the appsettingurlkey specifically for each
service identified

As it turns out, I asked this question on a forum over a year ago and never got a response. I eventually figured it out but got lazy and didn't respond to my own post with the answer.  Here's the answer:

The command line wsdl command doesn't allow for this explicitly.  However, you can use a properties file to make this work. 

Here is the XML Parameter file


0:  <wsdlParameters xmlns="http://microsoft.com/webReference/">
1:   <nologo>true</nologo>
2:   <parsableerrors>true</parsableerrors>
3:   <sharetypes>true</sharetypes>
4:   <language>CS</language>
5:   <namespace>MyOrgNS.Proxy</namespace>
6:   <documents>
7:   <document>http://myServer/WS/webSvc1.asmx?WSDL</document>
8:   <document>http://myServer/WS/webSvc2.asmx?WSDL</document>
9:   </documents>
10:   <appSettingUrlKey>MyOrgNamespace.MyAppName</appSettingUrlKey>
11:   <appSettingBaseUrl>http://myServer/WS/</appSettingBaseUrl>
12:   <out>C:\MyPath\Proxy.cs</out>
13:  </wsdlParameters>
</PRE< P>

 

Here is the WSDL Command:

"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\WSDL" /Parameters:{ENTER_PATH_TO_ABOVE_XML_FILE}"

The important part to note is that each web service starts off with http://myServer/WS/... in the properties XML file.  Then the appSettingBaseURL is "http://myServer/WS/".  Finally, note that the app Setting URL Key is specified as MyOrgNamespace.MyAppName.  In your client's app or web.config file, you'll need to add <add key="MyOrgNS.Proxy" value="http://devServer/SomeURL/"/>  The .cs file that is generated from running the WSDL tool will replace "http://myServer/WS/" with "http://devServer/SomeURL/" before making the http request to the actual service.

Technorati Tags: ,,

I just read this post from Justin Etheredge about strategies for becoming a better developer:

CodeThinked | What is your strategy for becoming a better developer?

Self improvement and mentoring others to improve is one of my strongest passions right now.  I think that Justin's two recommendations would also be my first recommendations for being a better developer.  These are "Emulate" and "Get Involved".  I'd also like to add "Read" and "Stretch".

Read.  This pertains to blogs, articles, and books.  Subscribe to RSS feeds, magazines and commit to a reading list.  These resources are extremely valuable in extending your breadth and depth in a particular technology.  I commit at least 1 hour of my day to reading interesting things.  Most of the time, they have nothing to do with my exact job at hand but at the very least gives me perspective into successful people's habits.  CodeThinked is one of over 100 blogs that I subscribe to.  One tip here: Actually SUBSCRIBE!  Here are some instructions by Jeff Blankenburg.  This will create a virtual Todo list that you can follow.  If you don't subscribe it's very easy to let your day job get in the way of investing in your profession. 

Stretch. By this I mean set goals that push the limits of your comfort.  One area of comfort that I was not ready to move into yet was speaking publicly.  When I was younger, I had a severe stuttering problem.  It was difficult for me to hold conversations with people; even those close to me.  Through two years of speech therapy sessions and some significant confidence boosting activities, I overcame that shortcoming and was able to hold conversations and even group discussions occasionally.  It was a big stretch goal of mine to give a public presentation a few weeks ago at the Kentucky Day of .Net.  But it was an enormous growth experience.  Find those things that you have no comfort with and become comfortable.  Specific to programming: if you are a .Net developer, check out f# and become proficient.  Learn some Ruby well enough to share it with others. 

Continue this list of recommendations and extend Justin Etheredge's non-meme.

 

Starting July 1st, I've been working with a great team of developers, a wonderful design firm, and a superb client to create a public store front for Stanley Steemer.  The effort from an implementation stand point took 6 developers about 12 weeks to get up and running.  It was a lot of work in a short period of time.  I thought I'd share some of our issues during the development process and how we solved them.

First though, I'd like to thank a few people publicly first. 

  • Jeremiah was a great tech lead and took ownership of the project to mentor and deliver some great implementations. 
  • Raju took detail-oriented to a new level.  His CSS and design implementation made the entire thing possible
  • Chris was a powerhouse of delivery constantly producing features in record time.  The timeframe was short and Chris was a big reason for success
  • John is a JQuery/javascript master.  Much of the site's functionality is because he took ownership and made very difficult logic work
  • Stanley's development team really stepped it up and put together a good architecture for the back end.  Working with legacy code isn't always easy but they delivered what seemed to be impossible items quickly.
  • HGA produced a killer design and worked interactively with the development team throughout the entire development process.

Here's a snapshot of the site:

image

Some stuff we did well:

Communication

This project would have failed miserably if everyone wasn't on the same page during the development process.  Communication was key.  We leveraged a WSS site for discussions, bug tracking, resource links and documentation.  The site was free, easy to setup, and a breeze to use but technical and non-technical people alike.

Iterative Development

We broke our deliverables out by week.  The rules for the HMB team were as follows: 1.) You pick your work 2.) Your work has to be done by the end of the week 3.) If your work isn't done by the end of the week, you have to work the weekend to get it done by Monday at 8:00 am

User Demo's

In this case, we treated HGA (our design partner) as our user.  Every week on Tuesday afternoon, we would walk over to their office and show them what we did the previous week.  The meeting would start off with the list of corrections from the previous week.  Next we would cover all the new pages/features.  Finally we would list our commitment for the next meeting.  This was received very well and this level of organization was probably our most valuable asset for the short turn around.

Visibility

We leveraged several features of Team Foundation Server (TFS) to produce reports for our task assignments, bug rates, and project progression.  This let HMB's management staff know exactly how things were going at any time they wanted.  We also set up an automated build to a server for internal viewing of hour-by-hour progress.  If someone in the office had a free 20 minutes, we had an additional 20 minutes of QA testing.

Some stuff we changed in line:

Communication

Yes, this continually changed throughout the process.  Some communication worked really well.  We tried to use Instant messenger to communicate with other team members.  This turned out to be less efficient.  Toward the end of the project, we used the phone a lot more.  It was easier and more efficient to hold a conversation this way

PDF->HTML

Getting multiple browsers to work the same with CSS is a nightmare.  They render differently.  While it would be wonderful to have a single rendering engine, the truth of the matter is that we don't and we probably never will.  Get over it. Design firms need to be flexible and Development shops need to work very hard to identify problems ahead of time.  Work with every browser available and identify and minimize the differences.

Conclusion

We had a lot of fun on this project and look forward to enhancements in the near future.  It was a great experience and I'm lucky to be part of such a great team.  If anyone has any questions about process, our implementation, or ideas for new features, feel free to contact me.  My information is on this blog.

 

I was recently asked by a coworker when the COALMG meeting was.  This spawned an interesting conversation about how to find out when these community events are scheduled.  I'm in no way claiming to be the community expert here, just a participant.  Here are the meetings I know about:

If there are more groups in Columbus that should be added, please add them as a comment.