Tuesday, May 20, 2014

Microsoft CRM 2011: SecurityNegotiationException: A call to SSPI failed

Background

Recently, I was tasked with distributing the architecture of an existing Microsoft Dynamics CRM 2011 environment so that CRM would have a dedicated SQL server.  The original environment had everything running on the same machine.  Over time, the system performance had been steadily declining after the client had added new applications and organizations to CRM.

Problem

After I had installed and configured CRM on Server A and installed and configured SQL with SSRS and Microsoft Dynamics CRM Reporting Extensions for SQL Server on Server B, I opened the CRM web client and began testing to make sure everything was functioning correctly.  I noticed that everything functioned except for SSRS reports that were built using the Report Wizard.  I simply created a test report on the accounts entity and this would fail giving me the generic (rsProcessingAborted) error.

I checked for this error in the Reporting Services logs and found a little more detail:
Microsoft.Crm.CrmException: An unexpected error occurred.
System.ServiceModel.Security.SecurityNegotiationException: A call to SSPI failed, see inner exception.
System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception.
System.ComponentModel.Win32Exception: The target principal name is incorrect ---> Microsoft.Crm.Reporting.DataExtensionShim.Common.ReportExecutionException: An unexpected error occurred. ---> Microsoft.Crm.Reporting.DataExtensionShim.Common.ReportExecutionException: A call to SSPI failed, see inner exception. ---> Microsoft.Crm.Reporting.DataExtensionShim.Common.ReportExecutionException: A call to SSPI failed, see inner exception. ---> Microsoft.Crm.Reporting.DataExtensionShim.Common.ReportExecutionException: The target principal name is incorrect

Solution

The SQL server was missing a HTTP spn that it needs in order to run FetchXML queries from CRM.  I found a great description and solution to the problem here: http://support.microsoft.com/kb/2590774/en-us.

First, I ran the following setspn commands from the SQL server:
setspn -a HTTP/CRMSQLServerName myDomain\CRMAppPoolServiceAccount
setspn -a HTTP/CRMSQLServerFullyQualifiedDomainName myDomain\CRMAppPoolServiceAccount

Then, I set the useAppPoolCredentials value to True for the Microsoft CRM Website on the CRM server.

Tuesday, May 14, 2013

SharePoint 2013 Online App: 403 Response While Downloading Documents from a Document Library

Background

I've been building a lot of SharePoint 2013 Online Apps lately (both provider and SharePoint hosted).  Like most developers, I initially struggled with a few OAuth App Token challenges when trying to persist data between page loads.  And just when I thought I had a good methodology down, I ran into an issue downloading documents from a document library.

I kept receiving a 403 (forbidden) HTTP response code when I attempted to read the file from the document library.  I checked the document library permissions and they were correct.  So, I did some digging online and found others complaining about the issue.

In order to isolate the exact issue, first, I created a document library and uploaded a few PDF documents.  Then, I created a sample SharePoint 2013 App in visual studio.  If you are unfamiliar with the process, here is a good link to get you started: How to: Create a basic provider-hosted app for SharePoint.  In order to limit the scope of this post, I will not cover specifically how I obtained the Microsoft.SharePoint.Client.ClientContext instance in the sample code here.  Please reference the Sources Consulted section below for related reading.

The Original Code

Here was my original sample code I used to isolate the issue:

/// <summary>
/// Downloads a file from a document library and saves it to disk
/// </summary>
/// <param name="context"></param>
/// <param name="fileNameToSaveToDisk"></param>
public void DownloadFileTest(ClientContext context, string fileNameInDocumentLib)
{
    var list = context.Web.Lists.GetByTitle("DocumentLibraryName");
    context.Load(list);
    context.Load(list.RootFolder);
    context.ExecuteQuery();

    string serverRelativeUrl = list.RootFolder.ServerRelativeUrl;
    serverRelativeUrl += "/" + fileNameInDocumentLib;

    // Save file to a temporary location to prove all file contents were received
    string localFilePath = "C:\\Temp\\test.pdf";

    int position = 1;
    int bufferSize = 200000;

    // Open the file
    using (FileInformation fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(context, serverRelativeUrl))
    {
        Byte[] readBuffer = new Byte[bufferSize];
        // code below causes 403 error
        using (System.IO.Stream stream = System.IO.File.Create(localFilePath))
        {
            while (position > 0)
            {
                position = fileInfo.Stream.Read(readBuffer, 0, bufferSize);
                stream.Write(readBuffer, 0, position);
                readBuffer = new Byte[bufferSize];

            }
            fileInfo.Stream.Flush();
            stream.Flush();
        }
    }
}

