Advanced Search option Programatically Sharepoint Search - sharepoint

I am using object code model to retrieve search result from sharepoint search..Can any one suggest how do i put advanced search option for my search.Do object code model has the feature to perform advanced search.

Yes, you can perform advanced searches using the FullTextSqlQuery class as shown in the code example below. See also Best Practices: Writing SQL Syntax Queries for Relevant Results in Enterprise Search.
using (SPSite site = new SPSite("http://server")) // Site Collection URL
using (FullTextSqlQuery query = new FullTextSqlQuery(site))
{
query.ResultTypes = ResultType.RelevantResults;
query.EnableStemming = true;
query.TrimDuplicates = true;
query.Culture = new CultureInfo(1033); // Use en-US stemmer and word-breaker
query.RowLimit = 40;
query.StartRow = 0;
query.KeywordInclusion = KeywordInclusion.Allkeywords; // Implicit AND search
query.HighlightedSentenceCount = 3;
query.SiteContext = new Uri("http://server"); // Site Collection URL
query.QueryText = "SELECT WorkId, Title, Path, HitHighlightedSummary, HitHighlightedProperties, CollapsingStatus, Description, Rank, Size" +
" FROM SCOPE()" +
" WHERE \"scope\" = 'A Scope'" +
" AND FREETEXT(defaultproperties, 'keyword1 keyword2')" +
" AND Color = 'Black'" + // Color is a managed property
" ORDER BY Rank DESC";
ResultTableCollection results = query.Execute();
ResultTable relevantResults = results[ResultType.RelevantResults];
// TODO: Process results
};

Related

I have a list A with columns and another List B column name same as List A, all are single line text and I want to retrieve all the data

