[SharePoint 2010]Value from a User Profile custom field returns Null - sharepoint

In an EventReceiver I call this method GetPernNr on Item Added:
public override void ItemAdded(SPItemEventProperties properties)
{
SPSite site = properties.Web.Site;
using (SPWeb currentWeb = site.OpenWeb(properties.Web.ID))
{
.....
perNr = UserProfileUtils.GetPernNr(currentWeb, assignedTo.ToString());
.....
}
}
where assignedTo is a SPUser.
public static string GetPernNr(SPWeb web, string accountName)
{
string perNr = string.Empty;
UserProfile upUser = null;
try
{
PermissionSet ps = new PermissionSet(System.Security.Permissions.PermissionState.Unrestricted);
ps.Assert();
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite siteColl = new SPSite(web.Site.ID))
{
SPServiceContext serviceContext = SPServiceContext.GetContext(siteColl);
UserProfileManager upm = new UserProfileManager(serviceContext);
if (upm.UserExists(accountName))
{
upUser = upm.GetUserProfile(accountName);
if (upUser["PersonNumber"] != null)
{
perNr = upUser["PersonNumber"].Value.ToString();
}
}
}
});
}
catch (Exception ex)
{
..
}
finally { System.Security.CodeAccessPermission.RevertAssert(); }
return perNr;
}
It's strange, this code works when I try to get value from a default field in UserProfile (Office, Manager, etc). And also works when I call this method outside EventReceiver, but in my case, upUser["PersonNumber"].Value returns null.
Any help will be much appreciated

Did you check the custom property permission in the central admin.
Central Administration -> Edit User Profile Property -> Policy Settings
Make default privacy policy to everyone and then try.

Here is the steps for SharePoint Server 2013:
Central Admin > Application Management > Manage service applications > Your User Profile Application > Manage User
Properties
Select Edit option from property menu.
Now Under "Policy Settings":
Set Default Privacy Setting: Everyone

Related

Sharepoint 2010 event receiver and workflow not starting

I created an event receiver that should trigger a SharePoint designer workflow, however this never happens. This part of the code never evaluates to true for the guid and workflow association: if (association.BaseId == workflowGuid). I am a bit stumped and not quite sure why it's not working. Any insight would be appreciated...and my code is below. Basically when an item is added to my list, it should trigger my Sharepoint designer workflow but this never happens and I can manually start the workflow fine.
public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
startWF(properties);
}
private void startWF(SPItemEventProperties properties)
{
try
{
//bool startWF = false;
string strWorkflowID = "{c66ff94f-ba7c-4495-82fe-e73cdd18bad9}";
//string statusVal = properties.AfterProperties["eRequest Division"].ToString();
SPListItem li = properties.ListItem;
//using (SPWeb web = li.Web)
using (SPWeb web = properties.OpenWeb())
{
using (SPSite site = web.Site)
{
SPWorkflowManager mgr = site.WorkflowManager;
SPList parentList = li.ParentList;
//SPList list = web.Lists["Charitable and Political"];
SPWorkflowAssociationCollection associationCollection = parentList.WorkflowAssociations;
LookUpAndStart(li, mgr, associationCollection, "{c66ff94f-ba7c-4495-82fe-e73cdd18bad9}");
}
}
}
catch (Exception ex)
{
}
}
private static void LookUpAndStart(SPListItem listItem, SPWorkflowManager mgr, SPWorkflowAssociationCollection associationCollection, string workflowID)
{
foreach (SPWorkflowAssociation association in associationCollection)
{
Guid workflowGuid = new Guid(workflowID);
//if (association.Name.ToLower().Equals(workflowGuid))
//if (association.BaseId == workflowGuid)
//if (association.BaseId.ToString("B").Equals(workflowGuid))
if (association.BaseId == workflowGuid)
{
string data = association.AssociationData;
SPWorkflow wf = mgr.StartWorkflow(listItem, association, data, true);
break;
}
}
}
}
}
In my case the following was the problem.
Declarative workflows will not start automatically if the following conditions are true:
The Windows SharePoint Services Web application runs under a user's domain account.
The user logs in by using this domain account.
The site displays the user name as System Account.

