Author: Derek

  • System.TypeLoadException: Method does not have an exception

    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:

    • Interfaces assembly
    • Business Logic assembly (where interfaces are implemented)
    • Web Application (where Interface and Business Logic are married using the Unity Framework)

    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.

  • Filtering the SharePoint 2010 Blog Posts web part

    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.

  • Add root certificate as trusted source in SharePoint 2010

    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.

    1. A root certificate
    2. An intermediate or secondary certificate
    3. A site certificate

    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.

  • Rejected but encouraged

    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.

  • Override ASP.NET Membership Password Generation rules

    I am a real fan of the ASP.NET Membership system as a way to deliver a basic account management and log in mechanism to a web application.  I have used it in both ASP.NET and ASP.NET MVC applications, using both SQL and Active Directory as the backing identity store.

    One nuance of the Membership provider when using SQL is how it generates new passwords when the user requests their password be reset.  By default, the generated password is a whopping 14 characters in length, with no clear way to adjust the format.  (The MSDN page for SqlMembershipProvider.ResetPassword describes this behavior.)

    Thankfully, it is fairly easy to create a new MembershipProvider and override the GeneratePassword method with your own rules.

    First, we’ll create a new class that inherits SqlMembershipProvider.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace MyNamespace
    {
    public class MyMembershipProvider:System.Web.Security.SqlMembershipProvider
    {
    
    public MyMembershipProvider()
    : base()
    { }
    
    }

    Then we’ll override the GeneratePassword() method to use our own rules for creating a new password value.  In this case we assemble an 8 character string of upper and lower case letters, numbers, and a few symbols.

    public override string GeneratePassword()
    {
        string newRandomPassword = string.Empty;
        int passwordLength = 8;
        Random random = new Random();
    
        while (newRandomPassword.Length != passwordLength )
        {
            int randomNumber = random.Next(48, 122);
            if (randomNumber != 95 && randomNumber != 96)
                newRandomPassword += Convert.ToChar(randomNumber);
        }
    
        return newRandomPassword;
    }

    Next, we need to update the web.config file to define our new class as a provider for the Membership system.

    <membership defaultProvider="MySqlProvider">
    <providers>
    <add name="MySqlProvider" type="MyNamespace.MyMembershipProvider" connectionStringName="MyConnectionString" applicationName="My Application" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" maxInvalidPasswordAttempts="1000" passwordAttemptWindow="5" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" />
    
    </providers>
    
    </membership>

    Finally, we tell the included PasswordRecovery control to use our provider class, using the name specified in the web.config entry.

    <asp:PasswordRecovery ID="PasswordRecoveryControl" runat="server" Width="385px" UserNameLabelText="" OnSendingMail="PasswordRecoveryControl_SendingMail" MembershipProvider="MySqlProvider"
    OnUserLookupError="ShowPasswordRecoveryError" UserNameInstructionText="Enter your Email Address to receive your password">
    </asp:PasswordRecovery>

    This is a great testimony to the Provider pattern as a way to quickly reconfigure a system.

  • Picking a Mobile Web Strategy

    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:

    • the ability to leverage our existing code base vs. managing multiple code lines per device
    • broader device audience vs. per device versioning
    • avoiding deployment channels (and cost) via AppStore or Android Market

    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

    • easier deployment process with only one site to manage
    • unified Google Analytics

    However, there are some trade-offs:

    • lack of distinct Url such as “m.homespothq.com”
    • inability to easily deploy code fixes just to mobile site independent of main site
    • trickier to allow mobile users to view the non-mobile site if they so choose.

    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.

  • Unable to start debugging on the web server.

    This morning I got the following error when trying to run a project in Visual Studio 2010.

    After a bit of digging, I found that IIS was not running on my PC.  I tried using iisreset but it did not start up.

    A system reboot was all it took to get IIS cleared up and started without any exceptions.  I will note that a Windows Update had just occurred the night before.

  • Incoming Tabular Data Stream Incorrect

    This morning my team fielded an error we had not seen before in a production site.  When performing a lookup, the following exception bubbled up:

    The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect.  Too many parameters were provided in this RPC request.  The maximum is 2100.

    Upon investigation, we found that a Linq query using the .Contains() clause was the culprit.

    It appears that Entity Framework was translating the .Contains() clause to a WHERE x IN () when setting up the SQL SELECT statement to run.  In our case, we had done a retrieval of records first, then passed that list into the Contains.  It worked fine until the list exceeded 2100 entries.

    We were able to just refactor our lookup to eliminate the .Contains() clause.

    Part of what made this an unusual case was that even in production, this system had run for 2 years without any issues.  But as the number of records grew through the system’s use, it was only a matter of time before we exceeded that boundary imposed by SQL Server.

  • Creating or Consuming

    Creating or Consuming

    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?

  • SSMS Tools Pack Works for Me

    Today a co-worker of mine introduced me to a great add on to Microsoft’s SQL Server Management Studio (SSMS).  It’s simply called the SSMS Tools Pack and is a free download from https://www.ssmstoolspack.com/

    The product is a collection of ‘a few upgrades to the SSMS IDE that I thought were missing” according to the author.  These features include:

    • SQL Snippets
    • Window Connection Coloring
    • Window Content History, Query Execution History and Current Window History
    • Format SQL
    • Search Table, View or Database Data
    • Run one script on multiple databases
    • Copy execution plan bitmaps to clipboard or file
    • Search Results in Grid Mode
    • Generate Insert statements from resultsets, tables or databases
    • Regions and Debug sections
    • Running custom scripts from Object Explorer
    • CRUD (Create, Read, Update, Delete) stored procedure generation
    • New query template
    • General Options

    The particular feature I needed was to Generate Insert statements from an existing table – particularly when dealing with partial synchronizing between two copies of the same database, such as a Dev and Staging or Production environment.

    I’ve added SSMS Tools Pack to all of my systems now, and is definitely one product I want to promote.