I'm trying to create a "Who is" web part for a SharePoint 2010 project i'm working on.
This web part is supposed to select a random user from SharePoint profiles and display his/her name, department and phone.
The problem is that i couldn't find a way to get a random user directly from the User Profiles, which is what i'd like to do.
I found a way to do it:
SPServiceContext myContext = SPServiceContext.GetContext(mySite);
SPWeb myWeb = SPContext.Current.Web;
UserProfileManager profileManager = new UserProfileManager(myContext);
bool boolOut;
SPPrincipalInfo[] userInfos = SPUtility.GetPrincipalsInGroup(myWeb, "AllUsers", profileManager.Count, out boolOut);
Random random = new Random();
int randomUser = random.Next(0, userInfos.Length);
SPPrincipalInfo user = userInfos[randomUser];
bool userFound = false;
while(!userFound)
{
if (profileManager.UserExists(user.LoginName))
{
UserProfile userProfile = profileManager.GetUserProfile(user.LoginName);
userDepartment = Convert.ToString(userProfile[PropertyConstants.Department].Value);
userPicture = Convert.ToString(UserProfile[PropertyConstants.PictureUrl].Value);
userFound = true;
}
}
This way i did it could be a problem because the site would have 2k+ users, that's why i'd like to know if it's possible to do this directly from the User Profiles.
I'm new to SharePoint and it still a little confusing to me.
Thanks for your help.
I'm curious why the need for it to be a "random" user. I would suggest using the OOB functionality around suggested colleagues, and your web part could expose this information instead.
Related
I am currently developing an application to be used internally only at work. I need to get the currently logged in user's contacts to use in the application and I am currently getting the contacts with the following:
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace NameSpace = app.GetNamespace("MAPI");
Microsoft.Office.Interop.Outlook.MAPIFolder ContactsFolder = NameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
Microsoft.Office.Interop.Outlook.Items ContactItems = ContactsFolder.Items;
foreach (Microsoft.Office.Interop.Outlook.ContactItem item in ContactItems)
{
//do stuff with the contacts here
}
The problem with this approach is that whenever a user opens the application and Outlook is not already open, an Outlook popup appears asking the user to Allow or Deny the application's access to Outlook contacts. This is unnecessary and my only thought of how to stop this form happening is instead of using Outlook itself, get the contacts from the Exchange Server.
I have looked into a bunch of documentation for things like EWS however I have not found reference for EWS to be guaranteed working with Exchange 2019. I would also like any authentication done automatically based on domain authentication with the currently logged in user instead of requiring the user to input a password.
I did try to use this: https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/get-started-with-ews-managed-api-client-applications however ExchangeVersion only has options up to Exchange 2013.
What should I be using to achieve this? Any push in the right direction would be greatly appreciated.
Use the active directory instead of EWS to get network users data, including email address.
the relevant namespace is: System.DirectoryServices
Here is an example that I wrote in my project to get user data including email by the first name and last name from AD. Note: ActiveDirectoryEntity us a class of mine. also, regarding another issue you wrote in your question, entering the user and password is not needed because authentication was already maid when the user authenticated to windows.
public static List<ActiveDirectoryEntity> GetActiveDirectoryData(string sname, string fname)
{
try
{
DirectorySearcher search = new DirectorySearcher();
search.Filter = String.Format("(&(objectCategory=person)(objectClass=user)(givenname={0}*)(sn={1}*))", sname, fname);
search.PropertiesToLoad.Add("givenName");
search.PropertiesToLoad.Add("sn");
search.PropertiesToLoad.Add("mail");
search.PropertiesToLoad.Add("mobile");
search.PropertiesToLoad.Add("department");
var result = search.FindAll();
List<ActiveDirectoryEntity> resultlist = new List<ActiveDirectoryEntity>();
foreach (SearchResult r in result)
{
if (r.Properties["mail"] != null)
{
if (r.Properties["mail"].Count > 0)
{
ActiveDirectoryEntity ade = new ActiveDirectoryEntity();
if ((r.Properties["givenname"].Count > 0))
ade.FirstName = r.Properties["givenName"][0].ToString();
if ((r.Properties["sn"].Count > 0))
ade.LastName = r.Properties["sn"][0].ToString();
if ((r.Properties["mail"].Count > 0))
ade.Email = r.Properties["mail"][0].ToString();
if ((r.Properties["department"].Count > 0))
ade.Department = r.Properties["department"][0].ToString();
resultlist.Add(ade);
}
}
}
return resultlist;
}
catch
{
return null;
}
}
I am working on a C# code that retrieves all site collection paths from a On-Premise Sharepoint 2013 server. I have the following Site Collections on the server:
/serverurl/
/serverurl/my
/serverurl/my/personal/site1
/serverurl/my/personal/site2
/serverurl/sites/TestSite
/serverurl/custompath/site3
when I run my code , I only get the following site collections:
/serverurl/
/serverurl/my
/serverurl/my/personal/site1
/serverurl/my/personal/site2
I was wondering why my search does not return all the site collections?
here is my code:
ClientContext context = new ClientContext(siteUrl);
var cred = new NetworkCredential(userName, password, domain);
context.Credentials = cred;
KeywordQuery query = new KeywordQuery(context);
query.QueryText = "contentclass:STS_Site";
SearchExecutor executor = new SearchExecutor(context);
query.TrimDuplicates = true;
var resultTable = executor.ExecuteQuery(query);
context.ExecuteQuery();
foreach (var row in resultTable.Value[0].ResultRows)
{
string siteName = row["siteName"] as string;
Console.WriteLine("Site Name: {0}", siteName);
}
Thanks!
I was having the same problem today. I found two solutions.
Regardless if your on-prem or on Office365 we can use Microsoft.Online.SharePoint.Client.Tenant dll. You can use this to get all the Site Collections. You do need your admins to run some power shell if your on-prem. Vesa was nice enough to write a blog about it here
Once you get that done, you can do something like the following (Note:I have not tested this method with a non Admin account) (solution taken from here) Sadly this one will not work for me as I want security trimming and this will code must be ran by a user with tenant read permissions which our users would not normal have.
var tenant = new Tenant(clientContext);
SPOSitePropertiesEnumerable spp = tenant.GetSiteProperties(0, true);
clientContext.Load(spp);
clientContext.ExecuteQuery();
foreach(SiteProperties sp in spp)
{
// you'll get your site collections here
}
I ended up doing this which gets back to using search, I still have a problem, we have well over 500 sites/webs so I'm working with our admins to see if we can increase the max rows search can return. However, the true secret here is TrimDuplicates being set to false, I don't know why SP thinks the results are dups, but it obviously does, so set it to false and you should see all your sits.
KeywordQuery query = new KeywordQuery(ctx);
query.QueryText = "contentclass:\"STS_Site\"";
query.RowLimit = 500;//max row limit is 500 for KeywordQuery
query.EnableStemming = true;
query.TrimDuplicates = false;
SearchExecutor searchExecutor = new SearchExecutor(ctx);
ClientResult<ResultTableCollection> results = searchExecutor.ExecuteQuery(query);
ctx.ExecuteQuery();
var data = results.Value.SelectMany(rs => rs.ResultRows.Select(r => r["Path"])).ToList();
Hope one of the two will work for you.
I am running into a problem with the VersionOneAPIClient in that it will not recognize anything I give it ass an asset type. I understand the Attribute definitions probably don't make any sense but I've been trying pretty much everything. My end goal would be to query TeamRooms and get team names from all the teams in the team room.
It's my understanding from the documentation on asset types and how to query that this should work but that's what we all say.
I am using:
C# ASP.NET, VersionOneAPIClient 15.0.0.0
Strings I have tried:
TeamRoom
Task
Scope
Project
public bool APIgetTeams()
{
IAssetType teamroomType = services.Meta.GetAssetType("Task");
Query query = new Query(teamroomType);
IAttributeDefinition teamAttribute = teamroomType.GetAttributeDefinition("Children:Room.Team.Name");
query.Selection.Add(teamAttribute);
IAttributeDefinition scheduleAttribute = teamroomType.GetAttributeDefinition("Children:Scope.Room.Schedule.Name");
query.Selection.Add(scheduleAttribute);
query.Find = new QueryFind(scheduleName, new AttributeSelection(scheduleAttribute));
query.Paging.PageSize = 1;
query.Paging.PageSize = 0;
teamRoomAsset = (Asset)services.Retrieve(query).Assets.ToArray().GetValue(0);
return true;
}
My definition of services and the connector:
public static V1Connector connector = V1Connector
.WithInstanceUrl("http://versionone.cscinfo.com/VersionOneProd/")
.WithUserAgentHeader("New Dashboard?", "1.0")
.WithWindowsIntegrated()
.Build();
public IServices services = new Services(connector);
And these are my Errors / Stack Traces:
The error is likely simple and right in my face but I can't figure it out.
You have a couple of things going on here. I will address your statement "My end goal would be to query TeamRooms and get team names from all the teams in the team room."
Here is a working chunk of code that reads all of your TeamRooms and prints the name of the Team Room and the Team Name. Once you get this working on your machine, attempt to do the paging. Add filtering incrementally to keep the debug cycles low.
static void Main(string[] args)
{
V1Connector connector = V1Connector
.WithInstanceUrl("https://www.MyV1INstance")
.WithUserAgentHeader("HappyApp", "0.1")
.WithUsernameAndPassword("login", "pwd")
.Build();
IServices services = new Services(connector);
IAssetType trType = services.Meta.GetAssetType("TeamRoom");
Query query = new Query(trType);
IAttributeDefinition teamAttribute = trType.GetAttributeDefinition("Team.Name");
IAttributeDefinition nameAttribute = trType.GetAttributeDefinition("Name");
query.Selection.Add(teamAttribute);
query.Selection.Add(nameAttribute);
QueryResult result = services.Retrieve(query);
Asset teamRooms = result.Assets[0];
foreach (Asset story in result.Assets)
{
Console.WriteLine(story.Oid.Token);
Console.WriteLine(story.GetAttribute(teamAttribute).Value);
Console.WriteLine(story.GetAttribute(nameAttribute).Value);
Console.WriteLine();
}
Addendum
I just realized that you were using WithWindowsIntegrated() instead of WithUsernameAndPassword().
Just change that in my sample but then confirm that you are logged into the machine as a Member that is already setup in VersionOne. The windows int auth is trusting IIS' decision to trust you but then immediately after allowing auth, you have to have an active Member account in VersionOne to have access to VersionOne assets.
I have pages that I admin in the Facebook and I want to share a link(not post) from that page using Facebook C# SDK. How can I do that? For clarify question, Facebook pages has link button that you can share link with page's picture.
Simply facebookclient.Post("me/feed",parameters);
For the parameters see https://developers.facebook.com/docs/reference/api/post/
messagePost["message"] = message;
messagePost["caption"] = caption;
messagePost["description"] = descr;
messagePost["link"] = "http://xxx";
FacebookClient fbClient = new FacebookClient(FacebookAdminToken); //users have to accept your app
dynamic fbAccounts = fbClient.Get("/" + FacebookAdminId + "/accounts");
if (pageID != null)
{
foreach (dynamic account in fbAccounts.data)
{
if (account.id == pageID)
{
messagePost["access_token"] = account.access_token;
break;
}
}
dynamic publishedResponse = fbClient.Post("/" + pageID + "/links", messagePost);
message.Success = true;
}
Hope his helps.
there is two majour problems with my solution:
1) my FacebookAdmintoken was created using the soon to be deprecated offline_status. there currently is no way for the access_token to stay alive otherwise. Facebook claims it does, but it just doesn't work.
2) there is a bug in the facebook API. when you use post('/id/LINKS') you cannot specify the picture (FB chooses a random pic from the site) and using post('/id/FEED') people can see the result, but they cannot SHARE it.
Seriously FB, get your act together!!!!!
I'm looking to try and get an MVC3 Canvas app working with the Facebook C# SDK, but am struggling to allow permissions - Below is my code, and when I open the app I get the 'Allow / Deny' dialog but when I click allow I get redirected to my app and the same dialog appears again (And again and so on no matter how many times I click allow)?
I guess I am missing something obvious... If I take the user_groups permission out it works fine, I just can't access the persons groups.
[CanvasAuthorize(Permissions = "user_groups")]
public class HomeController : Controller
{
public ActionResult Index()
{
IFacebookApplication settings = FacebookApplication.Current;
if (settings != null)
{
//CanvasPage = settings.CanvasPage;
//AppId = settings.AppId;
}
FacebookWebContext facebookContext = FacebookWebContext.Current;
FacebookSignedRequest signedRequest = facebookContext.SignedRequest;
var client = new FacebookWebClient(facebookContext.AccessToken);
dynamic me = client.Get("me");
var friends = client.Get("me/friends");
var groups = client.Get("me/groups");
ViewBag.Name = me.name;
ViewBag.Id = me.id;
JavaScriptSerializer sr = new JavaScriptSerializer();
var fbFriends = sr.Deserialize<FBFriends>(friends.ToString());
ViewData["friends"] = fbFriends.data;
return View("Friends");
}
}
Any help, tips or code samples greatly appreciated.
make sure u have set the appid and appsecret correctly.
download the source code and checkout the "samples" folder, there are a bunch of asp.net mvc samples.