I have a list A with columns Title, Emp ID & Start Date and End Date, Designation, in List A I have some data, and another List B column name same as List A, all are single line text and I want to retrieve all the data which is in List A using Visual Studio.
//Code
using System.Net;
using Microsoft.SharePoint.Client;
using (ClientContext context = new ClientContext("http://yourserver.sharepoint.com/")) {
context.Credentials = new NetworkCredential("user", "password", "domain");
List announcementsList = context.Web.Lists.GetByTitle("List A");
// This creates a CamlQuery that has a RowLimit of 100, and also specifies Scope="RecursiveAll"
// so that it grabs all list items, regardless of the folder they are in.
CamlQuery query = CamlQuery.CreateAllItemsQuery(100);
ListItemCollection items = announcementsList.GetItems(query);
// Retrieve all items in the ListItemCollection from List.GetItems(Query).
context.Load(items);
context.ExecuteQuery();
foreach (ListItem listItem in items)
{
// We have all the list item data. For example, Title.
label1.Text = label1.Text + ", " + listItem["Title"];
//label2.Text = label2.Text + ", " + listItem["Emp_x0020_ID"];
//EMP_x0020_ID could be internal name of SharePoint list column "EMP ID"
//Likewise check the column internal name for all the columns
//To find internal name, go to list settings and click each column
//you will see towards the end of the url something like &Field=Emp_x0020_ID
//"Emp_x0020_ID" is the internal name of the field
}
}
I hope this helps
Your question is tagged with sharepoint-online so this code will work for you. Instead of NetworkCredential (as stated in answer by #Dhurba) you have to use SharePointOnlineCredentials.
string userName = "";
string password = "";
string siteUrl = "https://tenant.sharepoint.com";
using (ClientContext cc = new ClientContext(siteUrl))
using (SecureString securedPassword = new SecureString())
{
password.ToList().ForEach(c => securedPassword.AppendChar(c));
cc.Credentials = new SharePointOnlineCredentials(userName, securedPassword);
// Load only server relative url
cc.Load(cc.Web, p => p.ServerRelativeUrl);
cc.ExecuteQuery();
// Get list by url - better than by title, because title can be different in other languages
List list = cc.Web.GetList($"{cc.Web.ServerRelativeUrl.TrimEnd('/')}/Lists/SomeListUrl");
// Load all items even if the list contains more than 5000 items,
// which is hard limit in SharePoint Online, using paggination
CamlQuery query = CamlQuery.CreateAllItemsQuery(200);
do
{
ListItemCollection items = list.GetItems(query);
cc.Load(items);
cc.ExecuteQuery();
foreach (ListItem item in items)
{
Console.WriteLine($"ID: {item.Id} | {item["InternalNameOfColumn"]}");
}
// Set position info to query
query.ListItemCollectionPosition = items.ListItemCollectionPosition;
// When there are no other items the position info will be null
} while (query.ListItemCollectionPosition != null);
}
Note:
If you are using older Visual Studio than 2017, the interpolation $"{someVariable}" will not work and you will have to replace it with eg. string.Format("{0}", someVariable).

(401) Unauthorized exception while downloading file from SharePoint

I have generated an access token using OAuth mechanism for SharePoint Online server. I am using this token to create ClientContext using CSOM. While I am able to access all the sites, libraries, and folders seamlessly, I get error
The remote server returned an error: (401) Unauthorized.
while downloading the file from SharePoint Online. Below is the code that I am using for file download:
var clientContext = TokenHelper.GetClientContextWithAccessToken("https://adventurer.sharepoint.com/Subsite1", accessToken);
var list = clientContext.Web.Lists.GetByTitle("SubSite 1 Library 1");
string vquery = #"<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='UniqueId' /><Value Type='Lookup'>" + "6718053d-a785-489c-877f-5a4b88dcb2a7" + "</Value></Eq></Where></Query></View>";
CamlQuery query = new CamlQuery();
query.ViewXml = vquery;
var listItems = list.GetItems(query);
clientContext.Load(listItems, items => items.Take(1).Include(item => item.File));
clientContext.ExecuteQuery();
var fileRef = listItems[0].File.ServerRelativeUrl;
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, fileRef);
I don't understand the root cause of this error, as I am passing client context with right access token. I want to know if OpenBinaryDirect has a limitation to work with access tokens? If not, what is wrong with above code? Is there any other alternative that can be used to download using access token?
After trying a lot of alternatives, I have come to conclusion that OpenBinaryDirect() cannot be used with OAuth tokens. I was able to download file from SharePoint Online using two other approaches. I am posting the answers here so that it might help someone:
Approach 1 (OpenBinaryStream):
var file = clientContext.Web.GetFileByServerRelativeUrl(fileRef);
clientContext.Load(file);
clientContext.ExecuteQuery();
ClientResult<Stream> streamResult = file.OpenBinaryStream();
clientContext.ExecuteQuery();
While this approach works perfectly, OpenBinaryStream is not available in Microsoft.SharePoint.Client.dll <= v 14.0.0.0.
Approach 2 (WebClient or Other Http Requests):
string downloadUrl = HostURL + "/_api/web/getfilebyserverrelativeurl('" + fileRef + "')/$value";
WebClient client = new WebClient();
client.Headers.Add("Authorization", "Bearer " + accessToken);
client.DownloadFile(downloadUrl, filePath);
Note the download URL that I have used for WebClient. Normal file URL will not work to download files from SharePoint Online.
I am using C# and here is how I am currently retrieving documents from SharePoint Online. I am showing the user a list of their documents in a gridview, so I populate a DataTable with the documents. I am unsure of a way using an Access Token, but if you are able to use a Service Account like I am, then hopefully this helps you.
Namespaces
using Microsoft.SharePoint.Client;
using SP = Microsoft.SharePoint.Client;
Object Attributes
SecureString securePassword = new SecureString();
private string username = "";
ClientContext context = new SP.ClientContext("https://<root>.sharepoint.com/<site collection (unless root)>/<site>");
Constructor (This is how I am authenticating)
public SharePoint()
{
securePassword = convertToSecureString(System.Web.Configuration.WebConfigurationManager.AppSettings["O365PW"]);
username = System.Web.Configuration.WebConfigurationManager.AppSettings["O365UN"];
context.Credentials = new SharePointOnlineCredentials(username, securePassword);
}
Method to get documents
public DataTable GetDocuments(int changeID)
{
DataTable dt = new DataTable("ChangeDocuments");
DataRow dr = dt.NewRow();
dt.Columns.Add("Title");
dt.Columns.Add("URL");
dt.Columns.Add("ChangeID");
dt.Columns.Add("Modified");
dt.Columns.Add("ID");
// The SharePoint web at the URL.
Web web = context.Web;
// We want to retrieve the web's properties.
context.Load(web);
// We must call ExecuteQuery before enumerate list.Fields.
context.ExecuteQuery();
// Assume the web has a list named "Announcements".
SP.List oList = context.Web.Lists.GetByTitle("Name of your document library");
// This creates a CamlQuery that has a RowLimit of 100, and also specifies Scope="RecursiveAll"
// so that it grabs all list items, regardless of the folder they are in.
CamlQuery query = CamlQuery.CreateAllItemsQuery(100);
query.ViewXml = "<View><Query><Where><Eq><FieldRef Name='ChangeID'/>" +
"<Value Type='Number'>" + changeID + "</Value></Eq></Where></Query><RowLimit>100</RowLimit></View>";
SP.ListItemCollection items = oList.GetItems(query);
// Retrieve all items in the ListItemCollection from List.GetItems(Query).
context.Load(items);
context.ExecuteQuery();
foreach (Microsoft.SharePoint.Client.ListItem listItem in items)
{
// We have all the list item data. For example, Title.
dr = dt.NewRow();
dr["Title"] = listItem["FileLeafRef"];
if (String.IsNullOrEmpty(listItem["ServerRedirectedEmbedUrl"].ToString()))
{
dr["URL"] = "<root>/<site>/<document library>" + listItem["FileLeafRef"].ToString();
}
else
{
dr["URL"] = listItem["ServerRedirectedEmbedUrl"];
}
dr["ChangeID"] = listItem["ChangeID"];
dr["Modified"] = Convert.ToDateTime(listItem["Modified"]).ToString("MMM.dd,yyyy h:mm tt");
dr["ID"] = listItem["ID"];
dt.Rows.Add(dr);
}
return dt;
}
Method to convert password to secure string
private SecureString convertToSecureString(string strPassword)
{
var secureStr = new SecureString();
if (strPassword.Length > 0)
{
foreach (var c in strPassword.ToCharArray()) secureStr.AppendChar(c);
}
return secureStr;
}

