April 2014 - Posts

In case you missed it last week, be sure and check out my guest post on the Hey, Scripting Guy blog.  There, I show you how to create sites, get sites, and delete sites from SharePoint Online using PowerShell and CSOM.  SharePoint Online Management Shell doesn't have this functionality, but you can use CSOM instead.  If you are using Office 365, this can be handy to meet your site provisioning needs.

Hey, Scripting Guy Blog Post

I also posted the complete PowerShell scripts to the TechNet script center.

I hope you find these scripts useful.  Let me know if you have any questions.

TechEd North America 2014 is right around the corner.  I'm proud to be among the few offering SharePoint sessions at the conference.  This year, the conference is in my old neighborhood, Houston, TX.  If you are going to be at the conference and have survived until the last day, Thursday (5/15), I have two great sessions for you to see.

  • Windows PowerShell 3.0 Administration with Microsoft SharePoint 2013 and SharePoint Online (OFC-B328) [Room 332A] (5/15/2014 8:30a) - If you love PowerShell and SharePoint this session is for you.  We're going to build custom scripts to work with SharePoint 2013 and SharePoint Online.
  • Search Content Enrichment and Extensibility in Microsoft SharePoint 2013 (OFC-B269) [Room 381A] (5/15/2014 1:00p) - In this session, you will learn all about how to extend search using the Content Enrichment Web Service and Custom Entity Extraction.

I'm looking forward to seeing everyone in Houston!

Also, be sure and check out my TechEd Guide for SharePoint People on IT Unity.

Follow me on twitter: @coreyroth

If you are using SharePoint Online (Office 365), you might notice some changes rolling out this week to your document libraries.  Previously, the header of your document library probably looked something like this.

SPOOldDocumentLibraryHeader

However, now, you will notice a new set of links where the new document link was.

SPONewDocumentLibraryHeader

You can still drag and drop files into your document library like before.  However, there are some other links to get you started.  What's nice about this is that it makes it more obvious about how to create a new document or upload it without having to mess with the ribbon.

Clicking the new button brings up a menu showing you common Office file types.

SPONewDocumentLibraryHeaderNewDocument

A sync button is also present which promotes the use of OneDrive for Business for synchronizing document libraries.

You'll notice that edit, manage, and share are disabled.  That's because these links are only available if you have a document selected.  Once you select a document, these options will be available.

SPONewDocumentLibraryHeaderDocumentSelected

Clicking edit will open the document for editing. 

Clicking manage actually brings up the ECB content menu.  This makes it a bit easier to access than before.

SPONewDocumentLibraryHeaderEditMenu

Lastly, clicking share brings up the document sharing dialog.  I think these are nice changes that make things easier to work with.  I wonder if these links are extensible like ribbon actions or ECB menu items.

If you don't see these changes in your SharePoint Online tenant, sit tight as they should be showing up before very long.

The Content Enrichment Web Service (CEWS) allows you to extend the functionality of SharePoint 2013 Search.  Using CEWS, a developer can send the values of managed properties to an external web service and return new or modified managed properties to include in the index.  The process involved implementing a custom WCF service and then registering it with PowerShell.  The PowerShell cmdlet specifies which properties go into and out of the service.

This post has been cross-posted to MSDN Code where you can download a working sample and deploy it.

This example will take the values of the Author and LastModifiedTime managed properties and write a new string such as "Modified by <author> on <LastModifiedTime>." to the managed property TestProperty.  This property need to be created first prior to trying to use your Content Enrichment Web Service.  The property should be configured as type Text with the following attributes: Query, Search,Retrieve, and Refine.

CEWSNewManagedProperty

To get started, create a new WCF Service Project called ContentEnrichmentExampleService.

CEWSVisualStudioNewService

Once the project is created, you can delete the default service Service1.svc and IService.cs as it won't be needed.

Next, you will need to add a reference to the following assembly. 

  • microsoft.office.server.search.contentprocessingenrichment.dll

This assembly can be found in the folder Installation Path\Microsoft Office Servers\15.0\Search\Applications\External.

Now, we need to create the service to do the content enrichment processing.  Create a new service called ContentEnrichmentExampleService.svc. 

CEWSVisualStudioNewService2

Delete the file IContentEnrichmentExampleService.cs as it will not be needed.  The custom service instead inherits from IContentProcessingEnrichmentService.

Now we can start adding our code to ContentEnrichmentProcessingExampleService.svc.cs.  This code will retrieve the values from the input properties, create our new output property TestProperty and send it back to the search index.

