Search code examples
c#sharepoint-onlinecsomsharepoint-searchkeywordquery

SharePoint CSOM KeywordQuery - Field or property "QueryText" does not exist


I am attempting to search files and folders held in SharePoint for a user entered phrase but consistently get the following exception:

Microsoft.SharePoint.Client.ServerException
  HResult=0x80131500
  Message=Field or property "QueryText" does not exist.
  Source=Microsoft.SharePoint.Client.Runtime
  StackTrace:
   at Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream(Stream responseStream)
   at Microsoft.SharePoint.Client.ClientRequest.ProcessResponse()
   at Microsoft.SharePoint.Client.ClientRequest.<ExecuteQueryToServerAsync>d__53.MoveNext()
   at Microsoft.SharePoint.Client.ClientRequest.<ExecuteQueryAsync>d__39.MoveNext()
   at Microsoft.SharePoint.Client.ClientRuntimeContext.<ExecuteQueryAsync>d__57.MoveNext()
   at Microsoft.SharePoint.Client.ClientContext.<ExecuteQueryAsync>d__23.MoveNext()
   at SharePointAccessTest.Program.<Main>d__0.MoveNext() in C:\Repos\POC\SharePointAccessTest\Program.cs:line 78

I am using the latest release (1.11.0) of PnP.Framework which uses the SharePoint client object model (CSOM).

I would love to use the newer PnP.Core package or even the Microsoft Graph packages but the way my client has SharePoint set up they are not willing to give the app the necessary graph permissions!

Here's the request that is sent to SharePoint that I managed to capture using Fiddler Classic:

POST https://**redacted**.sharepoint.com/sites/Site/SubSite/_vti_bin/client.svc/ProcessQuery HTTP/1.1
Host: **redacted**.sharepoint.com
Authorization: Bearer ***redacted***
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Content-Type: text/xml
Content-Length: 1112

<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName=".NET Library" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions><ObjectPath Id="2" ObjectPathId="1" /><ObjectPath Id="4" ObjectPathId="3" /><ObjectPath Id="6" ObjectPathId="5" /><ObjectPath Id="8" ObjectPathId="7" /><ObjectIdentityQuery Id="9" ObjectPathId="7" /><SetProperty Id="10" ObjectPathId="7" Name="QueryText"><Parameter Type="String">test</Parameter></SetProperty><ObjectPath Id="12" ObjectPathId="11" /><Method Name="ExecuteQuery" Id="13" ObjectPathId="11"><Parameters><Parameter ObjectPathId="7" /></Parameters></Method></Actions><ObjectPaths><StaticProperty Id="1" TypeId="{3747adcd-a3c3-41b9-bfab-4a64dd2f1e0a}" Name="Current" /><Property Id="3" ParentId="1" Name="Web" /><Property Id="5" ParentId="3" Name="Lists" /><Method Id="7" ParentId="5" Name="GetByTitle"><Parameters><Parameter Type="String">Published Documents</Parameter></Parameters></Method><Constructor Id="11" TypeId="{8d2ac302-db2f-46fe-9015-872b35f15098}" /></ObjectPaths></Request>

Here's the formatted XML:

<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0"
    ApplicationName=".NET Library" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009">
    <Actions>
        <ObjectPath Id="2" ObjectPathId="1" />
        <ObjectPath Id="4" ObjectPathId="3" />
        <ObjectPath Id="6" ObjectPathId="5" />
        <ObjectPath Id="8" ObjectPathId="7" />
        <ObjectIdentityQuery Id="9" ObjectPathId="7" />
        <SetProperty Id="10" ObjectPathId="7" Name="QueryText">
            <Parameter Type="String">test</Parameter>
        </SetProperty>
        <ObjectPath Id="12" ObjectPathId="11" />
        <Method Name="ExecuteQuery" Id="13" ObjectPathId="11">
            <Parameters>
                <Parameter ObjectPathId="7" />
            </Parameters>
        </Method>
    </Actions>
    <ObjectPaths>
        <StaticProperty Id="1" TypeId="{3747adcd-a3c3-41b9-bfab-4a64dd2f1e0a}" Name="Current" />
        <Property Id="3" ParentId="1" Name="Web" />
        <Property Id="5" ParentId="3" Name="Lists" />
        <Method Id="7" ParentId="5" Name="GetByTitle">
            <Parameters>
                <Parameter Type="String">Published Documents</Parameter>
            </Parameters>
        </Method>
        <Constructor Id="11" TypeId="{8d2ac302-db2f-46fe-9015-872b35f15098}" />
    </ObjectPaths>
</Request>

And the formatted response:

[
  {
    "SchemaVersion": "15.0.0.0",
    "LibraryVersion": "16.0.23501.12002",
    "ErrorInfo": {
      "ErrorMessage": "Field or property \"QueryText\" does not exist.",
      "ErrorValue": null,
      "TraceCorrelationId": "8f13a0a0-70f0-6000-48fe-78b17a865d0d",
      "ErrorCode": -1,
      "ErrorTypeName": "Microsoft.SharePoint.Client.InvalidClientQueryException"
    },
    "TraceCorrelationId": "8f13a0a0-70f0-6000-48fe-78b17a865d0d"
  }
]

And finally the code that I am trying to get this to work with in a .NET 6 console app. The app authenticates using client credentials (client ID and secret):

var siteUrl = $"https://{tenantName}.sharepoint.com/sites/Site/SubSite";
using var clientContext = new AuthenticationManager()
    .GetACSAppOnlyContext(siteUrl, clientId, clientSecret))

var documents = clientContext.Web.Lists.GetByTitle("Published Documents");
var query = new KeywordQuery(clientContext, documents.Path)
{
    QueryText = "test",
};

var searchResults = new SearchExecutor(clientContext).ExecuteQuery(query);

await clientContext.ExecuteQueryAsync();

I tried using the latest pre-release version (1.11.129-nightly) and other release versions down to 1.5.0 with no luck.

I have managed to get other aspects of this working and can successfully navigate folder and files, and retrieve file contents but am really stuck with this search functionality.

I am fairly new to SharePoint development and have probably missed something that's really obvious to somebody else but I'm unable to find anything relevant to this error!


Solution

  • I think I figured it out what the problem was. The problem appears to be that I'm trying to query a specific site collection by passing the collection's object path:

    var siteUrl = $"https://{tenantName}.sharepoint.com/sites/Site/SubSite";
    using var clientContext = new AuthenticationManager()
        .GetACSAppOnlyContext(siteUrl, clientId, clientSecret))
    
    var documents = clientContext.Web.Lists.GetByTitle("Published Documents");
    var query = new KeywordQuery(clientContext, documents.Path);
    

    Removing these from siteUrl and keywordQuery seems to stop the error.

    var siteUrl = $"https://{tenantName}.sharepoint.com/";
    using var clientContext = new AuthenticationManager()
        .GetACSAppOnlyContext(siteUrl, clientId, clientSecret))
    
    var query = new KeywordQuery(clientContext);
    

    Although this will now search all sites and lists in the tenant. By adding a path filter though, it seems to restrict the results to the correct list.

    var query = new KeywordQuery(clientContext)
    {
        QueryText = $@"test path:""https://{tenantName}.sharepoint.com/sites/Site/Subsite/Published Documents""",
    };
    

    Caveat: Unfortunately I'm now getting a permissions error but this is a different issue that I'm pursuing with my client.