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.
Related
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
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);
}
}
});
}
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);
}
}
I'm trying to retrieve a name of the persdon who completed a task. In my Tasks list i can see 'Modified By' which is Editor.
In Sharepoint Manager I can see the persons name in the Editor column.
How can I get this value in the code
I create a task and after the ontaskchanged I have a code block. I've tried many permutations but cannot retrieve this data.
private void UpdateCreatedByAndModifiedByFieldData(string strSiteUrl, string strListName, string strUserFieldName)
{
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(strSiteUrl))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[strListName];
foreach (SPListItem listItem in list.Items)
{
//Read user id from a list column of user type and create SPUser object
SPUser user = web.EnsureUser(listItem[strUserFieldName].ToString().Trim());
if (user != null)
{
string userValue = user.ID + ";#" + user.Name;
//Assign the above user to the "Created By" column
listItem["Author"] = userValue;
//Assign the above user to the "Modified By" column
listItem["Editor"] = userValue;
//Call the update method to apply the above changes
listItem.Update();
web.Update();
}
}
}
}
});
}
catch (Exception ex)
{
throw ex;
}
}
Check this also
How to get SharePoint file creator name using AllDocs table?
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();