Start by adding using statements to the assembly we added.

using Microsoft.Office.Server.Search.ContentProcessingEnrichment;

using Microsoft.Office.Server.Search.ContentProcessingEnrichment.PropertyTypes;

The interface that the class is inheriting from will be shown as broken since you deleted it.  Change it instead to inherit from IContentProcessingEnrichmentService.

public class ContentEnrichmentExampleService : IContentProcessingEnrichmentService

Add a ProcessedItem collection to hold the output managed property values from the service.

private readonly ProcessedItem processedItemHolder = new ProcessedItem

{

    ItemProperties = new List<AbstractProperty>()

};

Then, Implement the ProcessItem method.  This method receives the input managed properties and allows you to write code to generate the output managed properties.

public ProcessedItem ProcessItem(Item item)

{

 

}

Inside the ProcessItem method, initialize the ErrorCode and ItemProperties.

processedItemHolder.ErrorCode = 0;

processedItemHolder.ItemProperties.Clear();

We then, need to Create a new output managed property named TestProperty.  The property object takes types based on what type of managed property you defined.

var testProperty = new Property<string>();

testProperty.Name = "TestProperty";

Now we are going to retrieve the managed properties using a simple lamdba expression.  Remember that the names of properties are case sensitive and need to match exactly how it shows on the Search Schema page.  You also need to cast the object to the appropriate type.  Since the Author managed property is a multi-valued property, we need to use List<string>.  The LastModifiedTime is a date so we use a DateTime type.

var authorProperty = item.ItemProperties.FirstOrDefault(i => i.Name == "Author") as Property<List<string>>;

var writeProperty = item.ItemProperties.FirstOrDefault(i => i.Name == "LastModifiedTime") as Property<DateTime>;

Now, we need to verify that the properties aren't null.

if ((authorProperty != null) && (writeProperty != null))

{

 

}

We are then going to write out a new string to TestProperty in the format Modified by {Author} on {LastModifiedTime}.  Since Author supports multiple values, only the first value was used.  This value goes in the Value property.  Once we set the value, we have to add it processedItemHolder so that it can send the values back to the search index.

testProperty.Value = string.Format("Modified by {0} on {1}.", authorProperty.Value.First(), writeProperty.Value);

processedItemHolder.ItemProperties.Add(testProperty);

Return the processItemHolder

return processedItemHolder;

At this point, we can run and debug our service using F5.  Leave the service running as it will be called when doing a full crawl.

To register the service with SharePoint we use using the New-SPEnterpriseSearchContentEnrichmentConfiguration cmdlet.  Use the following PowerShell script  to register the Content Enrichment Web Service.  Verify that the Endpoint parameter contains the correct URL to your service.  The example below has the location used in the source code I provided.  If you start from scratch or you have deployed you service to a remote server, then you will need to update the address.

$ssa = Get-SPEnterpriseSearchServiceApplication  $config = New-SPEnterpriseSearchContentEnrichmentConfiguration  $config.Endpoint = "http://localhost:54641/ContentEnrichmentExampleService.svc"  $config.InputProperties = "Author", "LastModifiedTime"  $config.OutputProperties = "TestProperty"  $config.SendRawData = $false  $config.Timeout = 30000  $config  Set-SPEnterpriseSearchContentEnrichmentConfiguration –SearchApplication $ssa –ContentEnrichmentConfiguration $config

The InputProperties parameter specifies the managed properties sent to the service.  The OutputProperties specifies the managed properties returned by the service.  Note, that both are case sensitive.  All managed properties referenced need to be created in advance.  Set the Timeout propety higher to give yourself sufficient time to debug.  For a complete reference on parameters, see this MSDN reference.

After registering your content enrichment service, start a full crawl.  Again, ensure that your Content Enrichment Web Service is running in the debugger.  While it is crawling, you can set breakpoints as desired. 

To verify the functionality after the crawl is complete, issue a query using REST in the browser like the one below.

http://server/_api/search/query?querytext='*'&selectproperties='title,path,author,testproperty'

This query will return every item in the index and include the new TestProperty field.  You can verify that the new property was included and has the expected result as shown in the example below.

CEWSRESTAPIQuery

I hope this gets you started with Content Enrichment Web Services.  I have a few follow-up posts to include on some more of the PowerShell parameters, but I hope this helps.

Again, you can find the complete source code and PowerShell script on MSDN Code.  Feel free to leave me a comment if you run into an issue or have a question.