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";
Related
I am trying to remove a piece of code from sharepoint master page from a lot of sites,so is it possible to manipulate the master page content using csom.
As a workaround, get the master page from Master Page Gallery using CSOM, modify the file and replace some content in the file, then set master page using this:
web.CustomMasterUrl = masterUrl;
Articles:
Set Custom Master Page through CSOM SharePoint
C# Search/Replace in Files
var rootWeb = clientContext.Site.RootWeb;
clientContext.Load(rootWeb);
clientContext.ExecuteQuery();
string CustomMasterPage = rootWeb.CustomMasterUrl;
var masterPagefile = rootWeb.GetFileByServerRelativeUrl(CustomMasterPage);
var stream = masterPagefile.OpenBinaryStream();
clientContext.Load(masterPagefile);
clientContext.ExecuteQuery();
if (masterPagefile.CheckOutType == CheckOutType.None)
{
using (var reader = new StreamReader(stream.Value, Encoding.UTF8))
{
masterPageContent = reader.ReadToEnd();
}
masterPagefile.CheckOut();
clientContext.ExecuteQuery();
var catalog = clientContext.Site.GetCatalog((int)ListTemplateType.MasterPageCatalog);
var files = catalog.RootFolder.Files;
clientContext.ExecuteQuery();
var fileCreationInformation = new FileCreationInformation();
fileCreationInformation.Content = Encoding.UTF8.GetBytes(masterPageContent);
fileCreationInformation.Overwrite = true;
fileCreationInformation.Url = rootWeb.CustomMasterUrl;
files.Add(fileCreationInformation);
clientContext.ExecuteQuery();
masterPagefile.CheckIn(" Test", CheckinType.MinorCheckIn);
clientContext.ExecuteQuery();
}
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;
}
You can add a new search scope via powershell:
New-SPEnterpriseSearchQueryScope -SearchApplication "Search Service Application" -Name NewSearchScope -Description "New Search Test Scope" -DisplayInAdminUI 1–OwningSiteUrl http://servername/sites/
But does anyone know of sample code that shows how to do this via OM ? (using the Microsoft.SharePoint.Administration namespace rather than Microsoft.Office.Server.Search)
any pointers will be great
regards
Mo
*Update**
ignoring error handling / logging etc, is this a valid way of doing this:
SPSite siteColl = (SPSite)properties.Feature.Parent;
Microsoft.SharePoint.Administration.SPServiceApplication spserviceapp = siteColl.SearchServiceInstance.Service.Applications["Search Service Application"];
SearchServiceApplication searchserviceapp = (SearchServiceApplication)spserviceapp;
ScopeInfo scopeInfo = new ScopeInfo();
scopeInfo.Name = "Scope test1";
scopeInfo.Description = "Scope test1";
scopeInfo.DisplayInAdminUI = true;
scopeInfo.CompilationType = ScopeCompilationType.AlwaysCompile;
scopeInfo.CompilationState = ScopeCompilationState.NeedsCompile;
int statusCode = 0;
int scopeId = searchserviceapp.AddScope(scopeInfo, out statusCode);
if (scopeId > 0)
{
RuleInfo ruleInfo;
ruleInfo = new RuleInfo();
ruleInfo.FilterBehavior = ScopeRuleFilterBehavior.Include;
ruleInfo.RuleType = ScopeRuleType.AllContent;
int ruleId = searchserviceapp.AddRule(ruleInfo, scopeId);
}
searchserviceapp.Update(true);
rather then the ssp way of searchcontext?
SearchContext searchctx = null;
searchctx = SearchContext.GetContext(web.Site);
Scopes scopes = new Scopes(searchctx);
Scope currentScope = scopes.AllScopes.Create(
"CurrentScopeName", string.Empty, new Uri(web.Site.Url), true,
string.Format("{0}/Search/Pages/Results.aspx", web.Site.Url),
ScopeCompilationType.AlwaysCompile);
currentScope.Update();
currentScope.Rules.CreateUrlRule(ScopeRuleFilterBehavior.Include,
UrlScopeRuleType.Domain, web.Site.Url);
ScopeDisplayGroup group = scopes.GetDisplayGroup(new Uri(web.Url),
"Search Dropdown"); group.Add(currentScope);
group.Update();
scopes.StartCompilation();
scopes.Update();
SearchContext is marked as obsolete in SharePoint 2010 Server, so it is not the recommended way of doing it.
Also, see this answer on SharePoint Overflow.
I need to know what is the best practice for sending emails from my sharepoint webparts and/or customized features.
Should I just use the normal .Net classes to send email ? or is their a better way to do it through integration with an outlook server ?
Easy way is to use the built in Utilities, this will then use the mail server setttings setup in central admin
using Microsoft.SharePoint.Utilities;
SPUtility.SendEmail(SPContext.Current.Web, false, false,
"toaddress#mail.com", "subject",
"body");
Universal way to send email in any context(where SPWeb not available) is read OutboundMailService settings which is used in SPUtility. Then create SmtpClient manually:
var adminApp = SPAdministrationWebApplication.Local;
var instance = adminApp.OutboundMailServiceInstance;
var server = instance.Server.Address;
var defaultFrom = adminApp.OutboundMailSenderAddress;
var client = new SmtpClient();
client.Host = server;
message.From = new MailAddress(defaultFrom );
...
You also can use this code for dynamic mail id. this code gets the mail according to the user. I have used CAML query to get the data for the email content from the lists.
SPUser AssigUser = oWeb.EnsureUser(Assigned_Username);
SPQuery mquery = new SPQuery();
mquery.Query = #"<Where><Eq><FieldRef Name='Email_x0020_Type' />
<Value Type='Text'>Review - Ready for Review</Value>
</Eq></Where>";
string Emailsub = "";
string Emailbody = "";
SPList mList = oWeb.Lists["Email Content"];
SPListItemCollection itemcollection = mList.GetItems(mquery);
foreach (SPListItem item in itemcollection)
{
Emailsub = item["Email Subject"].ToString();
Emailbody = item["Email Content"].ToString();
SPUtility.SendEmail(oWeb, false, false, AssigUser.Email, Emailsub,
Emailbody + "</br>" + oWeb.Url);
break;
}
using overload with StringDictionary arguments (source)
StringDictionary headers = new StringDictionary();
headers.Add("to", currCtxt.Web.CurrentUser.Email);
headers.Add("cc", "xyz#abc.com");
headers.Add("bcc", "");
headers.Add("from", "email#add.com");
headers.Add("subject", "Email Subject");
headers.Add("content-type", "text/html");
string bodyText = "Hello how are you?";
SPUtility.SendEmail(currCtxt.Web, headers, bodyText.ToString());
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
};