Multiple instances of webpart with custom EditorPart properties

I have recently stumbled upon an interesting problem in a sharepoint webpart.

I wanted to build a webpart that would dynamically create a contact form based on properties that the user set in the webpart property section. Because i wanted to give the user a dropdown from which he would select a sharepoint list from his site, and this dropdown has to populate on load based on his site, i had to use editorpart .

I won`t write about how this is done, because there are many other great posts in other blogs that explain how to do this : link1 , link2 .

After i have implemented the webpart, i have tested it and observed a problem. If i had only one webpart in the site collection, all went according to plan : the user set the properties based upon his needs and the webpart worked well.

The problem appeared when i added another instance of the webpart on another page from that site.  When i set its properties it changed the properties of first webpart as well. This problem persisted in a subsite as well.

After i googled a little i found 2 threads with the same problem, and no answers (in the meantime, i found the solution and answered).

Link1 

Link2

At first i had the properties of the webpart defined like this (this is an example of one):

public static string _emailReceiver;
[WebBrowsable(false), Personalizable(PersonalizationScope.Shared)]
public string EmailReceiver
{

get { return _emailReceiver; }
set { _emailReceiver = value; }
}
In the public class ContactFormWebPartEditorPart : EditorPart i had a textbox defined :
private TextBox Subject;

The apply changes in the editorpart :

public override bool ApplyChanges()
{

EnsureChildControls();

ContactFormWebPart webPart = WebPartToEdit as ContactFormWebPart;

if (webPart != null)

{

webPart.ContactFormList = _dropDownLists.SelectedValue.ToString();

webPart.EmailReceiver = Email.Text;

webPart.EmailSubject = Subject.Text;

webPart.RedirectTo = redirect.Text;

}

return true;

}

All you have to do is to change the EmailReceiver property from the webpart to:

[WebBrowsable(false), Personalizable(PersonalizationScope.Shared)]

public string EmailReceiver

{

get;

set;

}

I have tested it with 3 different webparts, configured each with different properties. It works! Two of them were on the same page!

Maybe it works because the setter and the getter generate random field names on compile time.

Hope that helps!

Advertisements

Working with sharepoint large lists

Please visit this : Samsung Service Galaxy S

In a recent project, I had to get some information from the last sharepoint listitems inserted. I used foreach. Of course it is a bad idea. When the list grew (thousand of listitems)…the program worked as fast as a drunken turtle. Ok… As I was saying the data I needed was from the last x items inserted. So I replaced the foreach with a simple for:
count=10; (the last 10 items inserted)
for (int i = oList.Items.Count – count; i < oList.Items.Count; i++)

I ran the program and saw that the improvement was not what I expected, so I made a testProject to measure the execution time, for the foreach block code and the code above (with the simple for);

DateTime startTime = DateTime.Now;

chunk of code (for or foreach iteration)

DateTime stopTime = DateTime.Now;
TimeSpan duration = stopTime – startTime;

For large lists the foreach statement took forever. The for statement took from 5 to 30 seconds for 4000 list items.
The odd part was that in the for statement as I said before, i iterated through the last 10 items.
So for 10 items I waited some good seconds.
I googled for the truth and I found this interesting article.

So I found out the SPQuery is one of the best ways to work with large lists.

SPQuery query = new SPQuery(oList.Views[0]);
Comm
query.RowLimit = 10;
SPListItemCollection filteredList = oList.GetItems(query);
foreach (SPListItem item in filteredList)
{
Blabla;
}

I ordered the list Descending by their ID so i got the most recent 10 list items.
I measured the execution time. At the first run it took 800 milliseconds for 4000 list items. The next executions took only from 15 to 30 milliseconds.
I would say…it is at least a good improvement;
An easier way to create CAML queries is with U2U CAML Query Builder
I tried to use CAML query to get the max ID directly but I didn`t succeed. If someone reads this…:P and knows how please leave a reply.

Commerce Server 2009
Thank you,
Ing. Msc. Dan Gheorghe

