Go Search
SharePoint Thoughts
by Maurice Prather
Mon, 26 Jul 2010 23:02:30 GMT
Sometimes you don't run into problems until the day before you run a demo....
 
Case in point:
 
Two weeks ago as I was prepping to deliver an MCM course on BI that covered PerformancePoint and PowerPivot.  I wanted setup a PowerPivot app server so that I could demo a few things. 
 
Well, have you ever tried to run SP on a vm rig that is overburdened?  Sure you have... what is the first thing you do?  Shut down vms until you get your minimum working set.  It's simple... don't need machine A, shut it down.
 
And that's where I faulted.
 
Typically, when installing PowerPivot, I've never had to shut down my farm to conserve resources.  In the MCM lab, it made sense to not have all 6 machines in the farm running... well, I was proven wrong.  My attempt to only run SQL, AD, CA, and the target app server failed.
 
Tip:
When installing PowerPivot, your entire farm needs to be up and running. 
When the PowerPivot setup installs its solutions on the farm, it will wait some period (I forget the exact timeout value) for the deployment jobs to succeed.  On completion, it keeps moving the setup process along. 
 
Otherwise, if you don't have your entire farm up and running, SP does the right thing and leaves the deployment states as "Deploying" until all the machines come online and have a chance to process the timer job.  PowerPivot does what it needs to do (wait for the "Deployed" status) and then errors out if the timeout is exceeded.  Net result: your installation is out of whack.
 
Can you recover?  Maybe, with a leaning towards no.  I haven't spent enough time looking at this error case to figure out if you can recover/resume a PowerPivot installation.  I took the short cut and moved on to a cleaner system.
 
More in the coming weeks about not scrimping on resources...
 
-Maurice
 

Copyright © 2004-2009 BluedogLimited.com. Licensed under a Creative Commons License.

Tue, 01 Jun 2010 20:55:12 GMT
Quick update on the bug that I reported a few weeks ago...
 
During the MCM class, I had a chance to follow up on the SPManageAccount issue.  It turns out that the Managed Account feature simply looks up the account based on the actual string representation of the account (i.e. domain\account) rather than relying on the SID.
 
When I uncovered this problem, we had been actively using the account, discontinued use (but left it in the SPManagedAccount collection), and deleted the account from AD.  Since we had already loaded the information into memory, the netlogon api had effectively cached the user information.  Thus, subsequent lookups appeared to fail even though we had tried the simple process of recreating an identically named account (cached sid value didn't match the new sid value).  If we had just waited 15-20 minutes for the cache to timeout, we would have found that creating a new account with the same name would have worked. 
 
Net result: the bug is not as bad as it seems.  You are not required to restore the orginal account (sid).  Wait for the system to flush out the old cached values, then create a new account with the same login name.  At that point in time, you should be able to regain functionality and properly clean up your SPManagedAccount collection.
 
Thanks to Todd and Sean for helping unravel the issue...
 
-Maurice
 

Copyright © 2004-2009 BluedogLimited.com. Licensed under a Creative Commons License.

Tue, 11 May 2010 18:45:17 GMT
One of the classic problems with Web Parts is dealing with properties as your Web Part evolves and some properties are no longer needed.
Scenario:
Imagine that today you create a Web Part with property A.  You deploy the part and everything is working as expected. 
 
Then next week, you come along and decide that property A is no longer good enough.  You decide that your Web Part should have property B instead of A, but you need to use some information previously recorded in A. 
How do you deal with "upgrading" your properties?  WSS Web Parts and ASP.NET Web Parts both offer mechanisms you can use to easily interrogate older, unknown properties. 
  • In WSS Web Parts, you can reference the UnknownXmlElements property.  This property contains, as the name implies, all of the unknown xml elements found in the serialized form of that web part instance.
  • In ASP.NET Web Parts, you need to use the IVersioningPersonalizable interface.  This interface will allow you to process any orphaned personalization data. 

Interestingly enough, it's come to my attention that a lot of folks have never heard about IVersioningPersonalizable. It's handy, so be sure to put it into your toolbox.  :)

To help you along, here's an IVersioningPersonalizable example that you can easily test...

public class WebPart1 : WebPart, IVersioningPersonalizable {

  //[WebBrowsable]
  //[Personalizable(PersonalizationScope.Shared)]
  //public string OriginalValue { get; set; }

  [WebBrowsable]
  [
Personalizable(PersonalizationScope.Shared)]
  public string EvolvedValue { get; set; }

  private System.Collections.IDictionary orphanedProperties;