Sitecore HOWTO: Search item bucket for items with specific values

I have an item bucket with more then 30 000 items inside. What I need is to quickly search items that have particular field set to particular value, or even better is to make something like SELECT WHERE fieldValue IN (1,2,3,4) statement. Are there any ready solutions?
I searched the web and the only thing I found is "Developer's Guide to Item
Buckets and Search" but there is no code examples.
You need something like this. The Bucket item is an IIndexable so it can be searched using Sitecore 7 search API.
This code snippet below can easily be adapted to meet your needs and it's just a question of modifying the where clause.if you need any further help with the sitecore 7 syntax just write a comment on the QuickStart blog post below and I'll get back to you.
var bucketItem = Sitecore.Context.Database.GetItem(bucketPath);
if (bucketItem != null && BucketManager.IsBucket(bucketItem))
{
using (var searchContext = ContentSearchManager.GetIndex(bucketItem as IIndexable).CreateSearchContext())
{
var result = searchContext.GetQueryable<SearchResultItem().Where(x => x.Name == itemName).FirstOrDefault();
if(result != null)
Context.Item = result.GetItem();
}
}
Further reading on my blog post here:
http://coreblimey.azurewebsites.net/sitecore-7-search-quick-start-guide/
Using Sitecore Content Editor:
Go to the bucket item then In search tab, start typing the following (replace fieldname and value with actual field name and value):
custom:fieldname|value
Then hit enter, you see the result of the query, you can multiple queries at once if you want.
Using Sitecore Content Search API:
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Linq;
using Sitecore.ContentSearch.SearchTypes;
using Sitecore.ContentSearch.Linq.Utilities
ID bucketItemID = "GUID of your bucket item";
ID templateID = "Guid of your item's template under bucket";
string values = "1,2,3,4,5";
using (var context = ContentSearchManager.GetIndex("sitecore_web_index").CreateSearchContext())
{
var predicate = PredicateBuilder.True<SearchResultItem>();
predicate = PredicateBuilder.And(item => item.TemplateId == new ID(templateID)
&& item.Paths.Contains(bucketItemID));
var innerPredicate = PredicateBuilder.False<SearchResultItem>();
foreach(string val in values.Split(','))
{
innerPredicate = PredicateBuilder.False<SearchResultItem>();
innerPredicate = innerPredicate.Or(item => item["FIELDNAME"] == val);
}
predicate = predicate.And(innerPredicate);
var result = predicate.GetResults();
List<Item> ResultsItems = new List<Item>();
foreach (var hit in result.Hits)
{
Item item = hit.Document.GetItem();
if(item !=null)
{
ResultsItems .Add(item);
}
}
}
The following links can give good start with the Search API:
http://www.fusionworkshop.co.uk/news-and-insight/tech-lab/sitecore-7-search-a-quickstart-guide#.VPw8AC4kWnI
https://www.sitecore.net/learn/blogs/technical-blogs/sitecore-7-development-team/posts/2013/06/sitecore-7-poco-explained.aspx
https://www.sitecore.net/learn/blogs/technical-blogs/sitecore-7-development-team/posts/2013/05/sitecore-7-predicate-builder.aspx
Hope this helps!

SharePoint 2013 - Get SPListItem versions via REST

