I am receiving the error "Access Denied: Only an administrator may retrieve a count of all users." though I am using SPSecurity.RunwithElevatedPrivileges
What am I missing ? Please help.
private UserProfile GetUserInfo(string AccountName)
{
UserProfile profile = null;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPServiceContext serviceContext = SPServiceContext.Current;
UserProfileManager profileManager = new UserProfileManager(serviceContext);
if (AccountName != string.Empty)
{
if (profileManager.UserExists(AccountName))
{
profile = profileManager.GetUserProfile(AccountName);
}
}
//else
//{
// profile = profileManager.GetUserProfile(SPContext.Current.Web.CurrentUser.RawSid);
//}
});
return profile;
}
I was able to retrieve the user profile with the help of below code
SPSecurity.RunWithElevatedPrivileges(
delegate()
{
using (SPSite thisSite = new SPSite(SPContext.Current.Site.Url))
{
HttpContext tmp = HttpContext.Current;
HttpContext.Current = null;
SPServiceContext serviceContext = SPServiceContext.GetContext(thisSite);
UserProfileManager mgr = new UserProfileManager(serviceContext, true);
users.Text += "The total number of user profiles available: " + mgr.Count;
HttpContext.Current = tmp;
}
}
);
Source : http://weblogs.asp.net/sreejukg/access-denied-error-when-retrieving-user-profiles-count-from-sharepoint
yes, you need to generate a new context.
In you old code :
SPServiceContext serviceContext = SPServiceContext.Current;
UserProfileManager profileManager = new UserProfileManager(serviceContext);
You generate a new UPM with you current context, so you RunWithElevatedPrivileges is useless.
In you new Code :
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite thisSite = new SPSite(SPContext.Current.Site.Url))
{
[...]
SPServiceContext serviceContext = SPServiceContext.GetContext(thisSite);
UserProfileManager mgr = new UserProfileManager(serviceContext, true);
You get a new Context with Eleveted (because you instantiate a new SPSite in the ElevatedPrivileges) and thats why you can now use the UPM
Related
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
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.
i have a sharepoint problem. I have an event handler on a list and whenever someone adds a new item in the list I want to create a new web with the required details. The problem comes when a diferent user that is not site collection admin adds the item. On the Web.Webs.Add() method i get the error:
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).
Note that I'm using the SPSecurity.RunWithElevatedPrivileges delegate.
Here is a code sample:
public override void ItemAdded(SPItemEventProperties properties)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
string url = "the url";
if (Array.IndexOf(properties.Web.Webs.Names, url) >= 0)
{
properties.Web.Webs.Delete(url);
}
SPWeb newWeb = properties.Web.Webs.Add(url, "title", "description", properties.Web.Language, "STS#1", false, false);
});
}
Thanks.
I got it. The problem was that the web I was calling was not elevated, so I did somting like this:
public override void ItemAdded(SPItemEventProperties properties)
{
SPWeb web = properties.Web;
SPListItem currentItem= properties.ListItem;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(web.Site.ID))
{
using (SPWeb elevWeb = site.OpenWeb(web.ID))
{
SPList elevList = ListUtils.GetList(elevWeb, "list");
SPListItem elevItem = elevList.Items[currentItem.UniqueId];
elevWeb.AllowUnsafeUpdates = true;
string url = "the url";
if (Array.IndexOf(elevWeb.Webs.Names, url) >= 0)
{
elevWeb.Webs.Delete(url);
}
SPWeb newWeb = elevWeb.Webs.Add(url, "title", "description", elevWeb.Language, "STS#1", false, false);
}
}
});
}
I got an exception when executing this snippet code
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(siteUrl.Trim()))
{
using (SPWeb web = site.OpenWeb())
{
try
{
web.AllowUnsafeUpdates = true;
SPUser spUser = web.AllUsers[userName];
if (spUser != null)
{
SPGroup spGroup = web.Groups[groupName];
if (spGroup != null)
spGroup.AddUser(spUser);
}
}
catch (Exception ex)
{
this.TraceData(LogLevel.Error, "Error at function Named [AddUserToSPGroupWidget.AddUserToGroup] . With Error Message: " + ex.ToString());
}
finally
{
web.AllowUnsafeUpdates = false;
}
}
}
});
PLease guide me. Thanks in advance.
I don’t know what your exact exception is, but you can try to do following changes:
Instead of
SPUser spUser = web.AllUsers[userName];
use (it will ensure that user exists on the web)
SPUser spUser = web.EnsureUser(userName);
Instead of
SPGroup spGroup = web.Groups[groupName];
use (Groups collection contains only groups that are defined on the current sub web)
SPGroup spGroup = web.SiteGroups[groupName];
There is no need to check (spGroup != null) because if group is not found then always exception will be thrown.
Using the following block of code, the listItem.Update fails with a NullReferenceException:
SPWeb web = null;
SPList list = null;
SPListItem listItem = null;
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(this.SiteUrl))
{
web = site.OpenWeb();
list = web.Lists[this.ListName];
listItem = list.Items.Add();
listItem["Background"] = "foo";
}
}
);
listItem.Update();
}
catch
{
}
finally
{
web.Dispose();
}
If I move the listItem.Update() method inside of the anonymous delegate, I get "Operation is not valid due to the current state of the object."
Yes, I've combed through SO and have tried many permutations without success.
Any ideas?
Update:
After the first comment, I tried to remove the anonymous delegate from the code to see if it fared any better:
// store the selected item to pass between methods
public T SelectedItem { get; set; }
// set the selected item and call the delegate method
public virtual void Save(T item)
{
SelectedItem = item;
try
{
SPSecurity.RunWithElevatedPrivileges(SaveSelectedItem);
}
catch
{
}
}
public virtual void SaveSelectedItem()
{
if (SelectedItem != null)
{
using (SPSite site = new SPSite(this.SiteUrl))
{
using(SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[this.ListName];
SPListItem listItem = list.Items.Add();
//UpdateListItem(listItem, SelectedItem);
listItem["Background"] = "foo";
listItem.Update();
}
}
}
}
And this still fails "Operation is not valid due to the current state of the object." In both code samples, it looks like site.Impersonating is false. I am using Windows Auth, and Impersonation in the web.config. This is running from the ASP.Net Development server.
I found an example from this site (blackninjasoftware). I create a reference to the site, grab its SystemAccount token and then create another reference to the site, using the admin token. It seemed a little hackish to me at first - but hey - I have a deadline.
Final working method body now looks like:
SPListItem new_item = null;
SPSite initialSite = new SPSite(this.SiteUrl);
using (var site = new SPSite(this.SiteUrl, initialSite.SystemAccount.UserToken))
{
// This code runs under the security context of the SHAREPOINT\system
// for all objects accessed through the "site" reference. Note that it's a
// different reference than SPContext.Current.Site.
using (var elevatedWeb = site.OpenWeb())
{
elevatedWeb.AllowUnsafeUpdates = true;
SPList list = elevatedWeb.Lists[this.ListName];
new_item = list.Items.Add();
UpdateListItem(new_item, item);
if (new_item != null)
{
new_item.Update();
}
}
}
initialSite.Dispose();