Category Archives: Search

Solr: Error creating SolrCore when using the Sitecore installation Framework

Today I experienced an error while installing Sitecore 9 using the Sitecore installation framework:

“Install-SitecoreConfiguration : Error CREATEing SolrCore ‘xp0_xdb’: Unable to create core [xp0_xdb] Caused by: null”

Setting the verbose logging option didn’t help and my tries to manually reproduce the issue didn’t work out as well; Or the core was successfully created or I got an error message that the core was already created.

Continue reading

SharePoint 2013 and Windows 8 apps – better together Part 1: Introduction, background and considerations

This is the first post as part of a blog series about the integration of using SharePoint 2013 as a datasource for windows 8 apps.

Introduction

On 8 march 2013, my colleague Ad Reijngoudt (Windows 8 App developer, follow him on twitter: @Areijngoudt) and I spoke on the dutch Techdays on the subject: “SharePoint 2013 and windows 8 app – better together”. After this session, we got a lot of questions on several subjects, so I decided to write some blogposts on these subjects.

Continue reading

Fast: Adding managed metadata properties for the use with scopes in SharePoint 2010

Lately I was working on a project that required to make use of scopes and some managed metadata properties in those scopes. For some reason, those managed metadata properties didnt show up in my scope selection dropdownlist, but I was sure that this metadata property was available in my Fast Managed Metadata properties list

Continue reading

SharePoint: Modifying the PeopleResults.aspx – adding custom Profile Properties

To modify the results of the peopleresults.aspx, a few stepts have to be taken.
In my case, a Division is added to the results.

at first, make sure that the property that you want to display, is indexed so it will be part of the People Search Scope: Go http://MOSS2007/ssp/admin/_layouts/MgrProperty.aspx and select or add the UserProfileProperty that you want to be part of the search result. Check the indexed box.

Open your own userprofile, and add some data in the field.

After this, start a new full crawl on the contentsource that has the sps:// (people search) tag in it. When its finished, you will find the Division back in your metadata properties:

Now you will be ready to modify your peopleresults.aspx:
Go to this page, and open the page in edit mode. FInd the searchresults box, and open this one in edit mode, too. Press the “XSL-editor” button in here.
in here, you can edit the xsl to add the custom userprofile properties to the results.
I am gonna add this to the office information (I know it doesnt belong there, but hey, its just an example):

find the psrch-Description, and add an xsl:with-param names divi, which selects the division userprofile property from the peoplesearch results.

<div class="psrch-Description">
                        <xsl:call-template name="DisplayOfficeProfile">
                            <xsl:with-param name="title" select="jobtitle" />
                            <xsl:with-param name="dep" select="department" />
                            <xsl:with-param name="phone" select="workphone" />
                            <xsl:with-param name="office" select="officenumber" />
                            <xsl:with-param name="divi" select="division" />
                        </xsl:call-template>
</div>

now, find the DisplayOfficeProfile section and add a xsl-param name and a check + value of that parameter to display it in the results:

<xsl:template name="DisplayOfficeProfile">
        <xsl:param name="title" />
        <xsl:param name="dep" />
        <xsl:param name="phone" />
        <xsl:param name="office" />
        <xsl:param name="divi" />
        <span class="psrch-Metadata">
            <xsl:if test='string-length($title) &gt; 0'>
                <xsl:value-of select="$title" />
                -
            </xsl:if>
            <xsl:if test='string-length($dep) &gt; 0'>
                <xsl:value-of select="$dep" />
                -
            </xsl:if>
            <xsl:if test='string-length($phone) &gt; 0'>
                <xsl:value-of select="$phone" />
                -
            </xsl:if>
            <xsl:if test='string-length($office) &gt; 0'>
                <xsl:value-of select="$office" />
                -
            </xsl:if>
            <xsl:if test='string-length($divi) &gt; 0'>
                <xsl:value-of select="$divi" />
            </xsl:if>
        </span>
        <br/>
    </xsl:template>

Save the template and press apply. Prepare for an error, but don’t worry: publish the page and reload it, and your peopleresults will be updated with the custom property

Customizing MOSS Search – Part 2: Modifying the default Moss Search box, remove the contextual (this site) scope and modify the OSSSearchResults.aspx reference

When you want to customize the default WSS Search box, this isn’t too hard. It ships into the ContentLightUp feature, which contains a feature.xml and a searcharea.xml. In that searcharea.xml a reference to the searcharea.asxc exists. Because SharePoint works with delegates with searchboxes, all you need to do is copy that feature, modify its guid, lower the sequence (so that control will be loaded) and change the reference to your CustomWSSsearcharea.ascx.

<Control
        Id=”SmallSearchInputBox”
        Sequence=”99″ 
        ControlSrc=”~/_controltemplates/CusomWSSsearcharea.ascx”>
    </Control>
