Extend the Newsfeed Functionality of SharePoint 2013

Requirement: Provide ability to “one-click” post content to newsfeed or site feeds that users have access to.

postbutton

Solution:

  • SharePoint Provider-Hosted App
    • default.aspx – a custom page to allow users entering content and post to their newsfeed or site feed.
    • postnewsfeed
    • Custom Action – add “Post” to ECB menu of target lists
      <?xml version="1.0" encoding="utf-8"?>
      <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
       <CustomAction Id="c72a6c2f-b61e-41bc-90ec-4d7000aa4a64.PostToNewsfeed"
                     RegistrationType="List"
                     RegistrationId="100"
                     Location="EditControlBlock"
                     Sequence="20"
                     Title="$Resources:profilebrowserscriptres,PostCommandText"
                     HostWebDialog="true"
                     HostWebDialogHeight="420"
                     HostWebDialogWidth="500">
      
          <UrlAction Url="~remoteAppUrl/Pages/Default.aspx?{StandardTokens}&amp;SPListItemId={ItemId}&amp;SPListId={ListId}" />
       </CustomAction>

      Update: We are going to integrate SharePoint with Facebook, so need to remove the custom action from lists. Originally, the App was installed on AppCatalog site, and deploy to SPWeb based on the Site Template(Blog Site) via “Deployment” feature. So all the custom lists in Blog Site would have this custom action. Unfortunately, it’s not removed when we uninstall the App from AppCatalog site. Therefore, we have to write a script to remove them using CSOM. 

  • JQuery UI AutoComplete
    • Generating mention and hashtags via JSOMmention
/// <summary>
/// WebMethod to search people for metion
/// </summary>
/// <param name="spHostUrl"></param>
/// <param name="term"></param>
/// <returns>People Search result in an array contains AccountName and PreferredName</returns>
[WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static string[] SearchPeople(string spHostUrl, string term)
{

   List<string> searchResults = new List<string>();

   try
   {  
     using (var ctx = new ClientContext(spHostUrl))
     {
       if (ctx != null && term != null)
       {
         KeywordQuery query = new KeywordQuery(ctx);
         query.QueryText = "(PreferredName:" + term + "* AND LastName:" + term + "*)";
         query.SourceId = new Guid("B09A7990-05EA-4AF9-81EF-EDFAB16C4E31"); // this is the People result source
         query.RowLimit = 10;
         query.TrimDuplicates = true;
         query.EnableSorting = true;
         query.SelectProperties.Add("AccountName");
         query.SelectProperties.Add("PreferredName");
         query.SortList.Add("LastName", Microsoft.SharePoint.Client.Search.Query.SortDirection.Ascending);
 
         SearchExecutor searchExecutor = new SearchExecutor(ctx);

         ClientResult<ResultTableCollection> results = searchExecutor.ExecuteQuery(query);
 
         ctx.ExecuteQuery();

         #region loop through results
         if (results.Value.Count > 0)
         { 
           for (int i = 0; i < results.Value[0].ResultRows.Count(); i++)
           {
             var resultRow = results.Value[0].ResultRows.ElementAt(i);
             string name = resultRow["PreferredName"].ToString();
             string accountName = resultRow["AccountName"].ToString();
             searchResults.Add(name + "|" + accountName);
           }
         }
         #endregion
       }
     }
   }
   catch (Exception ex)
   {
     Logger.Log(ex);
   }

   return searchResults.ToArray();
}
/// <summary>
/// WCF Service method to retrieve Hashtags
/// </summary>
/// <param name="spHostUrl"></param>
/// <param name="term"></param>
/// <returns></returns>

public string[] SearchHashTag(string spHostUrl, string term)
{
   List<string> searchResults = new List<string>();
   try
   {
     using (var ctx = TokenHelper.GetS2SClientContextWithWindowsIdentity(new Uri(spHostUrl), null))
     {
       if (ctx != null && term != null)
       {
         TaxonomySession taxonomySession = TaxonomySession.GetTaxonomySession(ctx);
         TermStore termStore = taxonomySession.GetDefaultSiteCollectionTermStore();
         TermSetCollection termSetCollection = termStore.GetTermSetsByName("Hashtags", 1033);
         TermSet termSet = termSetCollection.GetByName("Hashtags");

         TermCollection termCollection = termSet.GetAllTerms();
         ctx.Load(termCollection);
         ctx.ExecuteQuery();

         #region loop through results
         if (termCollection.Count > 0)
         {
           var terms = termCollection.GetEnumerator();
           while (terms.MoveNext())
           {
             searchResults.Add(terms.Current.Name);
           }
         }
         #endregion
       }
     }

   }
   catch(Exception ex)
   {
     Logger.Log(ex);
   }

   return searchResults.ToArray();
}
Advertisements

Add and Retrieve property bag by CSOM

This blog will tell you how to add and retrieve web property bag through SharePoint CSOM.

I tried use Add method to insert a new property; however, it does not really add the new property.

Add Property

private int SetProperty(ClientContext clientContext, int flag)
{
  Web web = clientContext.Site.RootWeb;
  /* Add successfully, but not persistantly. Cannot find this new property when retrieve property bag
  clientContext.Load(web, w=>web.AppProperties);
  clientContext.ExecuteQuery();

  if (!web.AllProperties.FieldValues.ContainsKey("Customized"))
  {
     web.AllProperties.FieldValues.Add("Customized", flag);
  }
  else
  {
     web.AllProperties["Customized"] = flag;
  }
  */ 
  
  // Correct Approach
  var allProperties = web.AllProperties;
  allProperties["CIBCCustomized"] = flag;

  web.Update();
  clientContext.ExecuteQuery();

  return flag;
}

Retrieve Property

private int GetFlag(ClientContext clientContext)
{
  Web web = clientContext.Site.RootWeb;
  clientContext.Load(web, w => w.AllProperties);
  clientContext.ExecuteQuery();

  if (!web.AllProperties.FieldValues.ContainsKey("Customized"))
  {
    return 0;
  }
  else
  {
    return (int)web.AllProperties["Customized"];
  }
}