1 0 Archive | SharePoint 2010 RSS feed for this section
post icon

What tools to install on a SharePoint 2010 developer box

I’ve built out SharePoint development environments many times but I’ve never really sat down and made a list of the tools I use before.   A good friend emailed me today and asked what tools I have on my SharePoint development box and it prompted me to put a list together.   I thought I’d share what tools fit into my day to day usage.

First a bit about the infrastructure and topology of my development environment.   I’ve got a dedicated VMWare ESXi 5.0 box in my basement with an i7-920, 24GB of ram, and 4x2TB hard drives in Raid 1+0.  I’m using an Adaptec hardware raid controller all inside of  a Super Micro tower.

With that box I’m able to run quite a number of virtual machines for a lot of different tasks beyond SharePoint development.   I’ve got a combination of Linux and Windows servers and clients setup for building and testing various applications.   A couple boxes are mainstays however and provide resources that are shared across the rest.   These are my domain controller and SQL box.   Both are running server 2008R2.   The SQL box has multiple SQL instances on it (2008R2 and 2012).   I have a couple of different SharePoint VMs and fire them up depending on what I’m working on.

When setting up the development box I always turn to AutoSPInstaller to actually install the SharePoint bits.   It automates the process and makes it repeatable.   It can handle installing the prequisites, configuring the farm, configuring service applications, creating web applications, creating site applications, etc.   It is really very powerful and saves a ton of time in setting up a new environment.   You can get it at http://autospinstaller.codeplex.com/.

 

For my primary 2010 development box I also have the following tools installed:

And while I hesitate to admit it given how much I hate the headache it can cause, I do also use SharePoint Designer from time to time.   While I’m a firm believer that you shouldn’t do SharePoint customizations with it (everything should be done via Visual Studio and packaged into a WSP) the truth is that SharePoint Designer is really good for working on masterpages.   If you’re doing branding work then I’d recommend it be included into your tool arsenal.

Leave a Comment
post icon

Comparing Office 365 and Google Apps

I’ve used Google Apps for many years given that it is a reliable way for me to host my personal email for free.   I own my own domain (obviously) and I enjoy having the address jason@vallery.net.    Since the surname Vallery isn’t terribly common I’ve also had the occasion to setup email addresses for close and distant family members who wanted the novelty of name@vallery.net.    With the free version of Google Apps you can create up to 10 accounts which was more than enough for my limited needs.

Given my role in technology I’ve also had the occasion to help friends and family with their own personal web needs.  Over the last few years I’ve helped several folks get off the ground with a basic website and email on their own domain for either personal or small business use.   Every single time I’ve turned to Google Apps as the solution for them to host their email, calendar, etc.

Now that Office 365 has been available for a while I decided to evaluate both my own usage of Google Apps as well as what tool I’m recommended to people who ask me.   What I’ve found has redefined the problem a bit and changed the way I approach the answer.

For my own use I migrated my domain over to Office 365 last fall (around November 2011 I think).   I was pleased with the tools that Microsoft offered to accomplish this.   It was a pretty simple task for me to import the users, migrate their email, and then send them their new login credentials.   I had a little bit of effort in walking the family members through configuring Outlook and/or their Phones but it generally went well.

There were a few things that I immediately noticed were missing however:

  • No custom CNAME for the login page.   Everyone had got used to logging in at https://mail.vallery.net/.   Now I have to have them go to https://portal.microsoftonline.com?   What is that about?   It would have made the transition quite a bit simpler if I could have just remapped the CNAME so the URL wouldn’t have changed for the users.

 

  • DNS management is tricky.   Microsoft has the expectation that I’m going to just hand them over my domain and use their DNS servers.   No way Microsoft!!   I use my domain for a lot more than email and instant messaging.   I’ve got a number of complex records that need to be maintained.  I want the ability to dynamically update those records via an API.   That is why I turned to paying for the premium service from dyndns.org to host my DNS.   With the limited capability that Microsoft is offering for DNS management there was no way I was going to switch to their name server.   As a result I had to “trick” their system by looking up all of the records that they would have inserted on my zone had they been hosting it and then create them on dyndns.org’s server.   This wasn’t a big deal but shortly after I setup my account those records changed and my service stopped working.   I had to go and repeat the process.   I understand why from a stability perspective Microsoft wants to be able to handle the DNS for the domain but that just isn’t practical until their tools are as robust as other offerings.

 

  • Of course the biggest difference is cost.   For free with Google Apps you get 10 mailboxes, calendar, cloud storage for documents, instant messaging,  SAML claims support (ADFS),  and a marketplace full of additional capabilities.  For free from Microsoft you get….  nothing.    The cheapest Office 365 plan is $4/month/user and that only gets you exchange.   For $6/month/user you can include Lync and a SharePoint site collection.   You still don’t get full enterprise features like sync with AD, true SharePoint (mysites, multiple site collections, etc).   That doesn’t kick in until you get up the E1 plan.  Current Office 365 pricing and plans: www.microsoft.com/en-us/office365/compare-plans.aspx

 

