Monday, July 7, 2008

Treeview runtime error on Panel - UpdatePanel - EnsurePanelFix

Today i came across a problem in a web part i was developing.

I had a treeview inside a panel which in turn was inside an Ajax UpdatePanel.

The normal panel had its visibility set to false by default. And in the web part, clicking a button sets the visibility of that panel to true. I used this method to toggle the visibility of the treeview and related controls that resided with it on the panel.

Upon implementing this along with the UpdateProgress control and the EnsurePanelFix method, i started getting runtime errors whenever i tried to expand any of the treeview's nodes (all are collapsed by default).

After spending a lot of time troubleshooting and looking for answers, i discovered that the EnsurePanelFix method was causing the problem. And just for clarity, i'm not using the code provided by microsoft but rather the following simplified version:
ScriptManager.RegisterStartupScript(this,typeof(UnitBPUploadList),
"UpdatePanelFixup",
"_spOriginalFormAction = document.forms[0].action; _spSuppressFormOnSubmitWrapper=true;",
true);


And so i have found that the ONLY workaround for this is to dynamically add and remove the nodes of the treeview instead of making it visible and invisible each time the toggle is performed.
Everything else can be left on a panel and that panel can be set to visible=true or false as much as you like without having it affect anything else.

Just make sure that you NEVER touch the .visibility property of the TreeView control.

-

Tuesday, June 24, 2008

SPList fields - parsing source-code

Here is the source-code to obtain an html table of fields for any list:

(Please note that this example takes place inside the Render(HtmlTextWriter writer) method:

using (SPSite site = new SPSite(SPContext.Current.Site.Url))

{

using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ServerRelativeUrl))

{

SPList list = web.Lists["YourList"];

SPListItemCollection iCol = list.Items;


writer.Write("<table border=\"1\">");

writer.Write("<tr><td><strong>Field name</strong></td><td><strong>Sample value (if any)</strong></td></tr>");

for (int i = 0; i < iCol[0].Fields.Count; i++)

{

writer.Write("<tr><td><strong>");

writer.Write(iCol[0].Fields[i].Title);

writer.Write("</strong><br/>" + iCol[0].Fields[i].Description);

writer.Write("</td><td>");

writer.Write(iCol[0].GetFormattedValue(iCol[0].Fields[i].Title));

writer.Write("</td></tr>");

}

writer.Write("</table>");

}

}


SPList fields

If you've ever worked with fields from a coding point of view in sharepoint 2007 or plan to do so, then this list is invaluable to you.

It contains all the default fields for a SPList item. (Remember that pages are essentially list items and the pages collection is essentially a list).

Field name Sample value (if any)
Content Type ID
0x0100E65E7B14B0BC434CB9F70A29DDD8C22E
Approver Comments

DocumentTitle
at work2.jpg
DocumentTitle
at work2.jpg
File Type

ID
3
Content Type
Item
Modified
6/24/2008 5:07 PM
Created
2/20/2008 1:41 AM
Created By
System Account
Modified By
System Account
Has Copy Destinations

Copy Source

owshiddenversion
2
Workflow Version
1
UI Version
512
Version
1.0
Attachments
False
Approval Status
Approved
Edit

Select
3
Instance ID

Order
300
GUID
{B16BDAD3-7279-4C90-890E-D64D4FF9FE6E}
Workflow Instance ID

URL Path
/corporate/divisions/officeoftheceo/capacitydepoloyment/agencies/Lists/BusinessPortalUploadRecord/3_.000
Path
corporate/divisions/officeoftheceo/capacitydepoloyment/agencies/Lists/BusinessPortalUploadRecord
Modified
6/24/2008 5:07 PM
Created
2/20/2008 1:41 AM
Item Type
0
Effective Permissions Mask
0x7fffffffffffffff
Name
3_.000
Unique Id
389a8e63-0d5d-42c8-b8dc-a3702f566496
ProgId

ScopeId
{8FF6C25F-7D37-4569-823F-4E1C2433F5CF}
HTML File Type

Edit Menu Table Start
3_.000
Edit Menu Table End
3
Name
3_.000
Name
3_.000
Type