Add RoleAssignment to listitem.

Please visit this : Samsung Service Galaxy S

This is continuing the previous post. After you create the list item impersonating the current logged in user in the sharepoint site you might want to give that user only the right to read it.
After oListItem.Update(); you must run the code to do this with elevated Privileges to assign the role.

SPUser user = oWebsiteRoot.SiteUsers.GetByID(web.CurrentUser.ID);
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPSite site = new SPSite(SPControl.GetContextSite(this.Context).ID);
SPWeb w = site.OpenWeb();
Guid g = oListItem.UniqueId;
oListItem = w.Lists["Announcements"].GetItemByUniqueId(g);

oListItem is the listitem created in the previous post

I tried to set the RoleInheritence of the list item to false: oListItem.BreakRoleInheritance(false);
but i had some problems with it. I got the error:
“Updates are currently disallowed on GET requests.”

oListItem.BreakRoleInheritance(false) sets the spweb.AllowUnsafeUpdates to false; so after this you must set it true manually again even though we did that in the code before this (in the previous post) :

oListItem.BreakRoleInheritance(false);
w.AllowUnsafeUpdates = true;
w.Update();

Now to set the roles:

SPRoleDefinitionCollection webroledefinitions = w.RoleDefinitions;

SPRoleAssignment roleassignment = new SPRoleAssignment(user);

roleassignment.RoleDefinitionBindings.Add(webroledefinitions["Read"]);
oListItem.RoleAssignments.Add(roleassignment);
oListItem.Update();

});

And now every user sees the the items created by themselves.

Commerce Server 2009
By Ing. Msc. Dan Gheorghe

Sharepoint Impersonation.

Please visit this : Samsung Service Galaxy S

When you create a web form or web part for wss or sharepoint and work with list items for example you should impersonate the current logged user in your application to see who modified, added the list item. I chose this example to be the simplest.
So I created a web part for my sharepoint site.

I added this to the default project created when you choose Sharepoint Web Part project:
c# code:

private string customMessage = "Hello, world!";
[WebBrowsable(true),
WebDescription("Displays a custom message"),
WebDisplayName("Display Message"),
Personalizable(PersonalizationScope.User)]
public string DisplayMessage
{
get { return customMessage; }
set { customMessage = value; }

}

In the render function i added my code. To make a similarity to asp.net you can think of it as page_load handler. Whenever you refresh the page that has the web part on it it executes your code.
Here i get the current logged in user i display it on the screen and then i create a new item in the Announcements List as added by the user logged in:

protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
try
{
HttpContext ctx = HttpContext.Current;
SPWeb web = SPControl.GetContextWeb(this.Context);

if ( (ctx.User != null) &amp;&amp; (ctx.User.Identity != null))
customMessage=ctx.User.Identity.Name;
writer.Write(DisplayMessage);

And we show this way the current logged in user.
Now we impersonate the user and create a new item in the Announcements list in his name. Every logged in user has a token (it identifies the authentication process applied to the user).

SPSite impersonatedSiteCollection = new SPSite( SPControl.GetContextSite(this.Context).ID, token);
SPWeb oWebsiteRoot = impersonatedSiteCollection.OpenWeb();
oWebsiteRoot.AllowUnsafeUpdates = true;
SPList oList = oWebsiteRoot.Lists["Announcements"];

SPListItem oListItem = oList.Items.Add();
oListItem["Title"] = "My Item";
oListItem["Created"] = new DateTime(2004, 1, 23);
oListItem["Modified"] = new DateTime(2005, 10, 1);
oListItem.Update();
}
catch (System.ArgumentException e)
{
customMessage = e.Message ;
writer.Write(DisplayMessage);
}

I put it in a try catch sequence because the current logged in user might not have the rights to add a new item to that list and if so the page that contains the webpart will crash and he would not see it even though he has rights to. With the try catch the webpart will tell him that he has no rights.

Commerce Server 2009