Track if the users have read documents Sharepoint 2010 Document Center

I want to track if the users have read sharepoint 2010 document center's documents, currently user infos are not stored in audit logs, is there any way to do it?
It gets stored in audit logs.
Enable auditing for that particular document library and then get the details using the following code:
SPSite oSPsite = new SPSite
SPList doclib= oSPWeb.Lists["doclib"];
SPWeb oSPWeb = oSPsite.OpenWeb()
SPListItemCollection doclibitems= doclib.Items;
foreach (SPListItem odoclibItem in doclibitems)
{
odoclibItem .Audit.AuditFlags = SPAuditMaskType.View;
// odoclibItem .Audit.AuditFlags = SPAuditMaskType
SPAuditQuery oquery = new SPAuditQuery(oSPsite);
oquery.RestrictToListItem(odoclibItem );
odoclibItem .Audit.Update();
SPAuditEntryCollection oAuditEntryCollection =SPsite.Audit.GetEntries(oquery);
foreach (SPAuditEntry entry in oAuditEntryCollection)
{
if (entry.Event == SPAuditEventType.View)
{
id = Convert.ToString(entry.UserId);
// get the user name and other details here
}
}
}
I found the solution. Here is the steps.
1- Create a class library.
2- Right click the library and add new item.
3- Select ASP.NET Module under Web node.
4- Add PreRequestHandlerExecute event handler inside Init.Here is my code.
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += context_PreRequestHandlerExecute;
}
5- Methods
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
var app = sender as HttpApplication;
if (app != null)
{
string requesturl = app.Request.Url.ToString();
string file = string.Empty;
// if document opens in browser
if (app.Request.QueryString["Source"] != null && app.Request.QueryString["id"] != null && app.Request.QueryString["Source"].StartsWith(documentSiteUrl))
{
file = app.Request.QueryString["id"].Remove(0, app.Request.QueryString["id"].LastIndexOf('/'));
Worker(file);
}
// if document opened installed office apps or downloaded the document
if (requesturl.StartsWith(SiteUrl))
{
requesturl = requesturl.Remove(0, requesturl.LastIndexOf('/') + 1);
Worker(requesturl);
}
}
});
}
private void Worker(string requesturl)
{
#region ext control
List<string> extList = new List<string>(Exts.Split(';'));
bool result = false;
foreach (string item in extList)
{
if (requesturl.EndsWith(item))
{
result = true;
break;
}
}
#endregion
if ((!requesturl.Contains(".aspx")) && (!requesturl.EndsWith("/")) && result)
{
SPWeb web = SPContext.Current.Web;
String fileName = requesturl.Substring(requesturl.LastIndexOf("/") + 1);
// Add log
web.AllowUnsafeUpdates = true;
AddReadInfo(web.CurrentUser, fileName, web);
web.AllowUnsafeUpdates = false;
}
}
private void AddReadInfo(SPUser sPUser, string fileName, SPWeb web)
{
#region Logging
SPList logList = web.Lists.TryGetList("LogList");
if (logList != null)
{
SPListItem item = logList.Items.Add();
item["User"] = sPUser.Name;
item["Document"] = fileName;
item["Read"] = "Read";
item.Update();
}
#endregion
}
6- Don't forget signing the project.
7- Build Project.
8- Add dll to GAC and BIN folder under the C:\inetpub\wwwroot\wss\VirtualDirectories\80\ folder.
9- Open IIS Manager.
10- Find your site nod and select.
11- Open Modules.
12- Right click under modules page and select Add Managed Module option.
13- Give a name and select your module under dropdownlist.
14- IIS reset.

Check current user's permission if the user has no enumerate permission in SharePoint

