Jeff Townes' Blog
My Links
Blog Stats
  • Posts - 9
  • Stories - 0
  • Comments - 8
  • Trackbacks - 3
Archives

Friday, July 11, 2008

Wednesday, January 02, 2008

Count us in!  We just registered a team to participate in the www.WeAreMicrosoft.com charity challenge weekend on January 18-20.  It's a great opportunity to serve charities in our community using skills we know well.

We hope you'll join, too!

posted @ 11:19 PM | Feedback (0)

Wednesday, December 12, 2007

I have been working recently with SQL Server 2005 Reporting Services to display dollar sums and volume sums, and I’m happy to report [I couldn’t resist] that I’ve found a neat trick for formatting non-currency negative numbers. 

Our client requested that we apply the following formatting rules to report figures:

·         Use parenthesis instead of a minus sign to display negative values

·         Display no decimals and format numbers with a comma when they exceed 999

·         Display the currency sign for financial figures

These are seemingly simple requirements to accomplish with standard .NET format strings.  First, setting the Format property of the SSRS textbox (or other control) to C0 [c-zero] will format numbers as currency with no decimal places.  This format will also automatically add parenthesis around negative numbers:

o   $999 or $1,000 for positive dollar figures

o   ($900) or ($1,000) for negative dollar figures

Unfortunately, none of the easy-bake format strings for numeric values appeared to automatically display parenthesis for negative numbers.  I tried N0 [n-zero], G0 [g-zero], D0 [d-zero] and various other combinations.  The answer was to use a custom format string instead.

In order to format numeric, non-currency values to use parenthesis when displaying negative numbers, set the Format property of the SSRS textbox to “#,0;(#,0)” (and omit the quotation marks).  Problem solved!

Finally, if you’re looking to add a bit extra, format negative numbers to display in red font instead of black by adding this expression to the Color property of the textbox: 

=IIf([Expression to Evaluate] >= 0, "Black", "Red")

Or, in my case, the specific formula was:

=IIf(SUM(Fields!AmountBilled.Value) >= 0, "Black", "Red")

Happy Reporting!
posted @ 9:21 PM | Feedback (3)

Tuesday, September 11, 2007

I’ve finally learned my lesson about setting default values for C# Enumerates – always set them, because bad stuff happens when you don’t. 

Our team built a web application that communicated with a business logic tier using WCF services.  The design allowed us to utilize the same business and data retrieval logic across multiple client interfaces, returning Data Contracts to each interface, instead of scattering our logic enterprise-wide.  Everything was working well… until we moved the application to Production.

After moving to Production, we began receiving an ugly, non-descript error message in our user interface that “an existing connection was forcibly closed by the remote host,” and we chased it for hours before we found the problem.  First, we verified that we could communicate (authenticate and exchange information) with our WCF tier.  Success.  Next, we verified that our data schemas were the same in DEV and PROD.  They were.  Then, we checked for any problems with our user interface.  None found.  Finally, in a desperation move, I changed our database connection string to point to the development database server… and suddenly the application worked without errors… but re-pointing the connection string to production data caused the error to resurface.  I was puzzled.

Finally, our first clue came to us when we checked the XML log file created by WCF.  First, it logged a “Failed to send response message over HTTP” error, which was followed by an error message giving us the real error:

<Message>There was an error while trying to serialize parameter http://tempuri.org/:[WcfOperationContractName]. The InnerException message was 'Enum value '0' is invalid for type '[Client].[Application].Entity.[EnumerateType]' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.'.  Please see InnerException for more details.Message>       

It turns out that the stored procedure feeding data to this service returned some nullable columns of data, including the enumerate value, and this column happened to be NULL in Production but not in Development.  So, when WCF attempted to serialize the Data Contract and deliver it to the interface, it failed.  Unfortunately, the user interface did not receive a friendly message, but at least the information was in the WCF server logs.

In order to prevent this problem, I made two code modifications.  First, I included an “Unknown” Enum Member in my enumerate with a numeric value of 0:

[DataContract]

public enum SampleEnumerateType

{

[EnumMember] Unknown = 0,

[EnumMember] High = 1,

[EnumMember] Medium = 2,

[EnumMember] Low = 3

}

Next, I added a default value to the property where this enumerate was used:

private SampleEnumerateType _status = SampleEnumerateType.Unknown;

[DataMember]

public SampleEnumerateType Status

{

get { return _status; }

set { _status = value; }

}

And with that, the problem vanished.  Our user interface correctly displayed its data – including a row with a status value of “Unknown” – and the application was ready for primetime.

posted @ 12:48 PM | Feedback (0)

Monday, August 27, 2007

I just read on Chris Koenig's blog that the next BarCampDallas event is scheduled for Saturday, September 29:  https://barcamp.pbwiki.com/BarCampDallas-4?doneSave=1.  There was a good buzz around the last event, and I'm looking forward to experiencing this one myself.  See you there!

posted @ 8:50 AM | Feedback (0)

Sunday, August 26, 2007

Houston Techfest was held on Saturday, August 25 at the University of Houston, and it was a great success for HDNUG and the event organizers.  Brad Abrams flew in from Seattle for the keynote, and he and I had a great conversation late-morning about the Cider tools for creating XAML-based applications in Visual Studio 2005 and the future in VS 2008.

Speaking of VS 2008, I saw two new features which look very promising and immediately valuable to our clients.  First, there’s a new type of database project – not to be confused with the db projects released with .NET 1.0 – that look like a great way to finally manage and deploy database schema changes as part of an automated build process.  The demo only touched on them briefly, but I’m going to look around on Scott Guthrie’s blog to see if I can learn more.

