At work we came across an interesting issue while storing all dates in Microsoft SQL Server database in UTC time. We're going to allow users from different time zones to use the app and the UTC time will need to be translated to their time zone off of UTC. However, this week we were scratching our heads trying to figure out how to get Entity Framework 4 to default our database results as UTC. We are using MVC and doing Ajax data calls to a view which resturns data as javascript, and under the covers uses the Javascript serializer. Not knowing that the date is already in UTC time, the serializer attempts to convert it to UTC based on the timezone the system is in (Pacific Standard Time in our case). The issue is resolved if you do the following to any DateTime object before you pass it off for serialization:

CreatedDate = DateTime.SpecifyKind(CreatedDate, DateTimeKind.Utc);

At issue is that by default, Entity Framework is setting the DateTimeKind property to "Unspecified", and Javascript Serializer (as well as I think things like RIA services) decides that it probably isn't in UTC. The issue has been discussed before: http://www.west-wind.com/weblog/posts/471402.aspx

It was impractical for my team to remember to set this property every single time for all of our database dates, there could be hundreds. Instead, we'd like to force Entity Framework to initialize dates with DateTimeKind.Utc set. Entity Framework uses an .edmx file to generate a code file (something.designer.cs). Inside that file you'll see that DateTime fields are created as so:

 

        /// 
        /// No Metadata Documentation available.
        /// 
        [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
        [DataMemberAttribute()]
        public global::System.DateTime CreatedDate
        {
            get
            {
                return _CreatedDate;
            }
            set
            {
                OnCreatedDateChanging(value);
                ReportPropertyChanging("CreatedDate");
    		    _CreatedDate = StructuralObject.SetValidValue(value);
    		    ReportPropertyChanged("CreatedDate");
                OnCreatedDateChanged();
            }
        }
        private global::System.DateTime _CreatedDate;
        partial void OnCreatedDateChanging(global::System.DateTime value);
        partial void OnCreatedDateChanged();

What we'd like to do is add the following lines of code to each DateTime property class:

if(_CreatedDate == new DateTime())
{
     _CreatedDate = StructuralObject.SetValidValue(value);
     _CreatedDate = DateTime.SpecifyKind(_CreatedDate, DateTimeKind.Utc);               
}
else
{
    _CreatedDate = StructuralObject.SetValidValue(value);
}

OR a very similar addition for nullable DateTime objects that checks for null and passes the value if it exists:

 

if(_DeletedDate == new DateTime())
{
    _DeletedDate = StructuralObject.SetValidValue(value);
    				
    if(value != null)
    	_DeletedDate = DateTime.SpecifyKind(_DeletedDate.Value, DateTimeKind.Utc);
}
else
{
    _DeletedDate = StructuralObject.SetValidValue(value);
}

Since these classes get auto-generated every time there is a change in your .edmx class, the best way I've found to do this is to use a T4 template (.tt) transform to add this functionality. Here are the steps you'll need to take to put this in to practice:

1) If you don't already have it, from Visual Studio go to "Tools" -> "Extension Manager" and download "tangible T4 Editor". After you've installed, restart Visual Studio to get snytax highlighting.

2) Go to your .edmx file and right-click on any empty space and select "Add Code Generation Item..."

3) In the "Add New Item" dialog, select "ADO.NET Entity Object Generator"

4) Open the new .TT file is and search for the "WritePrimitiveTypeProperty" method is. This is where the magic is going to happen. We're going to add additional rules so that all DateTime and nullable DateTime objects get initialized specified as UTC.

 

5) Find the line: ReportPropertyChanging("<#=primitiveProperty.Name#>"); *for me this was line 599

Replace what is currently between the "ReportPropertyChanging" and the "ReportPropertyChanged" method callbacks the following. This adds the additional UTC DateTimeKind setting step if the property is a DateTime:

<#+ if( ((PrimitiveType)primitiveProperty.TypeUsage.EdmType).PrimitiveTypeKind == PrimitiveTypeKind.DateTime)
			{
#>
			if(<#=code.FieldName(primitiveProperty)#> == new DateTime())
			{
				<#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
<#+ 
				if(ef.IsNullable(primitiveProperty))
				{  
#>				
				if(value != null)
					<#=code.FieldName(primitiveProperty)#> = DateTime.SpecifyKind(<#=code.FieldName(primitiveProperty)#>.Value, DateTimeKind.Utc);
<#+ 			} 
				else
				{#>
				<#=code.FieldName(primitiveProperty)#> = DateTime.SpecifyKind(<#=code.FieldName(primitiveProperty)#>, DateTimeKind.Utc);				
<#+ 
				} 
#>
			}
			else
			{
				<#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
			}
<#+ 
			}
			else
			{
#>
		<#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
<#+ 
			}
#>

 

That's it! In total, the following is my entire "WritePrimitiveTypeProperty":

////////
//////// Write PrimitiveType Properties.
////////
private void WritePrimitiveTypeProperty(EdmProperty primitiveProperty, CodeGenerationTools code)
{
MetadataTools ef =
new MetadataTools(this);
#>

/// <summary>
/// <#=SummaryComment(primitiveProperty)#>
/// </summary><#=LongDescriptionCommentElement(primitiveProperty, 1)#>
[EdmScalarPropertyAttribute(EntityKeyProperty=<#=code.CreateLiteral(ef.IsKey(primitiveProperty))#>, IsNullable=<#=code.CreateLiteral(ef.IsNullable(primitiveProperty))#>)]
[DataMemberAttribute()]
<#=code.SpaceAfter(NewModifier(primitiveProperty))#><#=Accessibility.ForProperty(primitiveProperty)#> <#=code.Escape(primitiveProperty.TypeUsage)#> <#=code.Escape(primitiveProperty)#>
{
<#=code.SpaceAfter(Accessibility.ForGetter(primitiveProperty))#>get
{
<#+ if (ef.ClrType(primitiveProperty.TypeUsage) == typeof(byte[]))
{
#>
return StructuralObject.GetValidValue(<#=code.FieldName(primitiveProperty)#>);
<#+
}
else
{
#>
return <#=code.FieldName(primitiveProperty)#>;
<#+
}
#>
}
<#=code.SpaceAfter(Accessibility.ForSetter((primitiveProperty)))#>set
{
<#+
if (ef.IsKey(primitiveProperty))
{
if (ef.ClrType(primitiveProperty.TypeUsage) == typeof(byte[]))
{
#>
if (!StructuralObject.BinaryEquals(<#=code.FieldName(primitiveProperty)#>, value))
<#+
}
else
{
#>
if (<#=code.FieldName(primitiveProperty)#> != value)
<#+
}
#>
{
<#+
PushIndent(CodeRegion.GetIndent(
1));
}
#>
<#=ChangingMethodName(primitiveProperty)#>(value);
ReportPropertyChanging(
"<#=primitiveProperty.Name#>");

<#+ if( ((PrimitiveType)primitiveProperty.TypeUsage.EdmType).PrimitiveTypeKind == PrimitiveTypeKind.DateTime)
{
#>
if(<#=code.FieldName(primitiveProperty)#> == new DateTime())
{
<#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
<#+
if(ef.IsNullable(primitiveProperty))
{
#>
if(value != null)
<#=code.FieldName(primitiveProperty)#> = DateTime.SpecifyKind(<#=code.FieldName(primitiveProperty)#>.Value, DateTimeKind.Utc);
<#+ }
else
{
#>
<#=code.FieldName(primitiveProperty)#> = DateTime.SpecifyKind(<#=code.FieldName(primitiveProperty)#>, DateTimeKind.Utc);
<#+
}
#>
}
else
{
<#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
}
<#+
}
else
{
#>
<#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
<#+
}
#>

ReportPropertyChanged(
"<#=primitiveProperty.Name#>");
<#=ChangedMethodName(primitiveProperty)#>();
<#+
if (ef.IsKey(primitiveProperty))
{
PopIndent();
#>
}
<#+
}
#>
}
}
private <#=code.Escape(primitiveProperty.TypeUsage)#> <#=code.FieldName(primitiveProperty)#><#=code.StringBefore(" = ", code.CreateLiteral(primitiveProperty.DefaultValue))#>;
partial void <#=ChangingMethodName(primitiveProperty)#>(<#=code.Escape(primitiveProperty.TypeUsage)#> value);
partial void <#=ChangedMethodName(primitiveProperty)#>();
<#+
}

 

 

 

 

 

Part of the reason I choose C# for larger web projects, and a big reason I point to when people ask me about my tech preferences is the nice, clean, managed strongly-typed objects. "I want to know if I'm using my variables correctly at compile time, not after users start getting errors". Is this short sided of me? Am I being a code-purist, or prude?

About 6 months ago I started to let my guard down. There was a really great article written by Alexandra Rusina in the February 2011 issue of MSDN that gives you the C# skinny on var, dynamic, and object:

Understanding the Dynamic Keyword in C# http://msdn.microsoft.com/en-us/magazine/gg598922.aspx

Having read that, I get the difference, but why do I want to dance around without the fences? Why treat the standard int the same I would a string / value pair? It's chaos. It's all "var", it's groovy, right? No. What is this, PHP?

My "ah ha" moment was a couple weeks ago at the Mix11 conference in Las Vegas. I do a lot of Facebook development, and a lot of pulling my hair out because of the world of pain that is Facebook development. With facebook, you can get at user data using their old REST apis, their FQL queries, FQL multi-queries, and now their Graph APIs (and GraphAPIs with queries). The strongly typed control freak in me was declaring objects like "FriendLinks", "Friend", "FamilyConnection", "PhotoTag", etc. It got out of control. At Mix, I was really eager to hear from the creator of one of the C# libraries for Facebook, Jim Zimmerman about the status of his library, Facebook C# SDK. If you do Facebook development I highly recommend watching his talk in its entirety: http://channel9.msdn.com/Events/MIX/MIX11/OPN06 

What struck me the most of Jim's talk is that Jim feels my pain. For as much as Facebook can give a developer, they hide it in cracks and corners of their API. Sometimes you have to call their Graph API, get a result, then call an FQL query. Sometimes the result changes with new data because they've introduced a new feature. Deprecation of older APIs is quick. It's a very dynamic API. Which is exactly what led Jim to create the SDK the way he did. "I'm not writing a wrapper API around Facebook", he says with absolute conviction. I don't blame him. Instead, this SDK gives developers the tools we need.

I decided to give it a whirl. Here's the easy one, the Graph API for getting "me" (this user):

var client = new FacebookWebClient();

dynamic me = client.Get("me");
ViewBag.Name = me.name;
ViewBag.Id = me.id;

Nice! Now, no matter what Facebook adds to the "user" object, I can take advantage of it. if they added a profile property favorite_candy, it's just me.favorite_candy, and I've got it implemented. OK, but I might not mind adding a property to a Facebook.User object. So this is kinda cool, but I'm not totally sold.

Next, I'm going to commit to start poking around at some of the FQL (Facebook Query Language) tables I can query: http://developers.facebook.com/docs/reference/fql/, specifically, I want to query for all the photos I am tagged in from the photo_tag table: http://developers.facebook.com/docs/reference/fql/photo_tag/

var query0 = "SELECT pid FROM photo_tag WHERE subject=me()"; //photos I am tagged in

try
{
    var result = (IList<object>)client.Query(query0);
}
catch (FacebookApiException ex)
{
    throw;
}

Here's the data just back from Facebook's servers (I'm tagged in 356 photos):

Nice! So, I can make up queries and get back dynamic objects. OK, so that's cool, but even these smaller name/value pair type queries STILL hadn't sold me on ditching my safe zone of inteli-sense warm fuziness. Here's the clincher. I want all friends who are tagged with me in photos, and which photo we were tagged, as well as when that tag happened. Yes, you read that correctly. This scenario gave me pause and excitement. I don't want a strongly typed object anymore. Also, I need an FQL Multi-query to make this happen, starting with the query above where I select the photo ids of all the photos I am in. Here's that using the C# SDK:

 

var query0 = "SELECT pid FROM photo_tag WHERE subject=me()"; //photos tagged in
var query1 = "SELECT pid,subject,created,text FROM photo_tag WHERE pid IN (SELECT pid FROM #query0)"; //friends tagged in photos with me
try
{
    var result = (IList<object>)client.Query(query0, query1); //multi-query

    var resultPhotosUserIn = ((IDictionary<string,object>)result[0])["fql_result_set"];
    var resultTagsOfPeopleInPhotos = ((IDictionary<string,object>)result[1])["fql_result_set"];
}
catch (FacebookApiException ex){
     // Note: make sure to handle this exception.
     throw;
}

And here's my new frankenstein object. What's nice is if I didn't qet the FQL query right, or those data fields returned data differently than I expected, I can preview it in the debugger.

This makes a lot of sense now. If you're doing a lot of interesting Facebook queries, dynamic variables are your friends. Jim's approach also makes sense. As the Facebook API changes, he doesn't have to rush to his computer to update wrapper classes that we all have to wait to download.

Oh, and to sweeten the deal, this Facebook C# SDK is available as a NuGet package. Check out the install guides. Using NuGet you can have all this magic in your project in 5 minutes. 

Overview

This isn't a quick read, but I'm attempting to hit quite a few of the decision points I made migrating to Azure. I was skeptical, but as a result I have a nicer site architecture that is extremely scalable. I'm hoping that by laying out these areas where I had to pause and investigate I can better inform you on how to get "in the cloud".

The Scenario

Everyone's got their "big idea". We're gunna be like Mark Zuckerberg, but bigger, and we're going to get there faster. Well, maybe not, but, you probably have a big idea and you're concerned about the scenario that the site gets more traffic than your hardware can manage because of an outside event, the "Oprah effect". A few months ago I launched FoodBusterGame.com for the White House Apps For Healthy Kids contest. I decided to give Azure a try and also to be ready in case we won and a national press release got us that huge spike of users. For you, it might be your next big thing, your twitter or facebook.

So let's run with that, your next big thing gets mentioned on Oprah. Since you had a feeling the diva of TV might for some reason king your site you may done some / all of the following (in order of $$):

Less Scalable / Cheaper:

  • Spoken with your hosting plan about if they can increase the resources to your site
  • Paid for a Virtual Machine (VM) which can have it's resources expanded, to a point
  • Hosted on some VM cloud service like Amazon EC2, where you could deploy more copies of a site but you haven't figured out load balancing
  • Have a dedicated server hosted, and another one in a box ready to be co-located as well.

More Scalable / Expensive:

  • Have an EC2 load balanced setup with multiple VMs for database, web, and maybe a CDN
  • Have a load balancer, a database server and a web server, have rack space for more.
  • Have a server farm, with load balancing ready to go, even while you only have 20 users.

All of these scenarios crossed my mind, and I've heard of a people implementing few other general patterns.

Furthermore, I know how to set up simple load balancing for a scalable website, I've done it at work. You basically want to assume that a client will hit the load balancer, and get Server 1 on a request, but maybe get Server 2 on the second one. Server 2 needs to have access to that user's Session data, so you have to put that session data in a shared space, like the database. Same thing with any files they upload / need to get back; there needs to be some shared storage.

However, most of us don't start out our website projects with this in mind. We do a File -> New Project and let ASP.NET store the session information in memory, and we upload user files to a folder on the hard drive of the server. That's where I started at least, and it has worked for years on small to medium web projects.

My trip to the clouds

I'll admit, last year at PDC09 I was initially a little skeptical of Azure. It seemed too "pie in the sky" (excuse the pun) to rely on, too perscribed / limiting, and too different from my normal Web Server / Database Server combo duo I've gotten used to. However, the more I use Azure, the more it has forced me to modify my project in a way that I could handle the Oprah scenario. I say "forced" because I resisted. I found that while I still had options, the more scalable, better practices began to reveal themselves. Here's how Azure made me scalable:

Step 1 - Trying to get away with the old way - everything on one Azure Web Role VM & SQL Azure

Without much fuss I was able to use the Windows Azure SDK to re-create my site in an Azure Visual Studio project. I put my project up on Azure, my tables copied to SQL Azure using SQL Migration Wizard, bada bing, I'm "in the clounds". It shouldn't be much of a surprise that you can do this because even though you don't have access to it, every Azure instance is a Windows Server VM. In fact soon Microsoft will allow remote access to these (although I'm trying to avoid needing that for simple deployment / re-deployment).

So then I thought "ok, great, I'm in the clouds". BUT, guess what happens when you want to move from 1 instance to 2? Azure adds a load balancer which does round-robin traffic directing like my datacenter example above. A user might be interacting with Server 1 on one request, then Server 2 on another. The problem occurs if I log in on one server, but on the next request I was no longer logged having hit Server 2....

Step 2 - Attempt to put my Session State in the SQL cloud

In the traditional on-site server farm scenario what I'd do is just use the ASP.NET Session State SQL provider and point my web servers to all manage session in a SQL Server database. It's pretty quick and easy. You can build the SQL tables using a single command, and you add a couple lines to your web.config on each server and you're done -- all servers share session data.

My first inclination was to try to do the exact same thing using SQL Azure. Turns out it works, but with one issue. When you do this on a physical SQL server there is a scheduled job that runs every so often to invalidate old / expired sessions. SQL Azure doesn't support timed jobs, and so you'd have to figure out a way to run the "DeleteExpiredSessions" stored procedure regularly, otherwise you'll get people logging in with stale sessions. Here's a blog that suggests you have to create a worker role (another VM type which can run a looped / repeated code): http://blogs.msdn.com/b/sqlazure/archive/2010/08/04/10046103.aspx. This seems like overkill, setting up a full VM instance just to run a command every minute or two. Maybe you could justify it if the worker role had a whole slew of other things it was doing.

My next thought was to try to game the system, keep it all in one VM and somehow run that SP (bad, ugly coding, performance degrading thoughts ensued, I was glad to see that I'm not the only one (see the comments, esp by Michael Lang: http://blogs.msdn.com/b/sqlazure/archive/2010/08/04/10046103.aspx)

Step 3 - Embrace the SessionState in Table Storage

When Azure was first launched there wasn't SQL Azure. The developers asked, and Microsoft responded with a full relational DB in the clouds. The initial thought was that we'd use table storage. That understood, a lot of the common scenarios are worked out nicely to run in TableStorage.  SessionState is one of those.

I found this great blog post that helped walk me through TableStorage: http://www.intertech.com/Blog/post/Session-State-in-Windows-Azure.aspx

As the author points out, you'll need to include the AspProviders project found in the Azure Demos. This will give you the library you need: Microsoft.Samples.ServiceHosting.AspProviders.TableStorageSessionStateProvider 

*Note: I'd like to echo the sentiment that this library should get added to some part of the Azure SDK, in a more permanent namespace because of how important / useful it is.

**Note: I also recommend forking over a few bucks for the Cerebrate Cloud Storage tool to view your Table / Blob storage in Azure. Big time saver.

Step 4 - Make Deploy Fun & Easy

If you use Azure in a continuos production cycle you're going to be deploying a lot. Once you deploy, it takes me about 15 minutes until the whole site is up in "staging". Do yourself a favor and set up Azure deployment in Visual Studio. If you do this right, you click "Publish" and you can walk away and get a snack while your entire site goes up for staging. Here's a great blog post on how to set this up: http://blogs.infragistics.com/blogs/anton_staykov/archive/2010/08/31/how-to-publish-your-windows-azure-application-right-from-visual-studio-2010.aspx

Behold the beauty of right-click, "Publish": 

Step 5 - Blob Storage

Think of blob storage as your high-availability common file area. If a user uploads his / her profile photo, you'd put it here. The best news is that your project automatically has blog storage, and you only page for what you use. I followed this demo on setting up blob and it was pretty easy: http://msdn.microsoft.com/en-us/wazplatformtrainingcourse_exploringwindowsazurestoragevs2010_topic3.aspx

If you just want a quick-fix for saving to and reading from Azure, create a helper class and grab out of that example the following few methods:

  • EnsureContainerNotExists
  • GetContainer
  • SaveFile
  • DeleteFile

(again, use the Cerebrate tools to view the contents)

Step 6 - Set it all up in ServiceConiguration.csfg (and ServiceDefinition.csdef)

You should just be aware that a lot of your cloud settings aren't going in Web.Config. You need to reference your TableStorage account, BlobStorage account, etc in your ServiceConfiguration.csfg (and define these points in ServiceDefinition.csdef).

Conclusion

If you decide to deploy to Azure you've got a lot of options. You'll find your way pretty easily, but your first trip to the clouds is going to be your most memorable. I can safely say that I'm a fan -- the Azure mimics my way of thinking, I just had to find the right tools, samples, and syntax. I love that at any moment I can scale up to 100 instances, and then back down to just 2. Oprah, over here!!!

In a surprise move, Apple has relaxed their restrictions on which tools and languages developers can use to build apps for iPad and iPhone they previously disallowed in section 3.3.1:

"In particular, we are relaxing all restrictions on the development tools used to create iOS apps, as long as the resulting apps do not download any code," Apple said in a statement released to the press. "This should give developers the flexibility they want, while preserving the security we need."

http://arstechnica.com/apple/news/2010/09/apple-relaxes-restrictions-on-ios-app-code-iad-analytics.ars

I'm now intrigued at the propsect of the following code-reuse possibility using the Mono framework in addition to Microsoft C#. With Apple easing this restriction, C# works on:


With all of these tools, the goal is to reuse the functional (backend) code, and use the native UI (user interface) toolsets. For instance, on iPhone you still use Apple's user interface builder, but instead of combining that with backend code in Objective-C, you combine it with C# and the MonoTouch Framework(open-source .NET implementation). Same for Android, you combine it with Android's native UI builder, same with Phone 7. For the web, we use the MVC pattern which keep our functional code separate from our view (presentation code). Moving from the web to phones isn't a 1-to-1 switch, but some of our code could be cut / pasted.



But why C#? Aren't we playing in to the hands of the evil empire? Well, not really. I've said it before, C# is a great language that is as powerful as anything out there but lets developers write fewer lines of code. Like Java, we don't concern ourselves with low-level memory allocation and we get access to a powerful, tried and true tested framework for almost every web, client, server scenario you can find yourself in.


But C# isn't "free" as in "freedom", I hear. Well, more than you'd think. Microsoft released C# in a way that you, I, or for instance, Novell could freely implement the language and it is now a free ECMA standard language: http://port25.technet.com/archive/2009/07/06/the-ecma-c-and-cli-standards.aspx

As Microsoft's release explains it:"Under the Community Promise, Microsoft provides assurance that it will not assert its Necessary Claims against anyone who makes, uses, sells, offers for sale, imports, or distributes any Covered Implementation under any type of development or distribution model, including open-source licensing models such as the LGPL or GPL."

They even went so far as to apply these rules to their MVC framework, ASP.NET MVC.

Most businesses have to pick and choose to support more than one phone, which means a different code base and developer skillset. Web-based mobile apps are one approach, but are limited in capability so sometimes don't fit the need. I hope to see C# grow as a broader solution to cross-platform development.