  public WebPart1 () {
    this.Init += new EventHandler(InitHandler);
  } // End of constructor

  /// <summary>
  /// If property sets have changed, this method is called by the framework
  /// </summary>
  /// <param name="unknownProperties">Collection of orphaned properties</param>
  public new void Load(System.Collections.IDictionary unknownProperties) {

    // ----------------------------------------------------------------------
    // Save the reference to a local property. 
    // ----------------------------------------------------------------------
    // NOTE: 
    // SharePoint's Web Part Manager has not completed the load sequence at this 
    // point in time; therefore, if you call SetPersonalizationDirty at this point
    // in the lifecycle, you will get an InvalidOperation exception stating there 
    // is no WebPartManager on the page.
    // ----------------------------------------------------------------------

    this.orphanedProperties =     unknownProperties;

  } // End of Load

  private void InitHandler(object sender, EventArgs e) {

    // Check to see if we need to handle orphaned properties...
    if (this.orphanedProperties == null) {
      return;
    }

    // Find the property we want to update...
    foreach (System.Collections.DictionaryEntry de in this.orphanedProperties) {

      this.Controls.Add(new LiteralControl(de.Key + ": " + de.Value + "<br/>"));

      // Let's save OriginalValue property into EvolvedProperty
      if (de.Key.ToString() == "OriginalValue") {

        this.EvolvedValue = "Updated: " + de.Value;
        this.SetPersonalizationDirty();

      }

    }

  } // End of InitHandler

} // End of WebPart1 class

To see IVersioningPersonalizable.Load in action, you will need to..

  1. Uncomment the OriginalValue property. Compile, deploy.  (leaving the EvolvedProperty in place is ok)
  2. Add the part to a page, then set the OriginalValue property to something (i.e. "my value")
  3. Comment out OriginalValue propertly. Complile, deploy.
  4. Visit the page once more.  You should now see a message that says "OriginalValue: my value".  If you were to view the property pane, you will see that EvolvedValue now contains "Updated: my value".

Both the WSS and ASP.NET methods for reviewing orphaned properties effectively operate in the same manner, but there is one key difference:

ASP.NET Web Parts will not persist the collection of orphaned data if the Web Part is modified before you have a chance to process the data.  WSS Web Parts, on the other hand, will persist orphaned property values until they have been explicitly removed.

In short, it's really easy for you to create Web Parts whose property sets are evolving.

-Maurice


Copyright © 2004-2009 BluedogLimited.com. Licensed under a Creative Commons License.

Tue, 27 Apr 2010 03:26:28 GMT
Last week in the closing thoughts on the Binding Redirection post, I mentioned there was a bug within the new 2010 functionality.  Here's the scoop...
 
This bug won't affect every deployment.  However, if you run across it, a couple of things will happen:
  1. Redirection will not work
  2. You're going to leave garbage in web.config - making admins unhappy with you
The bug is completely related to your public key token (PKT) and how SharePoint creates the value that is punched into the web.config.
 
Let's take a brief look at the problem, then I'll describe the problem in detail...
 
Let's assume that your public key token is
d614fd19520471d5
If you use the BindingRedirect element in your solution, the resulting output within web.config will be...
 
      <dependentAssembly>
        <assemblyIdentity name="VisualWebPartProject1" publicKeyToken="d614fd1952471d5" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
 
 
Do you see the problem?
Split the PKT into 8 pairs - d6, 14, fd, 19, 52, 04, 71, d5
 
Notice that the 6th pair is 04 in the known, proper PKT.
 
However, the value in the publicKeyToken is written without the leading 0. 
 
Yup, it's a simple little padding error.  "04" is the same "4" if you are just looking at the single value; however, in order for the entire string to be correct, there needs to be 16 characters.
 
SPBug.
 
What is the effect?
  1. The first and most apparent effect is that redirection simply does not work.  The .NET framework will read the info and subsequently NOT find a match for your assembly.

  2. The next problem is less visible.  When you retract the solution, SharePoint will not clean up the bindingRedirect it inserted during deployment. 

    Net result: you'll leave a lot of junk dependentAssembly tags in your web.config.  admins will be unhappy (or more appropriately - more unhappy than normal!)
 
Details...
When you add a BindingRedirect to your solution, your solution manifest would like...
 
<Assemblies>
  <Assembly Location="Bluedoglimited.Demo.dll" DeploymentTarget="GlobalAssemblyCache">
    <BindingRedirects>
      <BindingRedirect OldVersion="0.0.0.0-1.0.0.0"/>
    </BindingRedirects>
  </Assembly>
