Showing posts with label SharePoint 2007. Show all posts
Showing posts with label SharePoint 2007. Show all posts

Friday, 19 April 2013

SharePoint Project Planning


Congratulate yourself for actually accepting planning is required with SharePoint.  I know Microsoft likes to tell us you can just turn it on and use it, but we all know that’s just not the case.  Too many places are stuck with the pilot that never ends.  Starting with pilot or POC is great approach, but for it to work you need to circle back and actually plan a proper deployment that includes DR, Availability and Performance.  The Pilot that never dies had none of these consideration and is like a ticking time bomb, who will be the first user that picks up the phone to complain the site is unusable?  Will it be the CEO?  More importantly will you be able to fix it?

To begin with make sure you have the correct people for the job.  If you are going to train up internal resources to do the job, ensure the training happens early, ideally before any solution planning.  This is because the team planning the SharePoint solution will need to lead the end users to the solution.  It's hard for the end user to ask for what they want, when they don't know what is available.  Ask any SharePoint professional and there are many tools, tips and quirks to using SharePoint that only someone with experience would think of.  If no one knows how SharePoint works, it becomes the blind leading the blind.  Which is why, even if you are planning to train up your internal resources, you should ensure you have an experienced SharePoint professional on the project.  As we all know, there are something's that only experience can teach us.

Once you have armed your team with this knowledge, the end users are going to ask for things that are known limitations of SharePoint.  While it is always a great strategy to use OOTB functionality, don't be too rigid on this.  Rather than just saying no, or agreeing to a complex custom solution, be prepared with work arounds or alternatives that may speak more to the spirit of the request.  After all, if the site is usable to the end user, who is going to use it.  But if it's overly customized who is going to support it?

Now that you have enough information to design a solution that will meet the end users' needs don’t' forget to consider the following in your design: High Availability, Disaster Recovery, Automated deployment to the multiple environments (UAT, Staging, Production), Security, Internal vs. External access, mobile (becoming bigger by the day), performance and of course monitoring. 

Be agile in development, especially with people that don't have much SharePoint exposure or experience.  Again, when people don't know SharePoint, they can't know what to ask for.  By giving the users prototypes or sneak previews into the solution you can identify gaps early and have a much better chance of delivering a solution the end user will actually use.

Test, test and test; be sure testers also have SharePoint training.  Otherwise how will they know what to test and how to test OOTB features?  During this testing be sure to test in an environment that simulates production.  If you're going to have a highly available environment with multiple Web Front End Servers, or you're using SSL, be sure to test these conditions.  I've seen many issues arise from these that are not reproducible in a single WFE, non SSL setup.  In addition ensure you test your nonfunctional features like Performance, High Availability, Disaster Recovery and monitoring.  After all if you don't test them, you don’t' have them.

Now that you have it in Production, the job isn't over.  We've simply moved to the next step in the SharePoint lifecycle: Build, monitor, review and improve.  After all the end users job is always evolving, your site will need to keep up.

Sunday, 10 February 2013

Alternate Access Mappings and SPFieldURLValue fields

Be careful if you're trying to programmatically pull back the value of a Hyperlink field when your site is using Alternate Access Mappings (AAM).
If the value of the Hyperlink field is pointing to an object within the current SharePoint site, the SharePoint front end will automatically update the URL for the AAM site you are currently using.  BUT if you are pulling the value programmatically it will always default to the URL of the default AAM site.


UPDATE:
Better Way to Fix:
I discovered an even better to fix this problem and it all has to do with how you open your SPSite Object.
For example if you do
SPSite site = new SPSite(SPContenxt.Current.Site.ID)
It will open the site in the default zone, which will then always return the URL of the default zone.
But if you do the following:
SPSite site = new SPSite(SPContext.Current.Site.ID, SPContext.Current.Site.Zone)
It will open the site in the zone the user is currently in and return the correct URL.

To fix this, you must turn the URL into a relative URL and then it will go to the AAM of the site you are currently logged into.  One way to achieve this is as follows:

SPFieldUrlValue linkfield = new SPFieldUrlValue(listItem["URL"].ToString());

string returnValue = linkfield.Url;

            try
            {
                using (SPSite site = new SPSite(returnValue))
                {
                    return returnValue.Replace(site.Url, string.Empty);
                }
            }
            catch
            {
                //swallow exception from Site Not Found
                return returnValue;
            }

How to Properly use RunWithElevatedPrivileges

RunWithElevatgedPrivileges will run the code block with Full Control rights even if the current user does not have full control.  This piece can be very useful, but must be used carefully to avoid creating a security hole.
The interesting part of this method is that for any objects to be run with this elevated context, they must be created within the RunWithElevatedPrivileges block.  This may seem obvious but lets take a look at a couple examples:
  
SPWeb web = SPContext.Current.Web;
SPSecurity.RunWithElevatedPrivileges(delegate()  
       {  
         PublishingWeb pWeb = PublishingWeb.GetPublishingWeb(web);
         ...
       })  

This method will result in an unauthorized error, unless the logged in user has enough permissions to open a Publishing Web object.  But we said the object must be created within the Elevelvated Permission block, so it looks like an easy fix to the above code:


SPSecurity.RunWithElevatedPrivileges(delegate()  
       {
        SPWeb web = SPContext.Current.Web;
         PublishingWeb pWeb = PublishingWeb.GetPublishingWeb(web);
         ...
       })

This method will also result in an unauthorized error.  Wait you say, the SPWeb object is created within the Elevated block, so it should work.  The issue is that the SPContext.Current.Web method returns an SPWeb object under the context of the current user, not the Elevated user, regardless of where the method is run...so how do you get an SPWeb object to run under the elevated permission?  You need to open the web using the GUID constructor, like this:


Guid siteID = SPContext.Current.Site.ID;
Guid currentWebID = SPContext.Current.Web.ID;

SPSecurity.RunWithElevatedPrivileges(delegate()
            {
             using (SPSite site = new SPSite(siteID))
                {
                    SPWeb currentWeb = site.OpenWeb(currentWebID);
                    PublishingWeb pWeb = PublishingWeb.GetPublishingWeb(web);
                    ...
                }
            })


The difference being the first and second examples are returning an already created SPWeb object, that was created under the current users context.  The last example is returning newly created SPSite and SPWeb objects, since they are within the elevated code block they will be created under the elevated context.  Now everything should work as expected, regardless of who is logged into the site.

             



Monday, 7 May 2012

Real Time Search Results with SP Change Log


Search results are only as up to date as the index.

In most cases this small limitation is not an issue. No one really cares that there posted document or blog post will not show up in search results until the next crawl.

From a performance point of view this is a very small price to pay, compared to looping through the entire site with the SharePoint API to find the handful of documents that may not be in the index.
But what if the majority of your screens are search drive? What if the people using the site needed to see the documents the minute they are posted?

Earlier in the year we ran into that exact problem on one of our projects. Many users found it confusing when they would post a new item, but it would take at least 5 minutes before their item would show up on any screens. 

Very unintuitive. How do you know everything went well?

To solve this issue we looked into the SharePoint Change Log. The SharePoint Change Log was created to be able to target which items need to be added to the index. In SharePoint 2003, every incremental crawl needed almost a full crawl just to see what had changed. In MOSS and higher every change is recorded in the Change Log, the crawl then uses this log to add/remove items from the index.

As you can imagine this is a very powerful tool. We can use the Search results to get the vast majority of results, then using the Change Log we target exactly what items need to be add/removed from our screens.
Just like that, Real Time Search Results from SharePoint.

Migrating SharePoint MySites from 2007 to 2010


The MySites, for me anyways, are like the forgotten child of SharePoint. When migrating I put a lot of thought into how to move their existing site collections and solutions. What do they currently have setup in the SSP and how are we going to recreate them in the Service Application architecture of 2010. But I never put a lot of thought into how are we going to move the MySites?

On the surface this doesn't sound like a big deal. MySites are site collections like any other, simply built off a different template. Ideally they are hosted on their own Web Application and have their own separate content database(s); so what's the big deal?

This view isn't that far off, but there are a couple gotcha's that you need to consider before making the move:
  1. No Visual Upgrade option for MySites (or at least I couldn't find one). This means you will be forced to the 2010 Master Page.
  2. All Profile Properties are stored in the SSP database, not the MySite Database. Any custom properties, or any customized values will not be migrated over with just the MySites Content Database.
  3. Audiences are stored in the SSP. Web Parts referencing audiences will be referencing the GUID of the Audience, not the title. This makes it very difficult to just recreate your Audiences on the new environment.
The solution to the last two issues is to migrate over the SSP database as the profile database of the UserProfile Service Application in the SharePoint 2010 environment.

To do this you can use this PowerShell cmdlet to create the new user profile Service:
$ProfileGUID = New-SPProfileServiceApplication –Name [User Profile Name] –ApplicationPool [App Pool Name] –ProfileDBName [SSP Database] [1]

The above command will create a User Profile Service Application and upgrade the SSP Database. You can review the upgrade by looking at the Upgrade Status page. Next you'll need to run this command:
New-SPProfileApplicationProxy –Name [User Profile Proxy] –ServiceApplication $ProfileGUID [2]

Next up, the multi value User Properties do not come through right away. This, again, is due the new Service Application structure. The multi values were stored in the SSP in MOSS, but are now stored in the Managed Metadata Service in SharePoint 2010. Fortunately there is a handy PowerShell cmdlet that help map the Properties to the Managed Metadata Service:
Move-SPProfileManagedMetadataProperty -Identity [Profile Property] -ProfileApplicationProxy [GUID of User Profile Application Proxy] -AvailableForTagging -TermSetName [Term Set Name] [3]
I ran the above command against these properties:
SPS-Interests
SPS-MemeberOf
SPS-PastProjects
SPS-Responsibility
SPS-School
SPS-Skills

Unfortunately, this command no longer works after you install the July CU or later [4]. If possible run this command after SP1, but before the CU.


Finally, I hope, there is the matter of the picture dimensions. In SharePoint 2010 they have changed things and now use three different sized pictures for the different areas of SharePoint. [5] When a user upload a picture SharePoint automatically creates these 3 different sized pictures. But what do we do about the pictures that already exist due to our migration? Once again it's powershell to the rescue. You'll need to run this cmdlet:
Update-SPProfilePhotoStore -MySiteHostLocation [URL to MySite Host] [6]



Now you should be able to open up this newly created User Profile Service Application. You should see that all your audiences, custom user profile properties and all the user profiles are all there.
To finish off this off, you will need to run a couple configuration steps:
  1. Start the User Profile Synchronization Service
  2. Re-Map any custom user profile properties to their AD property
  3. Configure Synchronization Connection and any filters
  4. Setup MySites
  5. Start Full Profile Synchronization
Now your upgraded MySites should be ready to use.


[1] http://technet.microsoft.com/en-us/library/ff608036.aspx
[2] http://technet.microsoft.com/en-us/library/ff607737.aspx
[3] http://technet.microsoft.com/en-us/library/ff608037.aspx
[4] http://blogs.technet.com/b/rycampbe/archive/2011/11/22/june-2011-cu-move-spprofilemanagedmetadataproperty-bug-and-the-workaround.aspx
[5] http://blogs.msdn.com/b/spsocial/archive/2011/01/07/photo-management-in-sharepoint-2010.aspx
[6] http://technet.microsoft.com/en-us/library/ff607547.aspx