As we know, we can check user's permission by doing this:
using (SPWeb web = site.OpenWeb(path))
{
SPUser user = SPContext.Current.Web.CurrentUser;
string loginName = user.LoginName;
if (web.DoesUserHavePermissions(SPBasePermissions.EnumeratePermissions))
{
if (web.DoesUserHavePermissions(user.LoginName, SPBasePermissions.Open))
{
//do something
}
}
}
Here is my question, if current user doesn't have enumerate permission, how to get permissions on SharePoint object? Thanks in advance.
You can do it by opening an "admin" web instance (creating a SPSite object and passing System account's user token to it). This way you do not have to worry about whether current user has or has not got enough permission.
SPUserToken adminToken = SPContext.Current.Web.AllUsers["SHAREPOINT\\System"].UserToken;
using (SPSite adminSite= new SPSite(SPContext.Current.Site.ID, adminToken) ) {
using (SPWeb adminWeb = adminSite.OpenWeb(SPContext.Current.Web.ID)){
if (adminWeb.DoesUserHavePermissions(SPContext.Current.Web.CurrentUser.LoginName, SPBasePermissions.Open)) {
//do something
}
}
}
Of course, you better not do this on every page load as creation and disposing of SPSite/SPWeb objects is relatively expensive.
Here I have defined a function that takes a SharePoint list object, a Role type and a User.
portal : The sharepoint list or document library object.
role : RoleType provided by sharepoint like Read, Design etc.
user : user to whom you want to grant role on portal.
Hope it will help you.
public static void AssignPermissionToPortal(string portal, SPRoleType role, SPUser user)
{
try
{
// Run with elevated privileges
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(SPContext.Current.Web.Site.ID))
{
using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
{
web.AllowUnsafeUpdates = true;
SPList portalList = SPListHelper.GetSPList(portal, web);
portalList.BreakRoleInheritance(false);
//Add Readers on portal
SPRoleDefinition permission = web.RoleDefinitions["Read"];
if (role == SPRoleType.Administrator)
permission = web.RoleDefinitions["Full control"];
else if (role == SPRoleType.Contributor)
permission = web.RoleDefinitions["Contribute"];
else if (role == SPRoleType.WebDesigner)
permission = web.RoleDefinitions["Design"];
else
permission = web.RoleDefinitions["Read"];
// Check the user Role on site level.
SPUser roleUser = uHelper.GetUserById(user.ID);
if (roleUser != null)
{
SPRoleAssignment assignment = new SPRoleAssignment(roleUser);
assignment.RoleDefinitionBindings.Add(permission);
portalList.RoleAssignments.Add(assignment);
portalList.Update();
}
web.AllowUnsafeUpdates = false;
}
}
});
}
catch (Exception ex)
{
Log.WriteException(ex);
}
}

membership requests e-mail address for SPGroup sharepoint

While creating Group in sharepoint we have an option
"Send membership requests to the following e-mail address"
It is used to send membership request to the SPGroup.
But how can we set the e-mail address programmatically
I'm trying to accomplish the same thing in a feature activated event. I have found how to create the group and how to access these settings in the object model. You can use my example below. The problem is, my changes to these boolean properties of the SPGroup don't take, despite calling SPGroup.Update(). The SPGroup created still uses the default settings (membership requests are turned off).
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPSite site = (SPSite)properties.Feature.Parent;
{
using (SPWeb web = site.RootWeb)
{
SPGroupCollection collGroups = web.SiteGroups;
SPUser user = web.EnsureUser("DOMAIN\\username");
collGroups.Add("MySPGroupName", user, user, "MySPGroupDescription");
if (!web.AssociatedGroups.Contains(collGroups["MySPGroupName"]))
{
web.AssociatedGroups.Add(collGroups["MySPGroupName"]);
}
SPRoleAssignment assignment = new SPRoleAssignment(collGroups["MySPGroupName"]);
SPRoleDefinition def = web.RoleDefinitions.GetByType(SPRoleType.Contributor);
assignment.RoleDefinitionBindings.Add(def);
web.RoleAssignments.Add(assignment);
web.Update();
collGroups["MySPGroupName"].AllowMembersEditMembership = true;
collGroups["MySPGroupName"].AllowRequestToJoinLeave = true;
collGroups["MySPGroupName"].OnlyAllowMembersViewMembership = false;
string emailForRequests = "username#domain.com";
if (!String.IsNullOrEmpty(user.Email))
emailForRequests = user.Email;
collGroups["MySPGroupName"].RequestToJoinLeaveEmailSetting = emailForRequests;
collGroups["MySPGroupName"].Update();
}
}
}
If using SP 2013, using PowerShell you can use the following code:
$membersGroup = $siteCollection.SiteGroups["$groupName"]
$membersGroup.RequestToJoinLeaveEmailSetting = "someone#mail.com"
$membersGroup.Update()