So what does that mean?   For someone like my cousin who has a classic car restoration business (http://chclassics.com) it would make no sense for him to pay $6/month/user for email.   He has five employees and only two of those actually use email.   With Google Apps he can get free hosting for his email and calendar and it meets 100% of his needs for free.   I can’t help but recommend that he go that route.

For someone like myself who lives in his email it makes more sense for me to go Office 365.   I mentioned the things that Office 365 was missing above but I didn’t mention what it brings.   This is exchange.   The most powerful mail server that has ever existed.   I get to push my email down to Outlook.  No more IMAP.   I get 25GB of storage to archive and search my old messages.   I get a SharePoint site for hosting my family’s documents.   I have a shared One Note with my wife with all kinds of stuff in it (tasks, shopping list, recipes, finances, etc).

So – if you’re a small business with a technical savvy audience that can appreciate the real value that having a true exchange/SharePoint based solution can bring then obviously Office 365 is the way to go.   If you need the very basic functionality and are watching your expenses very closely than I’d say stick with Google Apps.   For me the $6/month/user I’m paying is a small price to pay for the functionality that I get.   I will certainly continue to recommend Google Apps though for people like my cousin who just want to get their email.

Obviously neither Google or Microsoft are making their money off customers like myself or my cousin.   That isn’t the market that either of them are after.   The under 10 user customer isn’t even on the Microsoft radar.   I think from a public relations perspective though it would benefit Microsoft to consider introducing a plan that would directly compete with the free Google Apps plan.  Who knows…  maybe some day my cousins 5 person business will turn into a 50 person business?  Wouldn’t it be easier for him to continue using Google Apps then switch to Office365 at that point?

Leave a Comment
post icon

And we’re back…. On wordpress

So my fairly short lived experiment with migrating my Blog to SharePoint is over.   As much as I love SharePoint it really isn’t a great platform for public blogging, at least using the out of the box blog template.

There are some major limitations that caused me to switch back:

 

  • Because the solution runs in the sandbox I can’t make any outbound HTTP requests from my custom code.  This means that even if I wanted to write a custom comment handler to use a spam filter like Akismet, I can’t.   The result was that I was getting hundreds of spam comments on my blog. 
  • There is no URL rewrite support so all of the URLs on the new blog were simply “Post.aspx?ID=XX”.   This is crap for search engine optimization.
  • The comment capability doesn’t allow for anonymous users to specify their name and email address.   This meant that all comments were anonymous.

Overall it was a fun experiment and I learned a lot about sandbox solutions and online hosting.   I think I’ll stick to wordpress at least for now though as I have considerably more flexibility with it.

For historical purposes though I still have the Visual Studio project available that I used to create the sandbox solution here:  http://vallery.net/wp-content/uploads/2012/01/ValleryBlog.zip

Leave a Comment
post icon

Blog migration to SharePoint

 

You can find the source code for this entry at:  http://vallery.net/wp-content/uploads/2012/01/ValleryBlog.zip

So I decided to migrate my blog from WordPress to SharePoint.   The motivation was driven primarily out of wanting to “eat my own dogfood”.    Given that most of the work I do and the posts on my blog all have to do with SharePoint I thought it would be appropriate to actually host my blog with SharePoint.  

I decided to seek out a hosting provider which specializes in “SharePoint in the cloud” given that my blog is high enough traffic and important enough to me that hosting at my house isn’t an option.   I first turned to Microsoft’s Office 365 service given that I’m already hosting my personal email with them.    I was disappointed to learn that you currently cannot host a public facing website with anonymous access.   They require the site to be secured which wouldn’t work for a blog.

I emailed a couple of the other community hosting options and got a very nice reply from FPWeb.   One of the services they offer gives you a single site collection on SharePoint Foundation which you can optionally give anonymous access to.   The site is limited in terms of which SharePoint features are available but they did offer the blog template.  If you’re not familiar with the differences check out this great guide which details the plans that are available.   The site provided uses SharePoint hostname site collections which allows me to have a fully qualified domain name (http://blog.vallery.net/) point to a single site collection on their web application.  

For my use case there were a few limitations that bit me:

  • Deployed custom solutions must fit into a “Sandboxed Solution”.    This is true for any of the non-dedicated online SharePoint option though so not an issue with FPWeb specifically.    This means that many of the things I’m used to doing for my customer’s on-premise installations are not possible in the cloud.   Microsoft has a good list of the limitations of SandBoxed solutions worth reading.  The things I missed the most are:
    • Ability to create custom delegate controls.    This made doing a custom searchbox a bit more difficult and less flexible than I’d like.
    • Ability to integrate with external systems.   My current WordPress based blog will post to twitter automatically when I write a new article but given that no external HTTP requests are allowed I can’t write an event receiver to do that for me.
    • I have to deploy all style assets to the SharePoint “Style Library” because I can’t write to the file system.    This could potentially have a negative impact on performance because now they live in the database.
    • I wanted to create a few custom controls to handle some of the style elements.   For example the banner on the site isn’t as flexible as I’d like.   It should really pull the title, url, and description from SPContext.current.web.   I had to hardcode them into the masterpage which means my solution isn’t portable.
  • Since FPWeb only provides SharePoint Foundation it makes branding more difficult.   There are a number of capabilities found in the enterprise publishing features that I typically use with my customers which were unavailable to me. 
    • In a custom masterpage you can use the SPUrl object to find a the URL of the site collection or site in order to reference your style library (to include CSS, JS, and images on the page).   This is not available if you don’t have enterprise so I had to hard code the path to the Style Library into the masterpage.   On my development box I created a blog site collection in a managed path off the root which made the path different than my site here at FPWeb (which is the root site collection).   This caused me to have to make a quick change every time I switched from my dev box to pushing out the solution to FPWeb.
  • Search is limited given that it is only SharePoint Foundation.  This is fine because I only need a site scoped search anyways.   The trouble of course is that it turns out the control that is used is very different.   I styled the Enterprise version since that is what I had on my dev box.   Once I deployed to FPWeb I discovered that none of my styles worked.   I had to go back and refactor for the foundation search box.   It wasn’t a huge issue but it took me a while to figure out why my styles weren’t working!

Once I got my solution done with my custom style I needed to get all my old content off my WordPress blog and onto SharePoint.   I had some good conversations with Metalogix at their booth during the SharePoint conference in Anaheim so I was already familiar their "Migration Manager for Blogs and Wikis" product.   They were kind enough to give me a trial key which was enough to migrate my posts and comments from wordpress across.   The process was painless and just required confirming the source and destination.   It was able to capture metadata as well like category which was handy.  

I did discover a few issues with the way the data was migrated though.  I realized that the blog author for all of the posts and comments was listed as me.   I guess this make sense since the author field is tied to a people picker and needs to be a person.   None of the comment authors in wordpress are users in my SharePoint environment obviously.    Metalogix handles this by creating a couple of extra columns on the comments list which store the original comment author, name, and email address.   I plan on writing a custom XSLT file and view to parse this at some point to place this information onto the page.  I’ve also included these fields on the new comment dialogue so I can capture it for future comments.  For now though I’m listed as the comment author for all of the comments.

The only issue I had with the Metalogix tool is the moving of images.   This could easily have been my fault as well so I don’t want to blame the tool.   My posts had a number of embedded images which WordPress stored in the wp-content folder.   My expectation would have been that Metalogix would have grabbed those files and put them into SharePoint and updated the references.   It even looked like it attempted to do that however I received a bunch of error messages which indicated failure.   My images are still linking to their original source on my WordPress site (which is still up) so they are not broken.   One of my todo items is to migrate those across by hand and then update my old posts that reference them.     This will give me an opportunity to clean up my old posts anyways which I’ve been meaning to do for a while.

With everything up and running I put 301 redirects into the .htaccess file on my WordPress server for each post.   I pulled out a list of all the posts from the SharePoint list and matched them up to their original URL (which thankfully Metalogix stores in an additional column for me).   With all of these URLs known I’m able to redirect the deeplinks to their specific posts.   WordPress has the handy SEO optimized permalinks which SharePoint does not.

Overall I’m very satisfied with both FPWeb and Metalogix.  Without either of them this project would have been significantly more difficult.   If you can accept the limitations of hosting your SharePoint site in a shared environment then I highly recommend FPWeb.

In case anyone is interested in the actual development work that was involved with the branding in all this I’ve posted my Visual Studio project.  In total I spent about 15 hours on the entire project over my Thanksgiving weekend. You can download the project at http://vallery.net/wp-content/uploads/2012/01/ValleryBlog.zip.

Leave a Comment
post icon

Disable email notifications in SharePoint 2010

Out of the box in SharePoint 2010 all users who have a profile are also defaulted to having email notifications set to “on”.   This might make sense in a small scale implementation but for my customer that was unacceptable.  I created a powershell script that iterates through the user profiles and turns the notifications off.  This script is similar to ones I’ve posted before for working with the user profile however it uses different fields.  The SharePoint field is called SPS-EmailOptin. This field disables both SharePoint and NewsGator emails.

Of course in future releases these field names might change so you should verify before using this script.  In my case this was SharePoint 2010 October CU and NewsGator Social Sites 1.2.2419.

#Load the SharePoint snap-in
Add-PsSnapin Microsoft.SharePoint.PowerShell;

#Load the SharePoint assemblies
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server");
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles");

#Specify the MySite URL
$MySiteUrl = "http://sharepoint.vallery.net/";

#Get the server context for the profile manager
$site = Get-SPSite $MySiteUrl;
$ServerContext = Get-SPServiceContext $site;
$UPManager = new-object Microsoft.Office.Server.UserProfiles.UserProfileManager($ServerContext);

#Count variables
$ucount = 0;

$enumProfiles = $UPManager.GetEnumerator();
"Total User Profiles available:" + $UPManager.Count
$count=0;

#Loop through the profile entries and update the property
#Recieve Instant Notifications - NGAllowMetaEmail (bool)
#24 Hour Digest Email - NGReceiveDigestEmail (bool)
#RSS NewsFeed Email - NGAllowRssEmail (bool)
#SharePoint Notification emails - SPS-EmailOptin (int)
#This field has 3 values one for each email type

foreach ($oUser in $enumProfiles)
{
    $count = $count + 1;
    $u = $oUser.Item("Accountname");
    Write-Output "($count):  Setting values for $u";

    $oUser["NGAllowMetaEmail"].Value = $false;
    $oUser["NGReceiveDigestEmail"].Value = $false;
    $oUser["NGAllowRssEmail"].Value = $false;
    $oUser["SPS-EmailOptin"].Value = 111; 

    $oUser.Commit();
} 

#Dispose of site object
$site.Dispose();
Leave a Comment
post icon

Enumerating user profile property fields in SharePoint 2010 with PowerShell

I’ve been working quite a bit with SharePoint 2010 lately and have written a number of PowerShell scripts that I think will be useful to folks. This is the first of these.

This script connects to the User Profile managed service application and iterates through all of the properties that have been configured dumping the result to XML. The script additionally pulls in any mappings to active directory.

I’m currently working on a script that will import this XML and update the properties accordingly. I hope to post that soon as well.

#Define our configuration. This is the name you gave the import connection to AD
$url = "http://sharepoint.vallery.net/";
$connectionName = "Profile Sync";

#Setup our SharePoint objects
$site = Get-SPSite $url;
$serviceContext = Get-SPServiceContext($site);
$upManager = new-object Microsoft.Office.Server.UserProfiles.UserProfileConfigManager($serviceContext);
$syncConnection = $upManager.ConnectionManager[$connectionName];

#This is a collection of mappings to AD that we will use later 
$pmc = $syncConnection.PropertyMapping;

#This is a collection of all of the properties which we will iterate
$properties = $upManager.GetProperties();

# Create a new XML writer settings object 
$settings = New-Object system.Xml.XmlWriterSettings;
$settings.Indent = $true;
$settings.OmitXmlDeclaration = $false;
$settings.NewLineOnAttributes = $true;

# Create a new string writer to capture the output 
$sw = new-object System.IO.StringWriter;

# Create a new XmlWriter 
$writer = [system.xml.XmlWriter]::Create($sw, $settings); 

#Start the document and add the root node
$writer.WriteStartDocument();
$writer.WriteStartElement("properties");

#Iterate through the properties
foreach ($item in $properties);
{

    #Create the property element
    $writer.WriteStartElement("property");

    #Add in the fields as attributes
    $writer.WriteAttributeString("Name", $item.Name);
    $writer.WriteAttributeString("DisplayName",$item.DisplayName);
    $writer.WriteAttributeString("ManagedPropertyName",$item.ManagedPropertyName);
    $writer.WriteAttributeString("Type",$item.Type);
    $writer.WriteAttributeString("ChoiceList",$item.ChoiceList);
    $writer.WriteAttributeString("Description",$item.Description);
    $writer.WriteAttributeString("URI",$item.URI);
    $writer.WriteAttributeString("IsSystem",$item.IsSystem);
    $writer.WriteAttributeString("AllowPolicyOverride",$item.AllowPolicyOverride);
    $writer.WriteAttributeString("IsUserEditable",$item.IsUserEditable);
    $writer.WriteAttributeString("IsAdminEditable",$item.IsAdminEditable);
    $writer.WriteAttributeString("IsImported",$item.IsImported);
    $writer.WriteAttributeString("Length",$item.Length);
    $writer.WriteAttributeString("IsMultivalued",$item.IsMultivalued);
    $writer.WriteAttributeString("ChoiceType",$item.ChoiceType);
    $writer.WriteAttributeString("DefaultPrivacy",$item.DefaultPrivacy);
    $writer.WriteAttributeString("UserOverridePrivacy",$item.UserOverridePrivacy);
    $writer.WriteAttributeString("IsReplicable",$item.IsReplicable);
    $writer.WriteAttributeString("PrivacyPolicy",$item.PrivacyPolicy);
    $writer.WriteAttributeString("DisplayOrder",$item.DisplayOrder);
    $writer.WriteAttributeString("IsColleagueEventLog",$item.IsColleagueEventLog);
    $writer.WriteAttributeString("IsAlias",$item.IsAlias);
    $writer.WriteAttributeString("IsSearchable",$item.IsSearchable);
    $writer.WriteAttributeString("IsUpgrade",$item.IsUpgrade);
    $writer.WriteAttributeString("IsUpgradePrivate",$item.IsUpgradePrivate);
    $writer.WriteAttributeString("IsVisibleOnEditor",$item.IsVisibleOnEditor);
    $writer.WriteAttributeString("IsVisibleOnViewer",$item.IsVisibleOnViewer);
    $writer.WriteAttributeString("IsTaxonomic",$item.IsTaxonomic);
    $writer.WriteAttributeString("Separator",$item.Separator);
    $writer.WriteAttributeString("MaximumShown",$item.MaximumShown);
    $writer.WriteAttributeString("IsSection",$item.IsSection);
    $writer.WriteAttributeString("IsRequired",$item.IsRequired);
    $writer.WriteAttributeString("SubtypeName",$item.SubtypeName);

    #Look up any AD mappings in the PropertyManagerCollection and include them
    $writer.WriteAttributeString("IsImport",$pmc.Item($item.Name).IsImport);
    $writer.WriteAttributeString("IsExport",$pmc.Item($item.Name).IsExport);
    $writer.WriteAttributeString("DataSourcePropertyName",$pmc.Item($item.Name).DataSourcePropertyName);
    $writer.WriteAttributeString("OriginalDataSourcePropertyName",$pmc.Item($item.Name).OriginalDataSourcePropertyName);
    $writer.WriteAttributeString("AssociationName",$pmc.Item($item.Name).AssociationName);
    $writer.WriteAttributeString("Connection",$pmc.Item($item.Name).Connection.DisplayName);
    $writer.WriteEndElement(); 

}

#Finish up
$writer.WriteEndElement();
$writer.WriteEndDocument();
$writer.Flush();
$writer.Close(); 

#Capture the output into a string
$result = $sw.ToString();

# Write the XML out
Write-Output $result;

And here is an example of the XML output:

Leave a Comment