Second, it looks like Microsoft heard me groan when I learned that there’s not a built-in web interface to invoke WCF services.  With ASMX, I could launch a service, type in any required parameters (assuming they were not complex types), and then click the Invoke button.  With WCF, this was not possible, so basic testing became a slight bit harder because now I had to setup a unit test project and adjust my configurations appropriately so that I could establish a connection for testing.  Visual Studio 2008 (and the corresponding release of the .NET 3.5 framework) have tools that will address this need.  Specifically, there’s a service host executable that will enable you to quickly host a WCF service without setting up lots of configurations, and there’s a corresponding service client executable that will then allow you invoke the hosted WCF services.  The interface feels almost exactly like the ASMX interface for invoking services, and the results display in a very readable format so that I don’t have to comb through XML.  While this isn’t an enterprise hosting solution, it will certainly make setting up a Hello World services example much quicker.

Finally, I gave a presentation on Building Content Managed Websites Using ASP.NET 2.0 (the DotNetNuke counterpart).  The presentation covered master pages, navigation, security, and web parts, and the demo compared these technologies to the features available with the DNN portal.  Click this link to download my presentation and source code:  http://media.parivedasolutions.com/Public/HoustonTechFest/.

Thanks again to the event organizers.  Great job!

posted @ 7:56 PM | Feedback (0)

Monday, May 14, 2007

I am currently working with a team to build a large, distributed point-of-sale application for a national flight services company using WPF and WCF.  We’ve been making great progress on the software dev side, but lately we’ve encountered a few hardware troubles and tricks that I thought I should pass along…

Background

Our first hardware challenge was supporting MagTek USB credit card swipe blocks in a terminal services environment.  We were (and are) going to support terminal services operations as an alternative to local application installation, but the swipe block wasn’t cooperating. 

Swipes emulate keyboard input, so in theory the swipes should look identical regardless of whether the software is local or on a terminal server.  But, as we like to say,

                object reality != theory.InUse(environment);

Issue

We swiped the same credit card on a local machine and terminal server, but the results were different.

Local Machine Test

This was the correct swipe, and it was what all of the swipes should look like.  Incidentally, I’ve altered the swipes AND used a test-only credit card, so no devious purchases for you, folks. 

%B4716150001669044^BAKER/GREGORY ^0108XXXX000000767000000?;471615000166XXXX=...

Terminal Server Test

The terminal server was not just wrong – it was also inconsistent.  Two swipes resulted in two different character strings.

Swipe 1

5b$7161500016690446bakEr/grEgory 60109XXXX000000767000000/;471615000166XXXX=...

Swipe 2

%b47161500016690446baker/gregORy 60109XXXX000000767000000/;471615000166XXXX=...

It’s easy to see the differences between these swipes and the first (local machine) swipe.  Most notably, Swipe #1 has the wrong character at the beginning of the string.  Then, you’ll notice a missing ^ character and some inconsistencies in the name capitalization of the cardholder name on both swipes.

Resolution

The resolution is fairly simply yet obscure. 

When you connect to the terminal server (or remote desktop session), click Options, navigate to the Local Resources tab, and set the “Apply Windows key combinations” setting to “On the local computer” instead of the default “In full screen mode only”.  Thanks to Nathan Caneday for finding this one!

Final Terminal Server Test

After toggling this setting, here was the resultant swipe, a perfect match…

%B4716150001669044^BAKER/GREGORY ^0109XXXX000000767000000?;471615000166XXXX=...

Needle in the haystack.

posted @ 2:06 PM | Feedback (2)

Tuesday, April 24, 2007

Dallas Code Camp was held on Saturday, April 21 at Microsoft's offices in Irving, and the event was a great success.  The event had strong attendance, and the presenters were educational and entertaining... or, as my wife reminds me... as entertaining as a group of developers can be.

Brian Orrell presented on SharePoint Mash-ups, and I gave a presentation on Building Content Managed Websites Using ASP.NET 2.0 (the DotNetNuke counterpart).  The presentation covered master pages, navigation, security, and web parts, and the demo compared these technologies to the features available with the DNN portal.  Click these links to download my presentation and source code.

Kudos to the Dallas Code Camp team for organizing a successful event.  I look forward to next year!

posted @ 8:56 PM | Feedback (0)

Monday, August 28, 2006

Recently, I developed an ASP.NET 2.0 web application and discovered that the LoginStatus control does not clear Session on Logout.

Situation:
I used an ASP.NET 2.0 LoginStatus control in a Master page to provide users with an easy way to login / logout of a system.  The system performed many functions, and (against my own better judgment) I used Session to store user-specific search criteria. 

Problem:
Midway through the project, I noticed that this Session information was not clearing itself when a user logged out of the system.  I confirmed by logging in as "User 1", setting the Session value via a search, logging out, and subsequently logggin in as "User 2."  User 2 was able to view the search criteria entered by User 1 -- definitely NOT a desired behavior.

Cause:
After reflecting the ASP.NET 2 code, I discovered that the LoginStatus control does not clear Session when a Logout occurs.  The control does perform a FormsAuthentication.Signout(), and it clears the Response with a status code of 200.  But, it does not clear Session.

Solution:
The fix was simple.  I added an event handler to my LoginStatus control and wrote the code myself:

Master Page:
<asp:LoginStatus ID="LoginStatus1" runat="server" LogoutAction="RedirectToLoginPage" OnLoggedOut="LoginStatus1_LoggedOut" />

Master Page Code-Beside:
protected void LoginStatus1_LoggedOut(object sender, EventArgs
e)
{   
      Session.Abandon();
}

So, the lesson for me was to not take these new controls for granted.  They are easy to use, and they certainly simplify development, but it's important to unit test and ensure that each control achieves the result I expect.

posted @ 2:14 PM | Feedback (6)
Jeff Townes