I have a customer request to create a number of announcements based on some data from another database. Most of it seems easy enough but the new elements should be created by the user (login) specified in the input data. I was planning to add the announcements using the list web services but I sure would like to avoid using impersonation in order to get the create user right. Is there a way to assign the correct user as the creator without using impersonation?
I don't think that there is a method to archive this.
But perhaps this workaround might help. I have to admit I never tested this, it's only an idea how you might solve your problem.
You could try this. Create the new announcement with an admin user or with RunWithElevatedPrivileges(). After that use the RunWithElevatedPrivileges() method again and set the "created by" field to the user who should be the actual creator of the announcement. By this way only the "edited by" field should show the "wrong" user.
I know this is not a very elegant solution but it might work. ;)
I just realized that that my requirement was actually to circumvent the audit trail in SharePoint so I sure hope that it can't be done :-)
I came up with another solution: I added a new user or group field to the announcement list, and copy the AD-user logon into this field. Any report or view that previously used the "created by" field should now use the new field.
How about the situation where a real user enters a new element in the announcement list then? That will not update the new field with the logged in user!
Well, the only solution I could come up with is to add a ListItem Add trigger on the list. When a new element is added I check whether the new field contains a value, is not then I update the new field with the ID of the logged in user. That way the new field should always contain a valid userID.
I know this is not an elegant solution, but for the time being it is the best I can think of.
This may not be the answer you are looking for, but impersonation is pretty easy if you have code running in the GAC on a SharePoint server. You don't need to know any password which many do not realize, so I'll continue assuming that this was the reason you did not want to do impersonation. Here's how to do it.
You can connect to SharePoint using the typical constructor you use for SPSite and find the appropriate SPUser object. Once you do that, you can get the UserToken property for that SPUser. Then you'll need to use the SPSite constructor again, but use the overload that provides the SPUserToken. Then anything you do in SharePoint will be done via impersonation. No need to run with elevated privileges.
OK, now that I've said it in words, I'll try to guess at the code. It should be something like:
// Just determine the user token for a particular user
SPUserToken userToken = null;
using (SPSite tempSite = new SPSite("http://sharepointurl"))
{
using (SPWeb tempWeb = tempSite.OpenWeb())
{
// I think this next line works, but I'm going from memory
// I believe the user needs to have already logged into the site at least once
SPUser user = tempWeb.AllUsers["username"];
userToken = user.UserToken;
}
}
// Now do whatever we want impersonating that user
using (SPSite site = new SPSite("http://sharepointurl", userToken))
{
using (SPWeb web = site.OpenWeb())
{
// Do whatever you want here
}
}