Checking permissions of a user with a site collection

I want to check whether a user has permissions to a site collection. But i dono how to use SPSite.DoesUserHavePermissions().
What is SPReusableAcl? How can i get it for checking the permissions of the user?
Doesn't the MSDN article (SPWeb.DoesUserHavePermissions Method (String, SPBasePermissions)) help you? The example code can be used to check whether the user has access to a site collection:
using System;
using Microsoft.SharePoint;
namespace Test
{
class Program
{
static void Main(string[] args)
{
using (SPSite site = new SPSite("http://localhost"))
{
using (SPWeb web = site.OpenWeb())
{
// Make sure the current user can enumerate permissions.
if (web.DoesUserHavePermissions(SPBasePermissions.EnumeratePermissions))
{
// Specify the permission to check.
SPBasePermissions permissionToCheck = SPBasePermissions.ManageLists;
Console.WriteLine("The following users have {0} permission:", permissionToCheck);
// Check the permissions of users who are explicitly assigned permissions.
SPUserCollection users = web.Users;
foreach (SPUser user in users)
{
string login = user.LoginName;
if (web.DoesUserHavePermissions(login, permissionToCheck))
{
Console.WriteLine(login);
}
}
}
}
}
Console.ReadLine();
}
}
}
In the sample code above you would just have to change your Site URL and the Variable permissionToCheck. SPBasePermissions has a lot of possible permissions to check against, you can see the enumeration here (SPBasePermissions Enumeration).
Actually there are a lot of tutorials on how to check some user's permissions and you are not limited to DoesUserHavePermissions, see the following Google Search.
As usual, the MSDN examples provide nice textbook examples that do not always apply to real-life scenarios.
In the context of an application page running on SharePoint 2010, from what i understand this code needs to be wrapped in a call to RunWithElevatedPrivileges and even then, as my comment implies, it seems there is an implied catch-22 in the requirements. This works for me (the LoginName is just the FBA username or "domain\user" for AD user for the site - in our case an e-mail address is used):
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite elevatedSite = new SPSite(siteCollectionUrl))
{
foreach (SPSite siteCollection in elevatedSite.WebApplication.Sites)
{
using (SPWeb elevatedWeb = siteCollection.OpenWeb())
{
bool allowUnsafeUpdates = elevatedWeb.AllowUnsafeUpdates;
bool originalCatchValue = SPSecurity.CatchAccessDeniedException;
SPSecurity.CatchAccessDeniedException = false;
try
{
elevatedWeb.AllowUnsafeUpdates = true;
// You can't verify permissions if the user does not exist and you
// can't ensure the user if the user does not have access so we
// are stuck with a try-catch
SPUser innerUser = elevatedWeb.EnsureUser(loginName);
if (null != innerUser)
{
string splogin = innerUser.LoginName;
if (!string.IsNullOrEmpty(splogin) && elevatedWeb.DoesUserHavePermissions(splogin, SPBasePermissions.ViewPages))
{
// this user has permissions; any other login - particularly one that
// results in an UnauthorizedAccessException - does not
}
}
}
catch (UnauthorizedAccessException)
{
// handle exception
}
catch (Exception)
{
// do nothing
}
finally
{
elevatedWeb.AllowUnsafeUpdates = allowUnsafeUpdates;
// reset the flag
SPSecurity.CatchAccessDeniedException = originalCatchValue;
}
}
}
}
});
SPSite.DoesUserHavePermissions(SPReusableAcl, SPBasePermissions);

Resources