Modifying the OOB Moss Search Control is different. The MOSS Feature consists of the same files: a feature.xml and a searcharea.xml. The searcharea.xml doesn’t a contain a reference to a user control, but to the SearchBoxEx class in a certain assembly. It isn’t possible to style this control too much, because the output html is a tablerow. Luckily, this class isn’t sealed, so it’s easy to derive from this searchBox. Michiel Lankamp did this before, and reused the original controls of the searchbox, but put them into some div’s. I modified it a bit in such a way that it did work for me ;). He hided the Table with the search controls and rebuilded a structure from divs, where he placed the used controls in. This gives a lot more flexibility and the original Properties can be reused. Please note that the only thing you need to do, is override the CreateChildControls..

 

protected override void CreateChildControls()
{       
    // build the original controls first: we can reuse some of them
    base.CreateChildControls();
 
    // if no controls exist, return
    if ( Controls.Count < 1 )
    {
        return;
    }
 
 
    HyperLinkLoc hlink = null;
 
    // as the output html is a tablerow, we have to find a table with a tablerow in it 😉 
    foreach (Control c in Controls)
    {
        if (c is Table)
        {
            var table = c as Table;
 
            // Loop through cells to find the go button
            foreach (TableCell cell in table.Rows[0].Cells)
            {
                if (cell.Controls.Count > 0)
                {
                    if (cell.Controls[0] is HyperLinkLoc)
                    {
                        hlink = cell.Controls[0] as HyperLinkLoc;
                        break;
                    }
                }
            }
            //hide the table, because we are going to rebuild the search control
            table.Visible = false;
 
            //add new controls
            if (m_ddlScopes != null)
            {
                var scopeDiv = new HtmlGenericControl("div");
                scopeDiv.Attributes.Add("class", "custom-search-dropdown");
                scopeDiv.Controls.Add(m_ddlScopes);
                Controls.Add(scopeDiv);
            }
 
            if (m_searchKeyWordTextBox != null)
            {
                var searchDiv = new HtmlGenericControl("div");
                searchDiv.Attributes.Add("class", "custom-searchTextBox");
                searchDiv.Controls.Add(m_searchKeyWordTextBox);
                Controls.Add(searchDiv);
            }
 
            if (hlink != null)
            {
                var goDiv = new HtmlGenericControl("div");
                goDiv.Attributes.Add("class", "custom-searchGo");
                goDiv.Controls.Add(hlink);
                Controls.Add(goDiv);
            }
 
            if (ShowAdvancedSearch)
            {
                var advancedDiv = new HtmlGenericControl("div");
                advancedDiv.Attributes.Add("class", "custom-advancedSearch");
                var hl = new HyperLink
                {
                    Text = "Advanced Search",
                    NavigateUrl = AdvancedSearchPageURL
                };                       
                advancedDiv.Controls.Add(hl);
                Controls.Add(advancedDiv);
            }
            break;
        }               
    }
}

Using this method, all of the original Properties can be reused.
Two of those properties are asked a lot about:
DropDownMode and SearchResultPageURL

When wanting to search just the site that you are visiting, it could be an option to hide the WSS Search Contextual Scope “this site: <sitename>”. This can be disabled by setting the property “DropDownMode” to“ShowDD_NoContextual”. of course this can be done in code or in the feature ;). When this scope is used, the visitor is redirected to the  OSSSearchResults.aspx. this is a out of the box search results page, which resides in the layouts directory on the file system. A lot of people want to customize this page, or want to have another searchresults page which handles their query. According to the documentation, this can be done by modifying the  SearchResultPageURL property. By default, this is the OSSSearchResults.aspx. When changing this into CustomSearchResults.aspx, it is expected that the redirect does work. But for some reason, this isn’t the case. When the (obfuscated) base.CreateChildControls has been hit, the redirected page for the Contextual search is set back to OSSSearchResults.aspx.

After a bit hacking around, It made clear that the property “UseSiteDefaults” was set to true.After putting it to false, I was finally redirected to my custom searchresultspage, but On all Scopes. The Search Centre that i had specified in the sitecollection, was completely neglected. Specified scopes and people search didn’t work anymore, so using this parameter was not an option for me. Surfing the internet gave me the following 2 options:

  • create a HTTP handler to redirect
  • write an own searchbox class / user control with some own javascript to handle the scopes.

Both options werent the solution for me, because:

  • for every request for a page, the HTTP Handler verifies the request URL and decides wether or not it needs to be redirected
  • Writing an own search box control is too much work. Being a developer, I am lazy. And: “Je deteste javascript un peux” 😉 (and don’t tell me my french sucks ;))

