Saturday, July 27, 2013

Problem in KQL with date times and client object model in Sharepoint

Keyword query language (KQL) is the one of the basic ways to perform queries to the search index in Sharepoint 2013. When you use it e.g. in Content by search web parts (ContentBySearchWebPart) in order to show results based on specified parameters you may get the following error:

image

(We didn't understand your search terms. Make sure you're using the proper syntax).

Even stranger that the same page may work correctly (i.e. show search results) in one browser, but broken in another. In our case Content by search web part worked in IE10, but didn’t work in FF and Chrome. So what’s the reason of this behavior?

First of all let’s check ULS (as always). In my case there were several interesting records:

QueryTemplateHelper: Query template '(PublishingDate=1/1/{QueryString.Year}..31/12/{QueryString.Year})' transformed to query text '(PublishingDate=1/1/2013..31/12/2013)'

It shows how query transformation component transformed the search query. In this example we use year specified in query string in order to show all news for specific year. Transformed query was the same for IE and FF, so the problem was somewhere else.

Next interesting line was:

ExecuteFlowInternal Flow:Microsoft.SharePointSearchProviderFlow Exception: Microsoft.Office.Server.Search.Query.QueryMalformedException: Query '(PublishingDate=1/1/2013..31/12/2013)' failed: syntax error at position 1, Unable to parse '31/12/2013' as an absolute datetime value

it appeared only in FF where query didn’t work. So the problem was in the datetime format: Sharepoint couldn’t parse datetime string in FF and Chrome. But why it happened? Very often such problems occur because of different locales used for parsing the string. I checked languages settings in IE10 (there is no separate setting for languages now in IE. It uses languages specified in OS) and FF: there was difference. In IE there was Russian and English (US) languages, while in FF there was only English (US). Accordingly in http requests fiddler showed the following Accept-Language headers in the browsers:

  • Accept-Language: ru,en-us – in IE
  • Accept-Language: en-us – in FF

When I added Russian language to FF, search queries started to work, but we couldn’t use this solution in production of course: site shouldn’t rely on the client’s browser language setting, it should work in all cases. So I started deeper investigation.

First of all in Sharepoint 2013 there is convenient way to test search queries from UI against particular search result source: go to Site settings > Search result sources > select appropriate result source and click Edit. Then click Launch query builder button:

image

In the opened window write your query and click Test query. Here is the result in FF:

image

If we will check what happens in fiddler when you click on the Test query button, we will find that Sharepoint makes request to the client object model end point to the following URL:

http://example.com//_vti_bin/client.svc/ProcessQuery

It returns response in JSON format. In case of FF it returned exception:

[
{
"SchemaVersion":"15.0.0.0","LibraryVersion":"15.0.4420.1017","ErrorInfo":null,"TraceCorrelationId":"9213339c-4c53-3023-9599-62e1b6279428"
},185,{
"IsNull":false
},193,{
"IsNull":false
},197,{
"IsNull":false
},205,{
"IsNull":false
},219,{
"IsNull":false
},220,{
"HasException":true,"ErrorInfo":{
"ErrorMessage":"We didn't understand your search terms. Make sure they're using proper syntax.","ErrorValue":null,"TraceCorrelationId":"9213339c-4c53-3023-9599-62e1b6279428","ErrorCode":-1,"ErrorTypeName":"Microsoft.Office.Server.Search.Query.QueryMalformedException"
}
}
]

And in IE it returned actual search results. I.e. it seems like that client object model uses browser language for some operations. For example it uses it for datetimes parsing when KQL contains datetimes. Don’t know why MS did it like this, but it often will be a problem because you don’t want to rely on client browsers settings, functionality should work regardless of it.

But how to fix the problem? First of all I tried different syntaxes for the range operator in KQL:

PublishingDate=1/1/2013..31/12/2013
PublishingDate=1.1.2013..31.12.2013
PublishingDate=1/1/2013..12/31/2013

All of them had similar problem: depend on the browser language. The I tried to add the following line to the web.config in order to disabled changing UI settings based on the browser language:

<globalization fileEncoding="utf-8" enableClientBasedCulture="false" />

(tried to change it both in site virtual folder and in 15\isapi folder which is mapped to _vti_bin virtual sub folder in Sharepoint sites).

I already started to think about hard fix: implement custom http module which will change Accept-Language header for requests to the client object model end point (client.svc), but then tried to use one more syntax for datetimes:

PublishingDate=2013/1/1..2013/12/31

And fortunately it worked regardless of the browser language:

image

When I changed the year in the query it correctly showed the news published in this changed year, so logic was correct.

Important summary from this post is that Sharepoint uses browser language settings in client object model which may lead to different problems. In the example above solution was quite easy and doesn’t have side effects which would affect other functionality, but it may appear in other cases. Notice it when you will work with search-driven sites in Sharepoint 2013.

No comments:

Post a Comment