Server Relative URL
/corporate/divisions/officeoftheceo/capacitydepoloyment/agencies/Lists/BusinessPortalUploadRecord/3_.000
Encoded Absolute URL
http://dvbmdas15:101/corporate/divisions/officeoftheceo/capacitydepoloyment/agencies/Lists/BusinessPortalUploadRecord/3_.000
File Name
3_
Property Bag

Level
1
Is Current Version
Yes


See next post for source-code on how to replicate this table.

Using AJAX UpdatePanel since Sharepoint SP1

When you start with AJAX and sharepoint 2007 webpart after the year 2007, then it can be pretty daunting because most of the information out there on combining AJAX with Sharepoint 2007 was written in 2007 (end even before that in 2006).

This information is no longer applicable because Sharepoint 2007 SP1 supports AJAX. Sure you still have to modify a couple of things such as the web.config etc. (check my previous posts for a list of checks).

There are hundreds of websites out there that want to teach you how to use AJAX with Sharepoint 2007. Hell there are even several websites that want to teach you how to use AJAX with Sharepoint 2007 BETA!!!. People should surely take more responsibility for these posts and UPDATE or DELETE them when they are no longer applicable. Unfortunately this does not happen.

So let me tell you now that next time you google for information on how to do anything AJAX-related in sharepoint 2007 SP1, do yourself a favour and filter for articles written AFTER January 2008.

So you can safely ignore all those EnsureUpdatePanelFix() and similar pieces of code. Also you can safely ignore BaseWebPart and all other third-party webparts especially designed for ajax use in sharepoint. Using them will just give you more trouble than what its worth.

Wednesday, June 18, 2008

Using AjaxControlToolkit Accordion Control with Sharepoint 2007 web part

Should you wish to use the AjaxControlToolkit accordion control in a Sharepoint 2007 web part,