For some reason, I didn’t find any solution on the whole internet, that provided an easy to implement solution, that redirected the OSSSearchResults.aspx  and  was able to use the site defaults, so that no extra work on scoping was needed. Suddenly I got the solution!
This can be done with reflection, I managed to set the private member of the SearchBoxEx Class that stored the link to the OSSSearchResults.aspx. The only caveat that exists, is that you need the ReflectionPermission. When the DLL is in the GAC and/or the web.config trust level is set to full, this isnt too much of a problem (normally ;)). If it isn’t you will need to deliver a permissionset that allows your assembly or class to access the Non-public members when reflecting that class. Below is the code to redirect to the right page:

protected override void CreateChildControls()
{
    // the private member that stores the redirect address
    const string memberFIeld = "m_strOssSearchResultsUrl";
 
    // store the redirect url for later.
    // when debugging, the SearchResultPageUrl from the Feature Properties, is CustomOSSSearchResults.aspx
    var Url = SearchResultPageURL;
  
    // at this moment, the search centre is set, and all links are filled:
    // for example, SearchResultPageURL is set to OSSSearchResults.aspx(altough we specified CustomOSSSearchResults.aspx.
    // this is because "UseSIteDefaults"  is set to true in the feature settings.
    base.CreateChildControls();
 
    // In the code below, we try to find the private Member "m_strOssSearchResultsUrl" of SearchBoxEx, the
    // class that is derived from.
    // Make sure to have reflectionPermission, otherwhise the BindingFLags.NonPublic is ignored!
    // when running in GAC or having full trust in the web.config, this isnt an issue
    Type baseType = GetType().BaseType;
    FieldInfo fi = baseType.GetField(memberFIeld, BindingFlags.NonPublic | BindingFlags.Instance);
    if (fi != null)
        fi.SetValue(this, Url); // replaces URL with our redirection
}

Customizing MOSS Search – Part 1

MOSS 2007 and WSS 3.0 are using the same search engine. It only differs in the options that are available to each of the products. As expected, MOSS 2007 has a lot more functionality then WSS 3.0. Where WSS 3.0 is only able to use contextual search (as in: this site, this list), MOSS 2007 can be configurated to search in the whole farm (content sources), to search for certain type of results (defined in scopes), scheduling the crawl and property management (search on metadata).

Content Sources are the sources where we can get the information from. As per default, just 1 content source is defined: Local Office SharePoint Server sites. Within this Content source, all newly sitecollections are added to be crawled. It is also possible to add other sources like exchange folders, file shares and other websites. Those items are crawled using the default access account. If that account has no access to a source, those items are not crawled, and vice versa. When this account has a to high permission level on those sources, it can be possible that information that is not intended to be searched, is shown into the search results. This is not the case for sharepoint sites that are searched, because the results for these sites are security trimmed.

Search Scopes defines the kind of data you are searching for within a certain area. Two default scopes are “All Sites” and “People”.  The first scope defines that all information within All available sites is searched. The “People” scope is used for the people search. The data that is found within this scope are just user profiles. A third scope can be added, for example “News” In this scope you can specify that all content sources have to be used, but you require that only data with contentType NewsItem is included. This last requirement is called a “Property Query”

Managed Properties are properties that can be used in scopes. Those properties are provisioned by crawled properties that are mapped to this managed properties. For example, after a full crawl, there some new crawled properties are found: ows_AssignedTo(Text) and ows_Assigned_x0020_To(Text). Those two crawled properties can be mapped to the managed property AssignedTo. From now, in a Search Scope with the property Query “AssignedTo = Bas Lijten” can be used to create a scope where all items that are assigned to “Bas Lijten” can be searched. All items that apply to this rule, have a metadata property (crawled property) ows_AssignedTo or ows_Assigned_x0020_To with the value Bas Lijten

Configuring People Search

Configuring the People Search isn’t that hard. At first, you will need of course, user profiles and their user profile properties. You will have to configure the user import for this. After this, decide what user profile properties need to be indexed. With this index,  the user profile property will be part of the People Search Scope Schema. If a property is indexed, you will be able to search for that element, and you will be able to add that propety as a search result. When those configuration settings are made, the userProfile store needs to be crawled. If i am right, this is not enabled by default. This can be enabled by adding the following entry to one of the content sources:
sps3://mysite-host/

When this entry is added and a full crawl is started, all userProfiles will be added, together with its properties that can be used in a scope now.

In the next parts I will explain how to configure the search centre, how to configure/style the main search box and how to style the peoplesearch page.

SharePoint Search FullTextSqlQuery not returning not all items

Today I was breaking my head on some stupid problem within SharePoint Search. We created a site with about 50 dummy pages to test some cross webapp news aggregation webpart that I created. For some reason just 4(!) news items were found, each one existing in another subweb. In the SSP the View Scopes page also showed the magic number of ‘4’ items found.

THe problem? I forgot to set the following property to false, which is set to true by default:

query.TrimDuplicates = false;

It makes sure that items that look like each other, won’t be returned as a result. Due to the fact that i had 50 of the same dummy pages, just one item per subweb was returned.