The problem was stemming from the use of the Microsoft.SharePoint.Client.File.OpenBinaryDirect() method. This is a static method that is supposed to grab the file without having to call the ExecuteQuery() Method. However, since I was using the oAuth App authentication model, this method apparently doesn't pass my app token along like the ExecuteQuery() method does.

After pouring over lots of MSDN documentation, various blogs and asking a friend or two, I modified the code above and it works as expected:

The Working Code

/// <summary>
/// Grab a document from my document library utilizing the Microsoft.SharePoint.Client.File.OpenBinaryStream() method
/// </summary>
/// <param name="context"></param>
/// <param name="fileNameInDocumentLib"></param>
public void DownloadFileTest2(ClientContext context, string fileNameInDocumentLib)
{
    // Find the file by name
    CamlQuery camlQuery = new CamlQuery();
    camlQuery.ViewXml = @"<View>
                            <Query>
                                <Where>
                                <Eq>
                                    <FieldRef Name=""FileLeafRef"" />
                                    <Value Type=""Text"">" + fileNameInDocumentLib + @"</Value>
                                </Eq>
                                </Where>
                                </Query>
                            </View>";

    List list = context.Web.Lists.GetByTitle("DocumentLibraryName");
    ListItemCollection listItems = list.GetItems(camlQuery);
    context.Load(listItems);
    context.ExecuteQuery();

    if (listItems.Count > 0)
    {
        var item = listItems.First();
        Microsoft.SharePoint.Client.File file = item.File;
        ClientResult<Stream> data = file.OpenBinaryStream();

        // Load the Stream data for the file
        context.Load(file);
        context.ExecuteQuery();

        // If data received, write it to disk so I can verify the contents
        if (data != null)
        {
            int position = 1;
            int bufferSize = 200000;
            Byte[] readBuffer = new Byte[bufferSize];
            string localFilePath = "C:\\Temp\\test.pdf";
            using (System.IO.Stream stream = System.IO.File.Create(localFilePath))
            {
                while (position > 0)
                {
                    // data.Value holds the Stream
                    position = data.Value.Read(readBuffer, 0, bufferSize);
                    stream.Write(readBuffer, 0, position);
                    readBuffer = new Byte[bufferSize];
                }
                stream.Flush();
            }
        }
    }
}

Concluding Remarks

Notice in the example above I load the resulting Microsoft.SharePoint.Client.File object's Stream data by calling the OpenBinaryStream() method and then loading the contents by calling the ExecuteQuery() method on the current context.  This approach allowed me to successfully return the contents of  the file.  The only reason I wrote the file to my local hard drive was to verify that the file contents were correct.  It's kinda hard to validate I'm getting an un-corrupted PDF file simply by viewing a byte array.

As an aside, since it's probably more useful to return the file contents as a byte array, you could replace the code that writes the file to disk with something like:

if (data != null)
{
    MemoryStream memStream = new MemoryStream();
    data.Value.CopyTo(memStream);

    // returns a byte[]
    return memStream.ToArray();
}

Like/Dislike what you see? Feel free to drop me a line.

Sources Consulted

Microsoft.SharePoint.Client.File.OpenBinaryDirect() Method

Inside Microsoft OAuth Context Tokens

Authorization and authentication for apps in SharePoint 2013

OAuth authentication and authorization flow for cloud-hosted apps in SharePoint 2013

How to: Create a basic provider-hosted app for SharePoint



Wednesday, May 30, 2012

What Facebook's Mobile Strategy *Should* Look Like

I'm sure by now you have heard that Facebook's shares have been taking a dive since its initial IPO offering.  I am baffled as to why Facebook has been unable to tap into the mobile market, given the 900 million users it claims to have.  I am even more baffled at the current Facebook app that I have installed on my Android phone: it looks and functions just like the website, while completely ignoring the fact that it has access to my current location wherever I may be. For crying out loud it is 2012 and you are a huge company with billions of dollars and you can't figure out a way to make money while your app is installed on my phone and accompanies me nearly everywhere I go 24 hours a day?!

OK - I know how it is when someone is too close to a problem.  This happens to me all the time - I can't see the obvious solution.  So, if I owned Facebook (scary thought I know) I would be thinking about how I could implement the following:

I would want all of my users to start experiencing the web and their connections to others through the Facebook app.  Think of the Facebook app as a portal to the rest of the internet and their Facebook profile as a type of currency.  Every time someone is near a Starbucks, a notification could pop up inviting the user to get $0.50 off a latte if they buy it with their Facebook account.  Similarly, users could earn "points" for buying products and services through their Facebook accounts.  Facebook could partner with game companies and offer subscriptions at reduced rates.  Facebook would make a killing in referral charges for utilizing their network.  This is just the start - imagine being able to talk to someone for free through your Facebook account (voice or text) since everyone will be signed in all the time.  The opportunities to connect and create new experiences through the Facebook portal (app) would be right in your pocket, whenever you need it.  These are just a few ideas off the top of my head - can you come up with more?


Monday, May 21, 2012

Improving LinkedIn

Recently, a new app called Branchout was introduced on Facebook and it got me thinking about how stale LinkedIn has become lately.  However, I believe that LinkedIn could be improved if a few key features were added.

First, I would open up the content in the groups to all users of LinkedIn, but only allow group members to contribute to group discussions, polls, post, view and reply to jobs, etc.  This would keep the group membership exclusive, but would open up the information to everyone.  I predict this would make the quality of posts improve on average because the user's words would reach a larger audience and enable people to share information between different groups.  This could improve the chances of innovation and collaboration between individuals of different disciplines.  It would cut down on the information silo effect of LinkedIn and increase the quality of the information.  Done correctly, it would totally transform LinkedIn and make it more valuable and more visible to the public and indispensable to numerous professionals.
Second, I would add the ability to chat instantly with any user (like Facebook).  I can't fathom why LinkedIn doesn't allow this feature.  Imagine being able to talk to anyone in your extended network, as soon as you found that person's profile, if that user accepts the chat feature and the request to chat.  This would instantly encourage people to be logged into LinkedIn on a more regular basis while also increasing ad venue and user engagement.  This could be a huge win for LinkedIn.
Third, I would add the ability to create blog posts within LinkedIn.  This would enable potential employers to read what potential job candidates have written and what other experience they may have.  It would showcase writing skills and research interests.  This would be a great way for people to create a nice professional portfolio of themselves online.  LinkedIn feels so two-dimensional with jobs worked and skills acquired.  Anyone could post anything on their profile, but knowledge, skills and personality could also be demonstrated in blog posts.  This would benefit both users, prospective employers and LinkedIn by increasing site usage, user engagement and portraying a more accurate picture of what each LinkedIn professional really knows.  
Forth, I would add ratings to individual groups, users and posts.  This would use game theory principles to add incentives for posting quality content, becoming a member of a highly rated group and also encourage more users to join.  Users who post content others find helpful would naturally have higher ratings and be first in line for consideration of job opportunities and/or getting connected.
I believe that adding those few simple features and improving the information architecture and user experience of the site would solidify LinkedIn's presence on the web as *the* place professionals need to go to connect and collaborate because of the strength and legitimacy of its communities.

Tuesday, February 28, 2012

The Largest Benefit of Collaboration in the Workplace

I believe that the biggest benefit to collaboration in the workplace in today’s market has to be the potential for innovation. In one of my class textbooks Enterprise 2.0 Implementation, it states on page 72: ”In today’s economic arena wherein competition is global and products and services are cheap due to the increasing commercial potentcy of emerging markets, price is no longer an area in which organizations can hope to differentiate themselves. Instead, innovation is the principle means through which organizations can remain competitive.”

I agree with the author here, but I would take it even further and argue that in order to even enter certain markets, companies must have an innovative product or service. In many industries/markets, the barriers to market entry to be the cost leader are very high. I doubt anyone will be able to compete with Walmart as a cost leader, for example, any time soon.  However, one only needs to look at Apple for a good case study on innovation and becoming a market leader in the high-end niche electronics market.  Apple decided to change the focus of its company and drive focus away from just PCs and also into the mobile computing market.  Soon after coming out with the iPhone and iPad Touch, it was able to post its best non-holiday quarter earnings of 1.2 billion in profilts (Q1 FY 2009). In addition, Facebook is another good example.  Facebook started out as just one of many social networking sites. Initially, it was an invitation-only website where members had to be a student at a University in order to access and participate in the site. However, soon after adding a way to “tag” photos of friends and by concentrating on the user experience instead of sponsors Facebook took off, while its competitors, like MySpace, faded in popularity.  That innovative focus boosted the popularity of the website and has driven its succcess even to today (source).  Finally, Spigit is taking advantage of this trend by providing tools for companies to harness "crowdsourcing" in their client's organizations in order to boost opportunities for innovative solutions to problems.  "Spigit’s customers include 26% of the Fortune 100 and 16% of the Fortune 500".