firstly make sure you have gone through the following list of prerequisites and notes:
Brief overview of requirements for using Ajax with Sharepoint 2007 web parts


  1. You have to make sure you programmatically create the control in the web part codebehind. Do it in the method "protected override void CreateChildControls()"
  2. Define the control as a global variable:
    Accordion Accordion1;
  3. Initialise the control in the CreateChildControls() method
    Accordion1 = new Accordion();
  4. Make sure you give it an ID
    Accordion1.ID = "Accordion1";
  5. Set the selected index
    Accordion1.SelectedIndex = 0;
  6. Set other properties such as FadeTransitions and TransitionDuration etc
    Accordion1.FadeTransitions = true;
    Accordion1.FramesPerSecond = 20;
    Accordion1.TransitionDuration = 100;
    Accordion1.AutoSize = AutoSize.none;
  7. Add the accordion control to the page's controls collection
    this.Controls.Add(Accordion1) (note: this still takes place in the CreateChildControls() method)
  8. Add panes in the following way:
    AccordionPane pane1 = new AccordionPane()
    string header = "this is the pane header";
    pane1.HeaderContainer.Controls.Add(new LiteralControl(header);
    string content = "this is the pane content";
    pane1.ContentContainer.Controls.Add(new LiteralControl(content));
    Accordion1.Panes.Add(pane1);
  9. Remember that the following line of code must ALWAYS be at the end of the CreateChildControls() method:
    base.CreateChildControls();
  10. In your web part's Render(HtmlTextWriter writer) method
    add the following at the location where you want the control to be displayed:
    this.Accordion1.RenderControl(writer);
That should do it.

Brief overview of requirements for using Ajax with Sharepoint 2007 web parts

If you want to use the AjaxControlToolkit controls with Sharepoint 2007,

Notes/Checklist:

  • Installed the Ajax Server Extensions
  • Installed the AjaxControlToolkit
  • Upgraded Sharepoint to Service Pack 1 or later
  • Upgraded WSS 3.0 to Service Pack 1 or later
  • Copied the AjaxControlToolkit.dll file to the bin folder of your portal under C:\Inetpub\wwwroot\wss\VirtualDirectories\yoursite\bin
  • Updated the Web.config by adding relevant entries to support Ajax -> C:\Inetpub\wwwroot\wss\VirtualDirectories\80\web.config (copy entries from web.config in a website you created by using the Ajax Enabled website starter kit in Visual Studio)
  • FORGET ABOUT SMARTPART or any other 3rd party web parts that convert user controls into web parts. That was a crude workaround for versions of sharepoint before service pack 1.
  • Use the web part development add-in for visual studio (use it to develop, deploy and debug)
  • Add Scriptmanager control to your masterpage

    <WebPartPages:SPWebPartManager runat="server"/>

    <asp:ScriptManager ID="ScriptManager1" runat="server"/>
    <-- that is exactly where you must insert it
  • Remember to publish your masterpage after adding the scriptmanager
  • Toolkit controls have to be dynamically constructed in web part codebehind
  • If your webparts are iterating through sub-sites remember to use the SpSecurity.Delegate functionality as described in an earlier post in this blog.
If you're reading this and you see that i've missed something, please let me know.

Remove bad or broken web parts from a page

During the process of developing web parts, you might stumble on to situations where a web part that you've developed is causing errors on a page.

In a wide variety of scenarios, you might want to remove that web part from the specific page but you are unable to do this because the page cannot render.

To remedy this, you can use the Web Part Maintenance page for that specific page.

There is a long convoluted way of reaching this page but the straight-forward way of reaching it is:

> Add the following to the and of your URL: ?contents=1

Example: http://www.mysite.com/sitecol/default.aspx?contents=1

Automatically insert quotes in Visual Studio when editing HTML

A nice feature of Visual Studio 2005 that is DISABLED BY DEFAULT is to automatically insert attribute value quotes.

So when typing something like (td valign= the editor will automatically insert: (td valign="" and place the cursor inbetween the two newly inserted quotation marks.

To enable this feature, follow these steps:
  1. From the menu select Tools | Options
  2. Expand the "Text Editor" node
  3. Expand the "HTML" node
  4. Click on the "Format" node
  5. Tick the "Insert attribute value quotes when typing" tickbox under the "Automatic formatting options" group. (see image below)
  6. Click OK
Thats it.

Fin.

Thursday, March 6, 2008

Requires ScriptManager

ISSUES ISSUES ISSUES!

I got the whole AJAX thing workin in MOSS2007 and its really cool, i've got this accordion control that im using. Thing is tho that it came time to test other user roles and i have this dummy contributor user and once i swapped to that user... it stopped working!!

I suddenly got the "Accordion1_AccordionExtender" requires ScriptManager blA bla bla... and i'm like ..what the frikken hell???

So after rummaging around on yahoo for issues with security i realised that i hadnt PUBLISHED THE FRICKEN MASTERPAGE!!!!!

So yeah hope that saves someone else from wasting all that crappy time!

Wednesday, March 5, 2008

RunWithElevatedPrivelages

I'm sure many many people have tried building web parts that need to perform operations to which the currently logged user potentially doesnt have security clearance for.

I'm one of those persons.

The easiest most effective way to accomplish this is to use the SPSecurity.RunWithElevatedPrivelages(delegate()) method.

When i started looking into this i found several sources indicating that the correct way of using this method is as follows:


SPWeb objWeb = SPControl.GetContextWeb(Context);
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite objElevatedSite = new SPSite(objWeb.Site.ID))
{


using (SPWeb objElevatedWeb = objElevatedSite.OpenWeb())
{
// Allow unsafe updates because you can’t save changes
// during HTTP GET requests.
objElevatedWeb.AllowUnsafeUpdates = true;
SPNavigationNode node = new SPNavigationNode( å
“My Custom Node”, “http://node.url”, true);
objElevatedWeb.Navigation.QuickLaunch.AddAsFirst(node);
objElevatedWeb.Update();
}
}
}
);


And this worked fine for me when using Web User Controls. But somehow when i used this structure in web parts, i got the "using disposed SPWeb object no longer supported" error and it was difficult in this context to select an SPWeb which was not the current contextual web.

Thus i submit to thee THIS method which worked perfectly for me.


SPSecurity.CodeToRunElevated objCode = new SPSecurity.CodeToRunElevated(YourMethod);
SPSecurity.RunWithElevatedPrivileges(objCode);


In this scenario, "YourMethod" is a separate method which you call via the delegate.

Make sure to select any specific webs in the following way (or similar)

SPWeb selectedWeb = SPControl.GetContextWeb(Context).Webs[_targetSiteCollection];

(Actually I havent confirmed this but it worked for me and thats where i stopped).

Hope this helps.