I have a SharePoint 2013 List with versioning enabled.
I need to to get SPListItem versions list via REST.
I can get SPListItem by that request: http://spbreportportal/Projects/_api/lists/getbytitle('Projects')/Items(1)
But I can't find in documentation and in response how to retrieve all versions of this item.
Is it possible?
It does not seem possible to get versions for a List Item via REST/CSOM APIs, but there are alternative options
Using Versions.aspx application page
The idea is to perform a get request to Versions page: http://<server>/<site>/_layouts/versions.aspx?list={litsID}&ID=<itemID>
function getItemVersions(url,listId,itemId,success)
{
var versionsUrl = url + '/_layouts/versions.aspx?list=' + listId + '&ID=' + itemId;
$.get( versionsUrl, function( data ) {
var versionEntries = parseVersionList(data);
success(versionEntries);
});
}
function parseVersionList(data){
var entries = {};
var versionList = $(data).find('table.ms-settingsframe');
versionList.find('tbody > tr').each(function(i){
if(i > 0 && (i-1) % 2 == 0) {
var verRow = $(this); //get version row
var propsRow = verRow.next(); //get properties row
var versionLabel = verRow.find('td:first').html().trim();
entries[versionLabel] = {};
//extract item properties from propsRow goes here
//...
}
});
return entries;
}
//Usage
var webUrl = _spPageContextInfo.webAbsoluteUrl;
var listId = _spPageContextInfo.pageListId;
var listItemId = 1;
getItemVersions(webUrl,listId,listItemId,function(versionEntries){
console.log(versionEntries);
});
Using Lists SharePoint Web Services
Another option would be to utilize Lists SharePoint Web Services that exposes Lists.GetVersionCollection Method to return version information for the specified field in a SharePoint list
SPServices example:
$().SPServices({
operation: "GetVersionCollection",
async: false,
strlistID: "Projects",
strlistItemID: 1,
strFieldName: "Description",
completefunc: function (xData, Status) {
$(xData.responseText).find("Version").each(function(i) {
console.log("Name: " + $(this).attr("Description") + " Modified: " + $(this).attr("Modified"));
});
}
});
Note: This doesn't seem to work in 2013. I have verified this working in SharePoint Online and it may work in 2016+ but I have not verified the latter.
The situation may have changed since this question was originally posted, but it is now possible to use the REST API to get version history for any list/library item:
https://url/to/site/_api/web/Lists/getbytitle('MyListName')/items(ITEMID)/versions
This will return a series of results for the current version and all past versions, with the item's column values from each version.
As with other REST endpoints, you can use $select, $filter, etc. to further manipulate the results.
In the REST API, you can select the property OData__UIVersionString. It also supports OData__ModerationStatus
Ex:
GET http://site url/_api/web/lists/GetByTitle(‘Test')/items(item id)?$select=OData__UIVersionString,OData__ModerationStatus
More infos : https://msdn.microsoft.com/en-us/library/office/dn292552.aspx
It's not a solution to get all the versions or a specific version, but it's more info on the version.
To add to #Vadim Gremyachev's Excellent answer to use "GetversionCollection": This interface can also be reached using old school SOAP. Unfortunately it only returns one field at the time (so we use a lot of calls ...). The C# snippet is below.
//https://blogs.msdn.microsoft.com/pinch-perfect/2016/06/04/sharepoint-web-services-read-version-history-for-column-changes/
//http://www.indy.gov/eGov/City/DCE/Permits/Signs/_vti_bin/lists.asmx?op=GetVersionCollection
//https://www.codeproject.com/Articles/26338/Using-the-GetListItems-GetVersionCollection-and-Up
string strSite =
string strListGuid =
string strListItemID =
string strFieldName = "Title" // or some other field name
string requestXML = "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>" +
"<soap:Body>" +
"<GetVersionCollection xmlns='http://schemas.microsoft.com/sharepoint/soap/'>" +
"<strlistID>"+ strListGuid + "</strlistID><strlistItemID>" + strListItemID + "</strlistItemID>" +
"<strFieldName>"+ strFieldName +"</strFieldName>" +
"</GetVersionCollection>" +
"</soap:Body>" +
"</soap:Envelope>";
object xmlRequestObj = Activator.CreateInstance(Type.GetTypeFromProgID("Microsoft.XMLHTTP"));
MSXML2.XMLHTTP xmlRequest = (MSXML2.XMLHTTP)xmlRequestObj;
xmlRequest.open("Get", strSite + "/_vti_bin/Lists.asmx", false, null, null);
xmlRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/sharepoint/soap/GetVersionCollection");
xmlRequest.send(requestXML);
string responseText = xmlRequest.responseText;
To add more information reagrding on how to obtain all version history from a SharePoint list:
//Get ID of the Dossier in SP list
strID = items(i - 1).getAttribute("ows_ID")
Debug.Print strID
//Get all Versions of the ID in SP list as a XML
URL1: https://path to site collection/_vti_bin/owssvr.dll?Cmd=Display&List={LIstID}&XMLDATA=TRUE&Query=*&IncludeVersions=TRUE
XDoc3.Load (URL1 & "&FilterField1=ID&FilterOp1=eq&FilterValue1=" & strID)
Set Item = XDoc3.SelectNodes("//rs:data/*")
Set temp3 = XDoc3.SelectNodes("//rs:data/*")