So how does a company foster innovation through collaboration you ask?  Many have argued that innovation occurs in complex environments through social learning networks because the knowledge needed to solve the problem in that domain often spans multiple disciplines or specialties. For example, a paper entitled Interorganizational Collaboration: and the Locus of Innovation: Networks of Learning in BioTechnology states “We argue in this paper that when the knowledgebase of an industry is both complex and expanding and the sources of expertise are widely dispersed, the locus of innovation will be found in networks of learning, rather than in individual firms.”  Also, a white paper by IBM, entitled The new Collaboration: Enabling Innovation, Changing the Workplace, makes a similar point:  ”A company is a group of individuals. No one knows what everyone else knows… The new collaboration can provide a platform for helping the many operate as one because each person can be only a step away from the knowledge that other people have.”

It seems the need for collaboration is here to stay and will only grow increasingly more important in order to gain market leverage in our fast-pasted, highly competitive global economy.  Therefore, the salient question becomes: are you doing enough to foster meaningful collaboration that leads to business value among your employees in your organization?

Friday, February 24, 2012

Personal Attitudes Toward Solving IT Problems

Building Trust with the Client or Why Soft Skills are so Important

I used to think the most important goal of developing software was to do everything the client says to do, verbatim, without argument or regard for the consequences. However, in my experience, this has often led to project failure. Projects succeeded when my point of contact for the client was a subject knowledge expert on the technologies being used and really understood and valued user experience design principles.

The *best* way to build trust with the client (or anyone else for that matter) is to convey your ernest desire to do whatever is in the best interest of the client for the entire duration of your relationship with the client - in a word: altruism. Use your active listening skills to understand what your client really needs.

Once trust has been established, your recommendations are more likely to be considered and implemented. Sometimes this may mean offering a cheaper solution or a solution that the customer can maintain themselves without needing custom development or maintenance every year. Your clients will remember that you acted selflessly and will be more likely to work with you again in the future on another project, or recommend and introduce you to other clients.

Could this be a Systemic Problem?

Systems Thinking has always fascinated me. And I only got more interested after reading Peter Senge's book The Fifth Discipline: The Art and Practice of Learning Organizations. Systems Thinking is one of the 5 disciplines he believes an organization must possess in order to maximize its business potential, among other things. It's a good book and I highly recommend it. I have a favorite bookmark that I go to, as a cheatsheet of sorts, when I am faced with a particularly challenging work flow or business process problem that I need to solve: Places to Intervene in a System.

Debugging is Underrated!

I feel strongly that this is the *first* lesson any programmer should be taught: how to debug computer systems. I would have to say that the most useful skill I possess as a programmer is the ability to debug anything. I *have* to know why it's not working - it will keep me up all night... And here's the thing - it's completely underrated! Sure, you can find millions of webpages dedicated to tips and tricks and code samples, but very few sites on good debugging techniques. I'll be sharing some of my favorite resources in a future post. I just wanted to shine the spotlight on debugging.

Continuous Improvement

Confession - I have a tendency to over-think really simple things. I'm not alone - most IT folks I know seem to have the same affliction. For example, when I was a kid, I often pondered about the most efficient way to tie my shoes (go ahead, laugh). I've literally spent days thinking about this from every perspective I could imagine - from redesigning the laces and shoes to some sort of self-tying mechanism.

So, when I approach an IT problem, I often check in with myself to determine if I'm over-thinking the solution:

  • Have I properly identified, defined and understood the problem? 
  • Have I verified that all my assumptions are true? 
  • If I were the user, ideally, how would I want the overall system to function? 
  • Can any of the processes/components be simplified/improved? 

    Monday, February 20, 2012

    A Rant on the Usability of Mobile Touchscreen Websites

    This is a desperate plea to all web developers out there.  Please detect that I am on a mobile device and change all of your links to buttons.  Yes, even if the button will take up the entire width of my screen - that is OK!  What is *not* OK is having to zoom (which, sometimes I can't) and try for a very long time to touch a link and navigate to the page that contains the information that I want.  Stop using links.  Use buttons.  That is all.  Thanks for your consideration!

    Signed,
    Every Mobile User.