This was a great article about a large scale commercial product and the tools and techniques used to manage it.
https://www.drdobbs.com/tools/building-quickbooks-how-intuit-manages-1/
This was a great article about a large scale commercial product and the tools and techniques used to manage it.
https://www.drdobbs.com/tools/building-quickbooks-how-intuit-manages-1/
Sometimes you hit smack in to a runtime exception that requires a weekend off to get your head straight again to tackle come Monday morning. That was my experience today, as I wrangled with an unexpected exception when doing something I’d done plenty of times before.
Our app has the following structure:
We have a build script that copies the latest version of the Business Logic assembly in to the /bin directory of the Web Application, since that app does not reference the assembly directly.
It has been fairly routine for us, when adding or extending functionality, to add methods to our Interfaces library, implement the corresponding method in the Business Logic library, then use that method in our Web app. But this time around, even after clean builds, we’d get a runtime error when the Unity framework would try to initialize.
A bit of searching online revealed that this error occurs often when you’re not looking at the most recent version of an assembly that is implementing the Interface, and so to the Framework, it appears that the implementation is missing, even though your compiler will run clean.
As a step to make sure that there were no residual versions of previously built assemblies, I went through Windows Explorer to purge the /bin directories. Something caught my eye as I was looking at the /bin directory for the Business Logic library – an extra subdirectory names ‘x86’. In this directory were the Debug and Release subdirectories, and then the new build of the assembly.
So, it appeared the problem was that our build script was not in fact getting the latest version of our assembly since it was in a different (unexpected) location.
The x86 name was a clue to look at the Configuration Manager in Visual Studio. Sure enough, somehow the Business Logic project got set explicitly to x86 rather than ‘Any CPU’.
I changed the target platform for that project, did a new clean and rebuild, and this time through, the app loaded up without error.
Thankfully I didn’t spend an unrecoverable amount of time trying to sort this out, but I still thought it may be helpful to record for others who run in to that error and, as I did, mistakenly believe that nothing has changed to trigger the new runtime exception.
Sometimes it’s the little things that drive you mad.
We got a report from a customer following a SharePoint 2007 to 2010 upgrade that their Blog site was showing too many posts, and they wanted to filter it by category. That’s a simple enough request, right?
In 2007, the user explained, she’d Edit the Page, Edit Web Part, then click on the ‘Edit the current view’ to get the ability to set the filter criteria. However, in 2010, the ‘Edit the current view’ link never appeared.
I set off to confirm what she was seeing.
In my 2010 development lab, I created a new site using the Blog site template.
As advertised, the default view of the site showed the ‘Posts’ web part showing all the approved posts from the blog. I added a few other posts, and set one of the categories to be called ‘Announcements’.
So, as the user did, I went to Edit the web part.
Sure enough, the ‘Edit the current view’ was notably absent.
I was able to get the link to s how up, by changing the Selected View, clicking ‘Apply’, then re-selecting ‘<Summary View>’ and clicking ‘Apply’ again.
However, when I clicked on the link, I got a whole lot of nothing.
So, on to plan B as it was evident this was not to be done through the Browser UI. I launched SharePoint Designer and loaded up the Blog site.
Then clicked on ‘Edit site home page’ to load up the web part page. There was my Posts web part.
By selecting the Web Part, I got a ‘List View Tools’ ribbon with a nice big ‘Filter’ button on it.
Clicking the Filter button brings up the ‘Filter Criteria’ dialog, where I could add my category filters.
After adding the additional criteria, the Posts web part showed the filtered list of entries.
Save the page in SharePoint Designer, which will automatically publish the changes to the server.
Now, when I go back to the Blog site, I see the filtered list of entries.
Following a recent SharePoint 2007 to 2010 upgrade, we got a report of an RSS Viewer that was not displaying any content.
The message shown was “The requested RSS feed could not be displayed. Please verify the settings and url for this feed. If this problem persists, please contact your administrator.”
After confirming for myself, I checked the feed that the RSS Viewer was pulling, and found it was from the Cisco support forums at https://supportforums.cisco.com/community/feeds/video?community=2004.
Next we checked the SharePoint Logs to find the following entry:
04/02/2012 10:17:05.24 w3wp.exe (0x4610) 0x3D3C SharePoint Portal Server Web Parts 8imh High RssWebPart: Exception handed to HandleRuntimeException.HandleException System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. —> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure. at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRe… 193b14f8-f282-438d-bf91-36bb7c640d03
A corresponding entry in the Event log was also a clue.
An operation failed because the following certificate has validation errors:\n\nSubject Name: CN=supportforums.cisco.com, OU=Communications and Collaboration Team, O=Cisco Systems, L=San Jose, S=CALIFORNIA, C=US\nIssuer Name: CN=VeriSign Class 3 Secure Server CA – G3, OU=Terms of use at https://www.verisign.com/rpa (c)10, OU=VeriSign Trust Network, O=”VeriSign, Inc.”, C=US\nThumbprint: CAF5027FDDE630D4AC3FFB1000FC2E09B18249A3\n\nErrors:\n\n The root of the certificate chain is not a trusted root authority..
What was going on?
The Cisco site had a chain of SSL certificates that was 3 layers deep.
As the RSS Viewer attempted to connect to this location, it connects as the SharePoint service, not as a browser. SharePoint then tried to travel up the certificate chain to confirm the authenticity of each layer. When it got to the intermediate certificate, it choked, not able to validate it as a legitimately trusted source.
How do we fix it?
In order for SharePoint to recognize the Verisign certificates chained together and used by the Cisco site, we need to explicitly tell SharePoint they are trustworthy. Thankfully, there is a simple to use UI as part of Central Administration where we can do just that.
First, log in to Central Administration, then click on the ‘Security’ menu item.
Then, select ‘Manage Trust’ from the ‘General Security’ section.
Before we can add the Verisign certificates as trusted relationships, we have to retrieve them from the Verisign website. All of Verisigns root and secondary certificates can be found at https://www.verisign.com/support/roots.html
By examining the certificate details in the Browser, we can determine which root certificate to download and add to SharePoint. In our case, there needed root was:
Root 3
VeriSign Class 3 Primary CA – G5
Description: This root CA is the root used for VeriSign Extended validation Certificates and should be included in root stores. During Q4 2010 this root will also be the primary root used for all VeriSign SSL and Code Signing certificates.
Download the Root Certificate file.
Now, add the Trust Relationship to SharePoint
After that certificate is in place, you can return to the page with the RSS Viewer and confirm it is able to retrieve the results.
If not, then there may be additional certificates in the chain that you would need to retrieve and add to SharePoint.
The Trust Relationships in SharePoint are also used when calling out to an external web service from a web part.
Thanks to https://blog.mattsampson.net/index.php/calling-a-webservice-over-ssl-in-sharepoint-ssl?blog=1 for helping guide the way.
A few weeks ago I applied for a grant offered by a local Venture Capital firm. The grant application is essentially an abbreviated business plan, and finalists compete for several awards.
Today I received my rejection letter. Complete with the classic “we regret to inform you” clause.
However, they attached a remarkably polished PDF analysis of my application compared to the 183 other submissions.
The analysis gave me a unique insight to my own idea-making. Here was an objective evaluation of my idea (related to offering HomeSpot in a unique way to home improvement companies) and some direct feedback from people who look at entrepreneurial ideas for a living.
Across the seven scoring categories, our application performed above average in all seven. This is more clearly seen in graphical form.
I assume, but do not know for sure, that the selected finalists exceeded some established threshold for their total score. So, while our application was 30 points off of the maximum score, it may have only be 10 points off of the threshold. I’ll never know.
Here is some of the feedback from the reviewers:
This is an interesting service, but it feels like an ultra specialized solution. It is addressing a real need, but it is another website that consumers need to log into. It is not unique and it is very difficult to differentiate. Ultimately the success will obviously depend on execution.
What I take from this is the validation that we are addressing a real need. Finding a solution for a existing problem is key to success as an entrepreneur. I agree fully with the reviewer here that execution will be the determining factor on our success.
Great platform with promising customer feedback. I am wondering, however, what the long term competetive response and market growth will be. How are you planning to grow your platform outside of local handymans? What is your growth strategy serving as an anonymous service provider?
Again, affirmation on the product idea itself and the feedback we have received already. But the challenge is put forth – how do we grow, scale and sustain ourselves beyond our initial markets? The third review also shared this concern:
The problem, market, and technology are all very clearly presented. It is difficult to see how this really scales to a company with significant revenue…
In the eyes of a Venture Capitalist, “significant revenue” has lots of zeroes following it. For me as the entrepreneur, my standards of significance are no doubt different. My definition for success may well come in being able to first hit “insignificant revenue” having started with “zero revenue”. But for the reviewer, and the investor alike, the criteria for growth and scale are well understood.
The last reviewer was the most critical.
I think it’s good that there’s a competitor, but I’m slightly concerned that your product (as described) appears to be very similar, yet you describe your product as “revolutionary”. Honestly, this hurt the credibility a bit, at least in my eyes. If successful, there are likely to be other revenue stream opportunities. I’m not sure if you considered any, as they’re not included in the proposal. You indicated that the product is already on the market, but that you have no sales and don’t expect any for 12 months. Why? Also, pricing was not indicated.
This reveals much to me about how we presented ourselves in the application. We obviously (at least in this reviewer’s eyes) lacked differentiation and clarity on our current status and future growth. Our exclusion of other revenue streams was not because we are not keenly aware of them, but had to choose carefully our statements in the limited format of the application. Questions about our sales efforts and pricing are also in our minds constantly, but we chose not to put them forth in the application.
What is important is that these things that I deem to be secondary or even trivial are clearly not thought of the same way by the reviewer.
All told, I am encouraged by this feedback. It was a solid helping of affirmation, with some key calls to address the perceived challenges in a product we have yet to fully bring to market. I am motivated to prove these skeptics wrong, execute, achieve significant revenue, and capture all the opportunity before me.
In the ongoing development roadmap for HomeSpot HQ is a simple item: Create a Mobile Optimized Site. By itself, it is a pretty straightforward task. We designed the HomeSpot HQ site for a 1024×768 browser window. And while most of the modern mobile devices will render this site satisfactorily, there is definitely something about a truly optimized browsing experience when using the scaled down browser on an iPhone or (in my case ) Droid Incredible.
Web or Native
Our first strategic decision has been to focus first on an optimized website in lieu of a native mobile app. There are plenty of reasons for leading with this approach:
As HomeSpot is an ASP.NET MVC application, I was able to use some guidance from Scott Hanselman about having a parallel set of Views for the mobile browser set that run alongside the default set of Views for the traditional browser set. This approach allowed me to use my existing Controllers and (with a few exceptions) reuse the Models without modification. Compared to rewriting in Java or learning Objective C to target their respective device platforms, this approach represented the fastest path to mobile coverage.
Split or Common Site
The other choice I made was to keep the mobile version and desktop version of the site under the same Url. There are several pros and cons to this approach, and there may in fact be some ramifications I will have to deal with down the road. So, the user experience will be such that if you view the site on a recognized mobile device, you’ll be served the mobile optimized Views, otherwise you’ll get the normal desktop Views. The Url won’t change between the two versions.
The advantages of this approach, so far as I have thought about them, include
However, there are some trade-offs:
Mobile Web Framework
The final decision I chose to make was picking a mobile optimization framework. I looked at iui and jquery mobile primarily, and decided to go with jquery Mobile. While it is still emerging from an alpha stage, it appears to be meeting my expectations so far. I’ll create additional posts with more specific commentary on this platform.
The Mobile Optimized HomeSpot site is still under development and initial testing. Given the limited time afforded to me to contribute to my own side-hustle, I hesitate to even offer a ship date. Still, it has been a good exercise to weigh out the various options for reaching a mobilized audience.