Sharepoint 2013 extend ContentBySearchWebpart

My Query in Short :
I extended ContentBySearchWebpart, so that i could create my custom Query for Search. I modified the DataProviderJSON Property and added my custom QueryTemplate in it. But the Webpart renders with default results
What i am trying to do :
I created a catalog site collection and other publishing site collection
Created a List in catalog site, enabled it as catalog, made connection of this catalog in publishing site.
Added CSWP in publishing site Whose Result Source is the above catalog connection.
Now i want to customize my query
I have solved my problem. We are required to set some of the base properties in constructor of our extended webpart. Below is a code sample :
string dataProviderJson = "{{'Properties':{{'TryCache':true,'Scope':'{0}','HHTitle_WB_Marker1':50,'HHTitle_WB_Marker2':60,'UpdateLinksForCatalogItems':true,'EnableStacking':true,'searchTerms':'','Tag':''}},'QueryGroupName':'Default','SourceID':'8413cd39-2156-4e00-b54d-11efd9abdb89','SourceName':'Local SharePoint Results (System)','SourceLevel':'Ssa','CollapseSpecification':'','QueryTemplate':'{{searchTerms?}} (contentclass:sts_listitem OR IsDocument:True) SPSiteUrl:{1} ListId:3d001e7a-d856-428b-9785-edf7ec4f4876 {{?owstaxidMetadataRegion:{{Tag}}}} owstaxIdMetadataRegion:{2}','FallbackSort':[{{'p':'Rank','d':0}}],'RankRules':[],'AsynchronousResultRetrieval':false,'SendContentBeforeQuery':true,'BatchClientQuery':true,'FallbackLanguage':-1,'FallbackRankingModelID':'8f6fd0bc-06f9-43cf-bbab-08c377e083f4','EnableStemming':true,'EnablePhonetic':false,'EnableNicknames':false,'EnableInterleaving':true,'EnableQueryRules':true,'EnableOrderingHitHighlightedProperty':false,'HitHighlightedMultivaluePropertyLimit':-1,'IgnoreContextualScope':false,'ScopeResultsToCurrentSite':false,'TrimDuplicates':true,'ClientType':'ContentSearchRegular','UpdateAjaxNavigate':true,'SummaryLength':180,'DesiredSnippetLength':90,'PersonalizedQuery':false,'FallbackRefinementFilters':null,'IgnoreStaleServerQuery':false,'RenderTemplateId':'DefaultDataProvider','AlternateErrorMessage':null,'Title':''}}";
string siteUrl = SPContext.Current.Site != null ? SPContext.Current.Site.Url.Trim() : "";
base.ResultsPerPage = 3;
base.BypassResultTypes = true;
base.AlwaysRenderOnServer = false;
dataProviderJson = String.Format(dataProviderJson, siteUrl, siteUrl + "/sites/Catalog", "en");
base.DataProviderJSON = dataProviderJson;
base.ItemTemplateId = "/_catalogs/masterpage/Display Templates/Content Web Parts/Banner.js";
base.GroupTemplateId = "/_catalogs/masterpage/Display Templates/Content Web Parts/Group_Content.js";
base.SelectedPropertiesJson = "['PublishingImage','PictureURL','PictureThumbnailURL','Path','Title','Description','SecondaryFileExtension','ContentTypeId']";
base.HitHighlightedPropertiesJson = "['Title','Path','Author','SectionNames','SiteDescription']";
base.QueryGroupName = "Default";
base.RenderTemplateId = "/_catalogs/masterpage/Display Templates/Content Web Parts/Control_Banner.js";
base.StatesJson = "{}";
base.Title = "Banner Search WebPart";
base.Description = "Banner Search WebPart";
base.AllowMinimize = true;
AllowConnect = true;
AllowEdit = true;
AllowHide = true;
base.ZoneID = "ImportedPartZone";

Resources