Wednesday, October 12, 2011

Opening an Infopath form library template from Infopath in a link

I've found a lot of bad info on how to do this and it's not well documented so hopefully this helps someone:

first create a JavaScript function so that your links aren't super long:

<script type="text/javascript">
            function OpenForm(absSiteUrl, siteRelFormUrl, siteRelSaveUrl)
                        var formUrl = absSiteUrl + siteRelFormUrl;
                        var saveUrl = absSiteUrl + siteRelSaveUrl;
                        var formSvcUrl = absSiteUrl + "_layouts/FormServer.aspx?XsnLocation=" + formUrl;
                        CoreInvoke('createNewDocumentWithRedirect2',event, formUrl, saveUrl, 'SharePoint.OpenXmlDocuments.2', true, formSvcUrl, false, 0);

then create a link like so:

<a href="javascript:OpenForm('[AbsoluteSiteUrl]','[SiteRelativeFormUrl]','[SiteRelativeSaveLocationUrl]')">open form</a>

here are examples for the vars
[AbsoluteSiteUrl] = http://mysp2010server/siteA/
[SiteRelativeFormUrl] = myformlibrary/Forms/template.xsn
[SiteRelativeSaveLocationUrl] = myformlibrary

Tuesday, October 11, 2011

People Search from MySite returns 404

If you have MySites and a Search Center running in your farm, you may have overlooked a not-so-obvious configuration setting. When setting up MySites for a User Profile service application, your Search Center URL must point to the "Pages" folder where the Search Center publishing pages are located instead of the Search Center web URL. Otherwise, a People Search from a MySite will forward the request to to


(which doesn't exist) instead of


which is where the PeopleResults.aspx page is actually located.

TLDR: Use http://[searchcenter]/Pages/ for your Search Center url in UPA MySite Settings.

Thursday, September 8, 2011

Including a JS file for a custom ribbon control CommandUIHandler without using a ScriptLink CustomAction or Custom Page Components

I've been struggling lately with the proposed solutions for including the javascript for CommandUIHandler's CommandAction and EnabledScript attributes.  Thus far I have only seen the following examples:

  1. JavaScript directly into the attributes (messy),
  2. Including a ScriptLink command action (bad because then the script file is included in every page where the feature is activated causing bloated pages)
  3. Creating a page component (overcomplicated)
Instead of all this, I created a pattern which loads the js file on the fly with javascript and keeps your ribbon development more compact (note I have JQuery loaded in the master page, if you don't have this then you'll have to either load jquery dynamically or reference the elements without JQuery):

                                     $.getScript('/_layouts/myProject/myScriptfile.js', function(){ commandActionMethodInJSFile(); });"
                           function enabledController()
                               if(typeof checkIsEnabledMethodFromJSFile == 'undefined')
                                  $.getScript('/_layouts/myProject/myScriptfile.js', function(){ RefreshCommandUI(); });
                                  return false;
                                else return checkIsEnabledMethodFromJSFile();


The CommandAction is simple, just load the script file with the jQuery getScript() method and call your ribbon action in the callback.

The real trick was handling the Asynchronous load in the EnabledScript since it will just finish before the callback occurs. What this does is check to see if the method in your JS file has been loaded, if not it calls the jQuery getScript to load the file and then keeps the control disabled, then once the callback happens it calls 'RefreshCommandUI' to notify the ribbon that something has happened and it needs to evaluate the Enabled condition again.  This time, the method does exist because the script is loaded and thus you can call your enabled check method in your script file.

Giving credit where it's due, Andrew Connell's post helped me find the missing piece to my solution :
Hopefully this will help you keep your Ribbon development more simplified.

Wednesday, August 10, 2011

Quickly determine which PID corresponds to which App Pool's w3wp.exe

This is a command that will quickly let you know which w3wp.exe you should be debugging on Server 2008 (IIS7, since the App Pool isn't listed in Visual Studio's 'attach to process' dialog).

go to \Windows\System32\inetsrv and run "appcmd list wp" and you'll get a list that associates App Pool and PID

Wednesday, April 27, 2011

PowerShell code for looking up document properties

If you want to use the SPWeb.Files.Add() method that allows you to pass in a HashTable of metadata for the document, you will need to use the internal name of the metadata field, not the display name.   Here's a PowerShell script to get that for you quickly:

$web = Get-SPWeb
$list = $web.Lists["Shared Documents"]
foreach($item in $list.Items)
    $file = $item.File
    #output all the SPFile property names
    foreach($key in $file.Properties.Keys)
        write-host("File Key: " + $key)
    #output the associated item's fields
    foreach($field in $item.Fields)
        write-host("Item Field: " + $field.InternalName)

Thursday, March 10, 2011

Understanding Sandboxed Solutions

There are several components/processes that are involved in the execution of sandboxed solutions.    For a developer, it's critical to understand how coding/debugging various types of solutions changes based on the type of solution.  Here's how the execution goes in a nutshell:

When the sandboxed code is called, the Execution Manager (running in the w3wp.exe) makes a call to an application server running the User Code Service (SPUCHostService.exe).  The User Code Service then tells the Worker Service  (SPUCWorkerProcess.exe) to load the sandbox code.  The code is then verified to ensure only calls to the subset of the API allowed by the Sandbox API are called.  The worker process then executes the code against the Worker Proxy (SPUCWorkerProcessProxy.exe) which has full access to the SharePoint API (but the sandboxed code has already been disallowed from using the non-subset portion of the API by the Worker Service).

When debugging sandboxed solutions, you'll need to attach to the SPUCWorkerProcess.exe to step through your code.

Finally, the exe's for all the .exe's metioned above (except w3wp.exe) can be found in your 14\UserCode directory.

Monday, January 3, 2011

Thoughts on SharePoint 2010 Search Refinement

I've been spending a lot of time lately working with SharePoint 2010's "Refinement Panel" web part.

This capability was available only as a third-party add-in or Codeplex solution back in the MOSS days, but I was very excited to learn that it had been incorporated natively in 2010.

It's frustrating, however, to have to constantly explain to customers that Refinement goes only 500 results deep unless you have FAST, which requires Enterprise CALs. The standard search provides a Refinement Panel that defaults to an Accuracy Index of 50 and goes to a maximum of 500. This means that the Refinement capability will only work for the first 50-500 results returned.

So if a company is stuck with Standard CALs and no FAST, how do they get around this limitation? Surely a mid to large size company will have many more than 500 list items, documents and other artifacts returned in a global search of all content sources, including SharePoint sites, File Shares, etc.

So in our hypothetical mid to large size company scenario where a search for "widget" returns 5,000 results, how do we mitigate the problem I've outlined with the Refinement Panel? Well, there are a couple of ways:

  • Create focused search scopes
  • Remove the Refinement Panel web part for global searches

Fortunately, data from systems connected via Business Connectivity Services can't be used until you reach the Enterprise CAL level, either, so definitely use FAST for that and many other search improvements.

To conclude, don't fret if you're stuck with just the Standard CAL search experience. There are a few things you can do to make it a little better, especially with the Refinement Panel:

  • if you do use the Refinement Panel, limit results by creating scopes
  • Change the default Accuracy Index from 50 to 500 (the maximum in Standard)
  • Enable Counts for your Refinement Panel
  • ...but be sure to uncheck the "Use Default Configuration" box in the toolpart. :)