On this 3-day weekend, I found myself with a few spare cycles I don’t normally have.
But by default, it seemed, I used those cycles reading and consuming content from the web.
It occurred to me, that I could have been using those moments to create. To add a feature to HomeSpotHQ.com. To rework one of the broken reports from work. To make a smoothie even.
Does Creation always require more energy than Consumption? Why is the inertia to get towards Creation so high, but the path to Consumption so well paved?
And more critically, how do I maintain a mindset of Creation, while keeping idle Consumption at bay?
Amazon recently announced the release of their Simple Email Service for use by developers. In doing so, Amazon opens up a pay-as-you-go email sending mechanism that is tailored for application developers.
Sending system generated email messages has always proven to be a challenge for developers. It’s not for lack of means to do so, it’s dealing with a multitude of anti-spam safeguards imposed by ISPs and hosting providers. Some block outbound sending altogether, and many throttle the number of messages that can be send per day/hour/minute.
Amazon’s SES provides a great deal of infrastructure, and uses a variety of proven methods to help ensure deliverability of your message. Their quota system is dynamic, so the more you prove your messages are legitimate, the more you can send.
Setting up your SES account.
If you already have an Amazon Web Services account, adding on the Simple Email Service is pretty straightforward. You’ll get a confirmation email from Amazon to click through and activate the service. Initially, you’ll be set up in a Sandbox, and there is a process for requesting Production Access.
Getting your Access Keys
After you have enabled the service, you’ll need a set of credentials to use it. Again, if you already have an AWS account, you’ve probably got your Access Keys set up already. Like any credentials, keep them safe and secure. If someone were to gain access to your AWS keys, they could send email through SES without your knowledge.
Verifying an email address.
Before you can send outbound messages through SES, you have to verify the source email address. Amazon provides a small collection of scripts used to communicate via command line to the SES services. Follow the Getting Started guide’s instruction to prepare a file containing your AWS Access Keys and verify a sending address. SES will generate a response email to the address you are verifying, within which is a link you’ll have to click in order to complete the verification.
Downloading the Amazon Web Services API.
Amazon offers a couple of methods for leveraging the SES API. You can use the scripts downloaded to verify your source address to also send messages. I chose, however, to use their packaged .NET SDK library. It contains wrappers for all of Amazon’s Web Services, including the SES.
After downloading and unpacking the SDK, you can add a reference to the AWSSDK.dll assembly to your project.
Using the SES API methods.
Creating and sending email via the SDK then becomes a matter of setting up the outbound SES message object and sending it through the API. The following method takes a standard .NET MailMessage object and translates it to a SES message, then sends it along.
Public Function SendMessage(ByVal message As System.Net.Mail.MailMessage) As String Implements Core.DataInterfaces.IMailServer.SendMessage
If String.IsNullOrEmpty(_accessKey) Or String.IsNullOrEmpty(_secretKey) Then Throw New Exception("API Credentials are required to use this provider.")
Dim ses As New AmazonSimpleEmailServiceClient(_accessKey, _secretKey)
Dim messageToSend As New Amazon.SimpleEmail.Model.SendEmailRequest
'set up addresses
messageToSend.Destination = New Amazon.SimpleEmail.Model.Destination
For Each toAddress In message.To
messageToSend.Destination.ToAddresses.Add(toAddress.Address)
Next
For Each ccAddress In message.CC
messageToSend.Destination.CcAddresses.Add(ccAddress.Address)
Next
For Each bcAddress In message.Bcc
messageToSend.Destination.BccAddresses.Add(bcAddress.Address)
Next
'set reply to
If message.ReplyTo IsNot Nothing Then
messageToSend.ReplyToAddresses.Add(message.ReplyTo.Address)
End If
'set subject line
messageToSend.Message = New Amazon.SimpleEmail.Model.Message
messageToSend.Message.Subject = New Amazon.SimpleEmail.Model.Content().WithData(message.Subject)
'set message body
If message.AlternateViews.Count > 0 Then
Dim messageBody As New Amazon.SimpleEmail.Model.Body()
For Each view In message.AlternateViews
Dim viewStream = view.ContentStream
Dim viewData(viewStream.Length) As Byte
Dim viewContent As String = System.Text.Encoding.ASCII.GetString(viewData, 0, viewStream.Read(viewData, 0, viewData.Length))
If view.ContentType.MediaType.Equals("text/html") Then
messageBody.Html = New Amazon.SimpleEmail.Model.Content(viewContent)
Else
messageBody.Text = New Amazon.SimpleEmail.Model.Content(viewContent)
End If
Next
messageToSend.Message.Body = messageBody
Else
messageToSend.Message.Body = New Amazon.SimpleEmail.Model.Body(New Amazon.SimpleEmail.Model.Content(message.Body))
End If
'set from address
messageToSend.Source = message.From.Address.ToString
'send message
Dim sendResponse As Amazon.SimpleEmail.Model.SendEmailResponse
sendResponse = ses.SendEmail(messageToSend)
Return sendResponse.SendEmailResult.MessageId
End Function
End Class
Lessons Learned
A few things I learned to keep in mind:
Amazon’s service is easy to use, economical, and capable. I probably won’t replace every outbound message instance with SES, but definitely for cases where I need to generate larger batches (such as monthly newletters or maintenance reminders) I will leverage SES.
In this third installment of my Favorite Extension methods series, I will show how to quickly evaluate a string to determine if it is the string representation of a Guid.
I came upon the need for this method because I am using ASP.NET MVC for an application that uses a Guid to identify a record. In a case where my controller method is to retrieve a record, the controller’s parameter is a string.
<Extension()> _
Public Function IsGuid(ByVal value as String) As Boolean
If String.IsNullOrEmpty(value) Then
Return False
Else
Try
Dim guid As New Guid(value)
Return True
Catch Ex As Exception
Return False
End Try
End Function
Using this extension method, I can ensure that a string represents a Guid and I won’t encounter any errors when trying to Cast that value into a Guid.
If Not recordGuid.IsGuid Then Throw New ArgumentException("RecordGuid must contain a Guid string.")
Public Shared Function HtmlEncode(ByVal value As String) As String
Dim context As HttpContext = System.Web.HttpContext.Current
If Not context Is Nothing Then
Dim Server As HttpServerUtility = context.Server
If value Is Nothing OrElse Trim(value) = "" Then
Return "{none}"
Else
Dim sText As String = Server.HtmlEncode(value)
Dim sCRLF As String = vbCrLf
sText = Replace(sText, sCRLF, "<br>")
Return sText
End If
Else
Throw New Exception("This function must be called from an ASP.Net application.")
End If
End Function
Public Shared Function HtmlEncode(ByVal value As String, ByVal mapEmptyTo As String) As String
Dim context As HttpContext = System.Web.HttpContext.Current
If Not context Is Nothing Then
Dim Server As HttpServerUtility = context.Server
If value Is Nothing OrElse Trim(value) = "" Then
Return mapEmptyTo
Else
Dim sText As String = Server.HtmlEncode(value)
Dim sCRLF As String = vbCrLf
sText = Replace(sText, sCRLF, "<br>")
Return sText
End If
Else
Throw New Exception("This function must be called from an ASP.Net application.")
End If
End Function
<Extension()> _
Public Function HtmlEncode(ByVal value As String) As String
Return Functions.HtmlEncode(value, "{none}")
End Function
<Extension()> _
Public Function HtmlEncode(ByVal value As String, ByVal mapEmptyTo As String) As String
Return Functions.HtmlEncode(value, mapEmptyTo)
End Function