</Assemblies>
 
There are two things worth paying attention to here...
  • The BindingRedirect element only requires the OldVersion attribute.  Even though you know the PKT, you haven't specified it anywhere within the solution package.
  • Hence, publicKeyToken and newVersion are calculated based on the actual assembly values once it has been loaded.
The calculation routine that generates the PKT produces the wrong value.  If any pair is less than 0x0F (15), the resulting PKT string will be invalid.
 
Workaround...
There are two options worth considering:
  • If you want to use the new 2010 built-in functionality to deploy BindingRedirect instructions, your only recourse is to use a new public key that does not contain a paired value that is less than 0x0F.

  • If you can't change your key (because of company policy or legacy requirements), then SharePoint 2010's new functionality is not usable.  You will need make accommodations to write your own bindingRedirect information - programmatically or, worse yet, manually.  Either way, this is a probably not a good option for a number of reasons.

Finally, it's worth calling out this problem was reported shortly before RTM.  I've received confirmation that problem has been located and may be addressed in a future update.

-Maurice

 

Copyright © 2004-2009 BluedogLimited.com. Licensed under a Creative Commons License.

Fri, 23 Apr 2010 19:19:51 GMT
Last night, I ran across a pretty nasty problem with SharePoint 2010's Managed Accounts. 
 
If you delete the underlying account that is referenced by a SPManagedAccount instance, you will lose the ability to execute a variety of administrative tasks.  Nothing like being the highest permissioned authority in a SPFarm and be unable to do most anything.
 
Here's the repro:
  1. Create local or AD account "test123"
  2. Create a managed account that references "test123"
  3. Delete the account (but leaving the managed account intact)

In the above steps, note that I don't use the SPManagedAccount at all within SharePoint.  I simply created the account and then created a SPManagedAccount.

At this point in time, your administrative capabilities start to diminish.  The severity of the problem is completely dependent upon which product you are using - Foundation or SharePoint Server.

The biggest indication that you've lost control is the following error message that may appear when you try to enter particular pages or execute various actions:

Some or all identity references could not be translated.

Once you're in this state, there is no easy way to back out of the mess.  In fact, your experience will degrade over time (in other words, you will be progressively locked out of more of your farm as time progresses).  It's painful.

What areas are affected? 

  • In SPF, there does not appear to be much collateral damage.  Aside from being unable to delete the Managed Account, it seems you are mostly ok (please note that I spent all of 15 minutes on SPF install trying to get a repro and validating the fix). 
  • In MSS, the problem is super nasty - I was locked out of Manage Service Accounts, Timer Jobs, and few other areas.  In the areas where I could reach the configuration page, updates were prohibited.  This is where I spent most of my time trying to understand the problem after I ran into it. 

In Foundation, there is an unsupported way to remove the reference to the account.  One special query and flush of your config cache and you're back to a good state.

In MSS, that same action is useless because the User Profile service is now integrated into practically every call out to a user identity. 

After spending the better part of an evening trying to recover my ability to administer a SPFarm, I found the only way to accurately and easily restore admin functionality is to restore the deleted account.

This scenario quite frankly scares me.  Why?

  • Most SharePoint teams don't control their AD accounts.  Therefore, it becomes really easy for AD team to clean up accounts that they believe are not in use and unknowingly kill the ability to administer a SPFarm.
  • Recovering deleted accounts from AD is a pain. 
    • Note: There may be no opportunity to restore local accounts (this is an educated guess - I don't know enough to say with any authority).  However, most installs that go with a Standalone installation never use anything more than what the installer configures; this problem may never appear in those configurations anyways.
  • There may be a delay between the time the deletion occurs and you run into the first denial.  Therefore, it may be hard to connect the dots.

Aside from the error message that may pop up, how can you tell if your underlying accounts are missing?

Try enumerating the Managed Accounts (via CA or Get-SPManagedAccount).  SharePoint will show a blank entry for Last Password Change (or PasswordExpiration).

What is the sure fire way to fix the problem?  Restore the account.  As soon as the account exists (even if disabled), the authorization routines work and it's like nothing ever happened (sort of - you may need to reset some services like the Claims to Windows Token service).

What is the sure fire way to never get into this problem?  The proverbial "duh" is to not delete any accounts that are referenced by SPManageAccount in the first place.  :)

Here's to saving someone from a sleepless night...

-Maurice


Copyright © 2004-2009 BluedogLimited.com. Licensed under a Creative Commons License.