I am trying to perform a search for documents within a SharePoint site, but I need to apply audience targeting to the results before they are displayed to the user.
I am however struggling to either (a) retrieve the target audience settings within the original query...
using (SPSite site = new SPSite(SPContext.Current.Site.ID)) {
using (FullTextSqlQuery fullText = new FullTextSqlQuery(site)) {
fullText.QueryText = #"select Title, Path, Description, TargetAudience from scope() where ((""scope"" = 'All Sites'))"
+ #" and IsDocument = 1 and freetext(*, '{0}')";
fullText.QueryText = string.Format(fullText.QueryText, this.documentFilter.AllOfTheseWords);
fullText.ResultTypes = ResultType.RelevantResults;
ResultTableCollection resultTableCollection = fullText.Execute();
allofTheseWords = new DataTable();
if (resultTableCollection.Exists(ResultType.RelevantResults)) {
allofTheseWords.Load(resultTableCollection[ResultType.RelevantResults], LoadOption.OverwriteChanges);
}
}
}
or (b) retrieve the list item id (guid) from within the original query so that I can then tie up each result to the original list item (and therefore apply the audience targeting using the list item.
Any suggestions?
I eventually found a way to retrieve the original list item based upon the URL returned from the full text query and then apply the audience targeting test to the list item.
Related
I'm currently building a tool to migrate from a document management system to use SharePoint Online. The main challenge I'm facing is to preserve the details of document authors and creating time. I have checked bunch of of code online but I didn't get success with any of them.
Here are the approaches I used
SharePoint Rest API
Microsoft Graph API
CSOM (using console application)
Here is the code I have so far in CSOM but I'm still not able to update the Author field
li["Title"] = "Update from CSOM";
li["Created"] = DateTime.Now.AddYears(-5);
li["Author"] = author.Id;
li.UpdateOverwriteVersion();
clientContext.ExecuteQuery();
Any idea for how to do this, or if there is any other approach to achieve my goal?
The code works when I did test in my environment.
using (ClientContext context = new ClientContext("https://xxx.sharepoint.com/sites/lee"))
{
string s = "password";
SecureString passWord = new SecureString();
foreach (var c in s)
passWord.AppendChar(c);
context.Credentials = new SharePointOnlineCredentials("admin#xxx.onmicrosoft.com", passWord);
var author = context.Web.EnsureUser("Lee#xxx.onmicrosoft.com");
context.Load(author);
context.ExecuteQuery();
var _List = context.Web.Lists.GetByTitle("List1");
var li = _List.GetItemById(1);
li["Title"] = "Update from CSOM";
li["Created"] = DateTime.Now.AddYears(-5);
li["Author"] = author.Id;
li.UpdateOverwriteVersion();
context.ExecuteQuery();
}
You will need to update the Author and Editor fields at the same time in order to update the CreatedBy field. If you wish to update additional fields at the same time you can. Using SystemUpdate() does not update the Modified date whereas Update() does update the Modified date. See abbreviated sample below.
FieldUserValue userValue = new FieldUserValue();
User newUser = cc.Web.EnsureUser("newAuthor#xxx.onmicrosoft.com");
cc.Load(newUser);
cc.ExecuteQuery();
userValue.LookupId = newUser.Id;
item["Author"] = userValue;
item["Editor"] = userValue;
item.SystemUpdate();
cc.ExecuteQuery();
the ASP.NET_SessionState table grows all the time, already at 18GB, not a sign of ever deleting expired sessions.
we have tried to execute DynamoDBSessionStateStore.DeleteExpiredSessions, but it seems to have no effect.
our system is running fine, sessions are created and end-users are not aware of the issue. however, it doesn't make sense the table keeps growing all the time...
we have triple checked permissions/security, everything seems to be in order. we use SDK version 3.1.0. what else remains to be checked?
With your table being over 18 GB, which is quite large (in this context), it does not surprise me that this isn't working after looking at the code for the DeleteExpiredSessions method on GitHub.
Here is the code:
public static void DeleteExpiredSessions(IAmazonDynamoDB dbClient, string tableName)
{
LogInfo("DeleteExpiredSessions");
Table table = Table.LoadTable(dbClient, tableName, DynamoDBEntryConversion.V1);
ScanFilter filter = new ScanFilter();
filter.AddCondition(ATTRIBUTE_EXPIRES, ScanOperator.LessThan, DateTime.Now);
ScanOperationConfig config = new ScanOperationConfig();
config.AttributesToGet = new List<string> { ATTRIBUTE_SESSION_ID };
config.Select = SelectValues.SpecificAttributes;
config.Filter = filter;
DocumentBatchWrite batchWrite = table.CreateBatchWrite();
Search search = table.Scan(config);
do
{
List<Document> page = search.GetNextSet();
foreach (var document in page)
{
batchWrite.AddItemToDelete(document);
}
} while (!search.IsDone);
batchWrite.Execute();
}
The above algorithm is executed in two parts. First it performs a Search (table scan) using a filter is used to identify all expired records. These are then added to a DocumentBatchWrite request that is executed as the second step.
Since your table is so large the table scan step will take a very, very long time to complete before a single record is deleted. Basically, the above algorithm is useful for lazy garbage collection on small tables, but does not scale well for large tables.
The best I can tell is that the execution of this is never actually getting past the table scan and you may be consuming all of the read throughput of your table.
A possible solution for you would be to run a slightly modified version of the above method on your own. You would want to call the the DocumentBatchWrite inside of the do-while loop so that records will start to be deleted before the table scan is concluded.
That would look like:
public static void DeleteExpiredSessions(IAmazonDynamoDB dbClient, string tableName)
{
LogInfo("DeleteExpiredSessions");
Table table = Table.LoadTable(dbClient, tableName, DynamoDBEntryConversion.V1);
ScanFilter filter = new ScanFilter();
filter.AddCondition(ATTRIBUTE_EXPIRES, ScanOperator.LessThan, DateTime.Now);
ScanOperationConfig config = new ScanOperationConfig();
config.AttributesToGet = new List<string> { ATTRIBUTE_SESSION_ID };
config.Select = SelectValues.SpecificAttributes;
config.Filter = filter;
Search search = table.Scan(config);
do
{
// Perform a batch delete for each page returned
DocumentBatchWrite batchWrite = table.CreateBatchWrite();
List<Document> page = search.GetNextSet();
foreach (var document in page)
{
batchWrite.AddItemToDelete(document);
}
batchWrite.Execute();
} while (!search.IsDone);
}
Note: I have not tested the above code, but it is just a simple modification to the open source code so it should work correctly, but would need to be tested to ensure the pagination works correctly on a table whose records are being deleted as it is being scanned.
I'm looking for the way to get list of the emails and groups of emails from the active directory. The list will be used to populate autocomplete textbox, the same as in Outlook.
Have any of you done something like that in the past using Asp.Net MVC?
I made this in a project some time ago and here are few steps I think you need to take:
Create a directory entry for your domain
Create a directory searcher and initialize it with a filter
Create a search collection searching with previous filter
Iterate your search collection
Get your properties for current iteration
Get your email from property collection
Code example:
DirectoryEntry dir = new DirectoryEntry("LDAP://" + YourDomain, LoginUsername, LoginPassword);
DirectorySearcher search = new DirectorySearcher(dir);
search.Filter = "(&(objectClass=user)(objectCategory=person))";
SearchResultCollection searchResultCollection = search.FindAll();
if (searchResultCollection != null)
{
for (int i = 0; i < searchResultCollection.Count; i++)
{
SearchResult crt= searchResultCollection[i];
PropertyCollection properties= crt.GetDirectoryEntry().Properties;
// get email from properties["email"].Value
}
}
Some useful links: first , second , third
I am trying to use the Remarketing feature for the first time. I have got the Remarketing code from Adwords and placed it on the website.
Looking through the examples; i have garnered the below flow.
With #2 i can associate one of my Userlist with a predefined Adgroup to be shown during Remarketing. My question is how do i link the tracker ID that i have received (looks like var google_conversion_id = 9925XXXXX) with the code below? where is this linking done? UserListConversionTypes and BasicUserList both have ID's; am i supposed to set any of those or this is done automatically?
Any pointers/help will be appreciated.
Please also let me know if you fine any issue with the code below.
set up remarketing using the AdWords API in two steps:
Create a remarketing list.
Create a CriterionUserList to tie your list to an AdGroup.
1.Create a remarketing list
Creating a remarketing list involves the creation of two separate entities: the RemarketingList itself and its associated UserListConversionTypes also known as remarketing tags.
The following code shows how to create a remarketing list.
AdWordsServices adWordsServices, AdWordsSession session) throws Exception {
// Get the UserListService.
AdwordsUserListServiceInterface userListService =
adWordsServices.get(session, AdwordsUserListServiceInterface.class);
// Get the ConversionTrackerService.
ConversionTrackerServiceInterface conversionTrackerService =
adWordsServices.get(session, ConversionTrackerServiceInterface.class);
UserListConversionType conversionType = new UserListConversionType();
conversionType.setName("Mars cruise customers #" + System.currentTimeMillis());
// Create remarketing user list.
RemarketingUserList userList = new RemarketingUserList();
userList.setName("Mars cruise customers #" + System.currentTimeMillis());
userList.setDescription("A list of mars cruise customers in the last year");
userList.setMembershipLifeSpan(365L);
userList.setConversionTypes(new UserListConversionType[] {conversionType});
// Create operations.
UserListOperation operation = new UserListOperation();
operation.setOperand(userList);
operation.setOperator(Operator.ADD);
UserListOperation[] operations = new UserListOperation[] {operation};
// Add user list.
userList = userListService.mutate(operations).getValue()[0];
2.Tie a remarketing list to an AdGroup
A new type of criteria object called CriterionUserList is now part of v201008. Through this type of criteria you are able to tie a UserList to an AdGroup. As with other types of
criteria, this type is also managed through the AdGroupCriterionService. The following code shows you how to create a CriterionUserList and tie it to an existing AdGroup.
// Create user list criterion.
CriterionUserList userListCriterion = new CriterionUserList();
userListCriterion.setUserListId(userListId);
// Create biddable ad group criterion.
BiddableAdGroupCriterion biddableCriterion = new BiddableAdGroupCriterion();
biddableCriterion.setAdGroupId(adGroupId);
biddableCriterion.setCriterion(userListCriterion);
// Create operation.
AdGroupCriterionOperation operation = new AdGroupCriterionOperation();
operation.setOperand(biddableCriterion);
operation.setOperator(Operator.ADD);
AdGroupCriterionOperation[] operations = new AdGroupCriterionOperation[] {operation};
// Add keywords.
AdGroupCriterionReturnValue result = adGroupCriterionService.mutate(operations);
Thanks,
-Devraj
Those two examples from Google pretty much cover how it's set up
The linking is done behind the scenes by Google - they match the ID in YOUR remarketing tag (which is usually specific to one AdWords account) with your remarketing lists (which are again at account level).
You can have many remarketing lists with varying criteria (visited certain URLs on your site, converted, etc. & combinations thereof) and link one of those lists to your campaign or adgroup.
I'd maybe suggest doing this through the AdWords web user interface first time so you understand the process you are automating with the API
You can get all existing conversion trackers as below.
ConversionTracker theConversionTracker = null;
Selector conversionTrackerSelector = new Selector();
conversionTrackerSelector.fields = new string[] { "Id", "Name" };
ConversionTrackerPage conversionTrackerPage = new ConversionTrackerPage();
try
{
ConversionTrackerService conversionTrackerService = (ConversionTrackerService)adWordsUser.GetService(AdWordsService.v201502.ConversionTrackerService);
conversionTrackerPage = conversionTrackerService.get(conversionTrackerSelector);
if (conversionTrackerPage != null && conversionTrackerPage.entries != null && conversionTrackerPage.entries.Length > 0)
{
//iterate over conversionTrackerPage.entries and write down the Id of the convertion tracker you need
}
}
catch (Exception ex)
{
}
Then you can use the Id when creating the conversion type
UserListConversionType conversionType = new UserListConversionType();
conversionType.name = "My conversion type name";
conversionType.id = 19XXXXXXXXL; // The Id you wrote down.
i'm working on a symfony project to manage a database. First i explain how it works:
In the database, all elements are associated to an unique element 'scene'. When a user accesses the application, chooses what scene he wants to see (it saves that in a user parameter). So when listing elements, the application should only list elements associated with the scene selected by the user.
*Note: all elements have an scene attribute in the table definition.
So my problem comes here:
I developed a listing of an element entities using the help of a sfPropelPager class to paginate. Also added some filters to search in the list, and for that i used the filter system provided by symfony (<element>FormFilter.class.php and stuff).
Now i want the list to not show elements from other scenes than the selected by the user.
How can i do to add additional criteria to the criteria given by the filter class?
or How would you solve the problem?
here is my action code:
public function executeUnidadfilter(sfWebRequest $request){
$this->filter = new BaUnidadorganizativaTblFormFilter();
$c = $this->filter->getCriteria();
$this->filter->bind($request->getParameter($this->filter->getName()));
if($this->filter->isValid()){
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
echo $this->getUser()->getEscenario();
$this->pager->setCriteria($c);
$this->pager->init();
}else{
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
$this->pager->init();
}
$this->setTemplate('Unidadlist');
}
*Note: 'scene' mentioned below is Escenario in the code
thank you very much for your time
I solved the problem. The trouble was that i assigned the formfilter generated criteria to my criteria var Before the filter was filled. That's why of the error.
The resulting code is that:
public function executeUnidadfilter(sfWebRequest $request){
$this->filter = new BaUnidadorganizativaTblFormFilter();
$this->filter->bind($request->getParameter($this->filter->getName()));
if($this->filter->isValid()){
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
$esc = $this->getUser()->getEscenario();
$c = new Criteria();
$c = $this->filter->getCriteria();
$c->addAnd('codigo_escenario',$esc);
$this->pager->setCriteria($c);
$this->pager->init();
}else{
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
$this->pager->setCriteria($this->filter->getCriteria());
$this->pager->init();
}
$this->message=null;
$this->messageType=null;
$this->setTemplate('Unidadlist');
}