Archive for Development
Southern Maryland Give Camp – What a Blast!
Posted by: | CommentsLast weekend I was at the Southern Maryland Give Camp which really was an event not to be missed. In one weekend we designed and built a system to track and report on all of the services provided by the Tri-County Youth Services Bureau (TCYSB), an organization that provides important help to youth and families in Maryland. Their key goal was to automate the reporting they needed to do to the various state agencies and grant providers that otherwise took about a man year of effort to assemble by hand.
Held in the really beautiful St. Mary’s College of Maryland (a state school – who knew!) we set about building system to track all of the people TCYSB provides services to, all of the services that were provided, and then provide the data back out to satisfy the various reporting requirements. To get a feel for the complexity of the system, here’s the entity model:
When you have less than two days, it really focuses you on what’s important. For the most part we stuck with technologies we either knew or were willing to risk everything figuring out. We built the system using Entity Framework 4 (Model First), ASP.NET WebForms, and DevExpress Reporting. This was my first time using EF4 on a complete application, and it worked out amazingly well. Frankly, compared to the prototypes I did on EF1 they have really come a long way. Naturally we used DevExpress reporting not just because I know it (I know SSRS as well) but because ease of deployment is a big concern when you’re handing off a bunch of files to a customer with just this side of no IT support. Like a few vendors, DevExpress offered free licenses to the non profit organizations for solutions developed at the Give Camp.
Another thing that acquitted itself well was TFS – we had everyone on the team using our TFS server (since it was readily accessible and everyone had the client installed) and despite the high odds of merge hell it all came off without a hitch. Frankly, no one was more surprised than me.
At high noon on Sunday, 41 hours after the kickoff, we backed away from the source code, did a final check in and went into the group room for wrap up. Every team demonstrated what they built for their non-profit which was something to see. The results ranged from redesigned web sites to real line of business applications like what we did. Technologies spanned the range as well, with Microsoft pretty well represented as well as some interesting uses for Google Docs and Google Calendar.
What made it all work was behind the scenes – for me the biggest piece were the outstanding requirements documents we got prepared by Ann Scharpf before we got there. Combined with round-the-clock access to both the TCYSB staff and Ann we never had to guess at what we were trying to deliver. Frankly, I’ve never worked with a better BA than her and it made all of the difference.
Everything we might ask for was right there – more food than could be eaten, more caffeinated drinks than could be drunk, and roving specialists in design and technologies (a big shout out to Steve Michelotti for helping me with EF questions).
Finally, we had Jim Pendarvis doing his best impression of R Lee Ermey. When he says coding is over at high noon, coding is over at high noon! I can’t imagine how much work he personally had to put into making this happen.
If you have the chance, I really encourage you to check out a Give Camp near you. It’s a great experience to build something completely in a weekend that will make a huge difference for people. Regardless of your level of tech skill or even if you’re a designer, analyst or even (gasp) a program manager you can make a difference. Give it a shot!
CodeCamp NYC 2011.1 – Country Mouse in the City
Posted by: | CommentsSo I grew up in the small town of Fort Dodge Iowa, and let me tell you – I never expected to be walking around New York City having a great time. But, I knew any community that has Rachel Appel hanging around all the time would be at the very least uniquely fun, and most likely a great event. Let me tell you, it didn’t disappoint! It was great to walk around NYC and discover everything from clean cabs (seriously – and you could play football in the back of those things) to a bagpiper on Union Square to this thing:
Believe it or not, it’s registered as both a plane and a car. I wouldn’t want to bring either into the city!
I had a packed group for my presentation, so if you skipped out on the full room (I’m lookin’ at you, Gary!) here are the slides:
You can also find them on the CodeCampNYC site.
Enabling JSON Compression (and Gibraltar) in Windows Azure
Posted by: | CommentsA friend of mine posted to Twitter a bit ago that he was having trouble dealing with HttpCompression on Windows Azure. Specifically, only certain default MimeTypes were being compressed (like ASPX and CSS), while other important ones like JSON and SOAP were not.
During another Azure project, I also ran into an issue where logins stopped working after upgrading to Azure OS 2.X Azure SDK 1.3. It turns out that there is a bug in that release that doesn’t allow configuration inheritance for the MachineKey, and the workaround was to manipulate the server configuration in the RoleEntryPoint.
Since I’m already having to manipulate the server config to synchronize the MachineKey settings, I thought I’d whip up some code real quick to solve this problem during the same process, using the httpConpression topic on IIS.net as a guide.
If you don’t already have a RoleEntryPoint in your app… well, you should. Copy the code below into a new class file in your main application, and add a reference to Microsoft.Web.Administration.dll, as specified here. You’ll also notice Gibraltar-specific code peppered throughout… this is all that you need to get Gibraltar working on Windows Azure (as long as you’re also using the tip from my previous post as well).
(The code is long, and it’s in VB… because that’s the language this particular app was in. If you need it converted to C#, you can do so here.
UPDATE: My colleage Kendall pointed out that the role event handlers should be declared at the very beginning, and that, even though the RoleInstance’s OnStart event is called on a separate thread from the main app, it should still run the WarmUp loop on a separate thread, so that the function can return MyBase.OnStart() and exit properly. Good call.
Imports System.Linq
Imports Microsoft.WindowsAzure.Diagnostics
Imports Microsoft.WindowsAzure.ServiceRuntime
Imports Microsoft.Web.Administration
Imports System.Threading
Namespace Fon.Apps
Public Class WebRole Inherits RoleEntryPoint
Public Overrides Function OnStart() As Boolean
' For information on handling configuration changes
' see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
AddHandler RoleEnvironment.Changing, AddressOf RoleEnvironment_Changing
AddHandler RoleEnvironment.Stopping, AddressOf RoleEnvironment_Stopping
Gibraltar.Agent.Log.SendSessionsOnExit = True
Using server As New ServerManager()
'Cycle through the sites and set the MachineKey for each one.
For Each site In server.Sites
Dim siteConfig = site.GetWebConfiguration()
'Get the appSettings section
Dim appSettings = siteConfig.GetSection("appSettings").GetCollection().ToDictionary(Function(e) DirectCast(e("key"), String), Function(e) DirectCast(e("value"), String))
'Reconfigure the machine key
Dim machineKeySection = siteConfig.GetSection("system.web/machineKey")
machineKeySection.SetAttributeValue("validationKey", appSettings("validationKey"))
machineKeySection.SetAttributeValue("validation", appSettings("validation"))
machineKeySection.SetAttributeValue("decryptionKey", appSettings("decryptionKey"))
machineKeySection.SetAttributeValue("decryption", appSettings("decryption"))
Next
'Turn on compression for JSON and SOAP.
Dim config As Configuration = server.GetApplicationHostConfiguration()
Dim httpCompressionSection As ConfigurationSection = config.GetSection("system.webServer/httpCompression")
Dim dynamicTypesCollection As ConfigurationElementCollection = httpCompressionSection.GetCollection("dynamicTypes")
Dim e1 As ConfigurationElement = dynamicTypesCollection.CreateElement("add")
e1("mimeType") = "application/json"
e1("enabled") = True
dynamicTypesCollection.AddAt(0, e1)
Dim e2 As ConfigurationElement = dynamicTypesCollection.CreateElement("add")
e2("mimeType") = "application/json;charset=utf-8"
e2("enabled") = True
dynamicTypesCollection.AddAt(0, e2)
Dim e3 As ConfigurationElement = dynamicTypesCollection.CreateElement("add")
e3("mimeType") = "application/soap+xml"
e3("enabled") = True
dynamicTypesCollection.AddAt(0, e3)
server.CommitChanges()
End Using
'Poor man's Application Warm-up here
Tasks.Task.Factory.StartNew(Sub()
Try
While (True)
Trace.WriteLine("Warming up web site...")
Dim webClient As New Net.WebClient()
webClient.DownloadString("http://mysite.com/WarmUp.ashx?WarmUp=True")
Thread.Sleep(TimeSpan.FromMinutes(9))
End While
Catch ex As Exception
Gibraltar.Agent.Log.RecordException(ex, "WindowsAzure.WebRole.Startup", True)
End Try
End Sub)
Return MyBase.OnStart()
End Function
Private Sub RoleEnvironment_Stopping(sender As Object, e As RoleEnvironmentStoppingEventArgs)
Gibraltar.Agent.Log.EndSession(Gibraltar.Agent.SessionStatus.Normal, "Azure's configuration settings have changed.")
End Sub
Private Sub RoleEnvironment_Changing(sender As Object, e As RoleEnvironmentChangingEventArgs)
' If a configuration setting is changing
If e.Changes.Any(Function(change) TypeOf change Is RoleEnvironmentConfigurationSettingChange) Then
' Set e.Cancel to true to restart this role instance
Gibraltar.Agent.Log.EndSession(Gibraltar.Agent.SessionStatus.Normal, "Azure's configuration settings have changed.")
e.Cancel = True
End If
End Sub
End Class
End Namespace
You might have noticed the While loop that cycles every 9 minutes and makes a request to a specific website. Though the actual site details have been abstracted out, this is a trick that I use to keep my application “warmed up,” and is a variation on the technique used by Christian Weyer.
For the MachineKey part, you’ll also need to add the following entries to the appSettings section of each of the web.configs in your Role, being sure to replace your values where appropriate:
<add key="decryption" value="Auto" /> <add key="decryptionKey" value="YOURVALUEHERE" /> <add key="validation" value="SHA1" /> <add key="validationKey" value="YOURVALUEHERE" />
You’ll also notice that it’s also pretty easy to add additional MimeTypes to compress. Just continue to copy the pattern for any of the items you think are missing. Be sure not to add ones that don’t already exist, or you’ll likely crash your role.
Anyways, I I hope that helps some of you that are trying to resolve various Azure issues.
Have You Sampled Our Code Samples Yet?
Posted by: | CommentsOne of the great things about coming to work for Gibraltar is learning about all of these things that I didn’t know the product could do. For example, the other day, I was asked in one of our Live Support chats about how to see the details of a web site session in progress.
Gibraltar collects a wealth of information about your running website. However, by default, you can’t analyze the data until the web server process completes. I knew that live monitoring is one of the killer features slated for Gibraltar 3.0, but I didn’t realize that there are also very simple, workable ways to get Gibraltar data anytime you need it within the current Gibraltar 2.5 release.
As a former Gibraltar customer, when I wanted to get this data in the past, I simply recycled the AppDomain myself. I had Gibraltar configured to “autoSendSessions”, so whenever I recycled the AppPool, I’d automatically receive the latest logs. I realize that is not the best answer for a number of reasons, but it is what worked for me, so I passed that suggesion to the customer.
A little later, our fearless leader Jay messaged me and asked why I hadn’t sent him the link to the Code Samples page, which shows how to make Gibraltar immediately send the package for the current session whenever an error is logged. Feeling a little sheepish, I admitted “Because I didn’t know we had that feature.”
It turns out, we have some pretty cool samples that do a lot of very useful things. If you haven’t had a chance to check them out yet, you should. This also got me thinking about some ways we can make our samples more visible and accessible. Stay tuned for some cool web site updates in the coming weeks.
Before I go, I wanted to suggest a slight tweak to the “Submitting Sessions on Error” sample I just pointed you to. In .NET 3.5 and later (4.0 for you VBers out there), you can take advantage of Lambda Expressions to simplify this call a little bit. The version I use looks like this:
protected void Application_Start()
{
Log.MessageAlert += (sender, e) =>
{
if (e.TopSeverity <= LogMessageSeverity.Error)
{
e.SendSession = true;
e.MinimumDelay = new TimeSpan(0, 5, 0);
}
};
}
Or for the VB folk:
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs) AddHandler Log.MessageAlert, Sub(sender1 As Object, e1 As LogMessageAlertEventArgs) If (e1.TopSeverity <= LogMessageSeverity.Error) Then e1.SendSession = True e1.MinimumDelay = New TimeSpan(0, 5, 0) End If End Sub End Sub
This is simply some neat syntactical sugar that IMO makes your code a bit easier to read. Instead of having to follow the event handler to another method, you can see how the event is handled right there, without another method signature clogging up your code. Under the covers, the compiler will create the signature as an anonymous method, and sort everything out for you. Neat, huh?
I learn something new every day around here. Hope this little tidbit makes you more productive.





