Sunday, December 28, 2008

How do I display content from my organizations' portal in users' "My Site"?

An easy solution...
By Nimrod Geva

MOSS 2007, as I'm sure you all know, enables the creation of a personal site for every user in the organization (called 'My Site').

"My Site" can be used as the user's personal desktop and as an efficient and effective networking tool.

Recently a customer asked me she could display company announcements/news in each employees "My Site".

At first I wanted to answer - "Simply use the Content Query Web Part to aggregate news (or any other list type) from other site, in other words just use it to display the company news in all personal sites." But then I realized that such a glib answer would be misleading. Every "My Site" is actually a separate Site Collection. The Content Query web part aggregates list items within the scope of Site Collection but what about aggregating data located in the portal (one site collection) into the users' personal site (each deployed as a separate site collection)??

I searched for 3rd-party roll-up web parts and found several– all look great but even so – cannot aggregate data located on another site collection. So – KWizCom developed an easy solution. While we were at it we added some cool JavaScript and AJAX effects such as: columns drag & drop (just like in outlook) and in-place editing (no page refresh!!), and added some cool skins.

The result is our new KWizCom SharePoint List Aggregator which is the only roll-up web part that can aggregate data located in another site collection!

KWizCom's SharePoint List Aggregator can aggregate different data types, for example: to list name - all lists that begin with "Project_". This is much more flexible than the Content Query web part that can aggregate data from lists of the same Type/Content Type.

Last but by no means least – there is no need for MOSS (Content Query web part is available only in MOSS) – KWizCom's aggregator web part work also on WSS 3.0 !

Sunday, December 7, 2008

A special KWizCom thanks to our customers – get the FREE ad-on of your choice!

Dear all,



This holiday season we at KWizCom have decided to express our thanks to all of you who have chosen KWizCom for your add-ons, partnered with us in developing new add-ons etc. We want to give everyone who previously ordered a KWizCom product a large holiday bonus.
Click here to receive 1 FREE license for the add-on of your choice.
This gift is worth up to $799 (depending on the add-on you choose)!

This is a no strings attached benefit. All you have to do is to choose your gift and send us your information.

We continually aim to give our customers great service, excellent benefits and top-notch products. Thank you for helping make that possible!


But what if you've never purchased a KWizCom product? We won't leave you behind!
Those who have not yet enjoyed the benefits of KWizCom products won't be left out. We are giving all of you the opportunity to create a holiday bundle that will give you a huge discount - up to 50%!


Click here and get your Christmas bundle today!

From KWizCom –
We wish you all Happy Holidays!
May you always be surrounded with warmth and kindness, family and friends, good health, wealth, safety and happiness!


Friday, November 21, 2008

Want to know how to change MOSS search results sort order?

Hi,

Some of you may have seen my post on how to add rating field to MOSS search results,

Since than I have had several customers that wanted to allow their users to sort the search resutls by that rating field, and not by the relevance / date (Even though I explained that this will break the MOSS search relevance mechanism).

Be that as it may, after searching the web - I managed to locate several "free tools" that does that, but I was determined to find a more simple solution that did not involve downloading/executing any out side code on my server.

Finally, I found that this can be done by a very simple change to the XSL of the main search results body web part (the same one we modified in the previouse post).

Simply replace this statement in the XSL:
<xsl:apply-templates />

With this one:
<xsl:apply-templates>
<xsl:sort select="rating"/>
</xsl:apply-templates>


Note:
You might want to allow the user to sort by relevance / date and rating, and not only rating. In that case you should use the actions web part above the main search resutls web part and add a new option there to specify when it should sort by rating and not do it hard-coded in the results XSL web part.


Hope this helps,
Shai Petel,
VP R&D

Tuesday, October 7, 2008

Adding "Contact Us" to a SharePoint site

Whether you are hosting a WSS support site, or a publishing eCommerce site hosted with MOSS WCM, a lot of times you will find the need to allow your users to contact you using a simple "Contact us" form.

Well, this cannot be more simple in SharePoint.

This is how it is done with no development at all:

Create a list named Contact Us with fields: Subject, Body, To.

the To field - can be a user field or a choice field.

If it is a choice field (like: sales / support / partnersprogram etc...) you can do a WorkFlow using SharePoint Designer workflow wizard that sends the email to the manager / mailbox address of that subject.

If it is a user field - you create a view called: MyEmails - and set the filter to show items where To=[Me], so every user gets his "emails". Then you set up alerts to all users for new items in that view so they would get an email whenever a new item was created. (or you can do the WF solution as well).

Simple, Free and Out of the box.

Users will not see the actual email address of the person they are sending the email to, and the email will be sent from the SharePoint itself - so no spam.

You can extend this solution by adding a custom "Contact Us" form to create an item in the home page (use Custom List Form in SharePoint Designer, or Item Editor Plus from KWizCom to do so).

Also - you can use SharePoint to track these issues by adding a "Status" column that the user in charge can mark as "New, Waiting for someone else, Completed", or use the WF to create a task for each issue that is assigned to someone...

Lots of ideas, the nice thing is it is all free and you can extend and improve your solution as you go along!

* If you need help with configuring such a solution, contact me as we offer online training for these subject and in 4-5 hours online training you will be able to create and manage your own solutions even if you don't have any development experience.

Shai Petel,
VP Professional Services
KWizCom

Web site does not load well in IE 8

Using Internet Explorer 8, some web pages may appear broken or not load correctly...

We all remember how IE 7 broke 70% of the pages in Internet...
The bad news are IE 8 is going to do the same.

The good news are: It does not have to!

Microsoft has introduced a new meta tag you can add per page / site that will ensure IE8 clients will render the page in backward compatibility mode, so your site won't be broken...

Simply by adding a meta-tag to the response header:
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

IE 8 clients will emulate IE 7 compatibility mode and your site should be able to load correctly.

More info for Per page:
http://msdn.microsoft.com/en-ca/library/cc817574.aspx

More info for Per site:
http://msdn.microsoft.com/en-ca/library/cc817572.aspx


Enjoy,
Shai Petel

Monday, October 6, 2008

CRM Error: Generic SQL Error Code: 0x80044150

So, I have seen and checked very proposed solution to this error on the web.

The only problem associated with this issue I did not see any record of is of course the error I had with a customer recently...

The issue is complicated-simple issue...

Simple explanation would be:
Once you export and entity, add a new attribute with the same name as an existing one (not case sensitive - meaning 1= new_myattribute 2=New_myattribute) you will get this error.

Simple, Right?

Now, for the complicated way of getting this error...

Normally, the CRM will lower-case all letters in the attribute and add the "new_" prefix for you.

So - when looking for a property to check if it exists I used to have a lower-case case sensitive XML XPath search for it, and if I did not find it - I knew it was safe to add it...

Only that apparently the CRM 3.0 and CRM 4.0 has some inconsistency with the prefix of custom attributes...

One adds new_ while the other adds New_, this means that one of our customers who used the CRM SharePoint connector in CRM 3.0, upgraded the solution to CRM 4.0, and run our solution again - ended up with this error message since he had the old field from the upgrade and we were trying to add it as duplicated in the new version since we could not find it...

Well - complicated enough?

I will keep the conclusion short -
1: Be sure not to add duplicate attributes, or import will fail.
2: When looking for attributes - don't use case-sensitive comparison (although tempting in XML)!
3: Email the CRM developer guys and request nicely for better error messages ( don't tell them I sent you :) )

Well, Please feel free to post here any other problems / solutions related to this very generic error code.

Just for the record - the error code mostly refers to trying to assign data into a field that is too long... so if you didn't check that first - this would be a good time to do so... :)

Error using web part connection in list item form

Ever go this error when using a connection?
"Web Part Error: This page has exceeded its data fetch limit for connected Web Parts. Try disconnecting one or more Web Parts to correct the problem."

Well, it is known that the filter connections sometimes invoke this, and there are ways to fix it... but - I just found a "fluke" in the SharePoint connections infrastructure that is not caused by bad-coding at all.

As a matter of fact - I can reproduce it using only out of the box web parts and no custom code at all!

We wanted to have in our customers list, when a user go in to the display form of a customer, to get a list of contacts associated with this customer from the contact list.

So - we added the List View web part of Contacts list into the DispForm.aspx of the Customer list.

Than we used Custom Item Property (more information on www.kwizcom.com) that gets the current customer's title and sends it as a filter to the List View web part...

Sounds simple, only to find out that using List View web part on a display form, with a filter connection - is apparently (and unspoken) not supported!!!

It will always give an error "Web Part Error: This page has exceeded its data fetch limit for connected Web Parts. Try disconnecting one or more Web Parts to correct the problem.".

This has nothing to do with my code ( I found out couple of hours later ) since if I try it using the Query string filter web part - I get the same result every time.

Ok, after a while, I started looking for other creative solutions and found a work-around for this issue.

Converting the List View web part to a Data View web part will solve this issue and will allow you to add a filtered view of related information!!!

(Sorry for the !!!, just excited that it is not my code that caused the issue :) )

(* hint: to convert list view into data view - open the page in SharePoint Designer, right click on the list view and select the "convert to data view" option... )

Well, hope this helps save some lives, keep me posted if you have additions / questions,

Shai Petel,
VP Professional Services
KWizCom

Tuesday, September 30, 2008

Export SharePoint list to excel using DataGrid

From time to time I learn that the OOTB export to excel capabilities of SharePoint are missing some edge.

For instance - the latest thing my colleague found is that if you do not have excel 2007 but earlier versions, it does not export some column types correctly, or are completely missing.

So, I have created a simple ASP.NET web part that will allow the user to export the list items / list view into excel, that does not require a specific version of excel to be installed on the client.

The concept is simple:
Connect to a list / view,
Get items as DataTable
Connect DataTable to a DataGrid
Export DataGrid to excel.

So, to get the list items / view items into a Data Table, I used one of these code samples:
For list URL + view ID:
using (SPSite site = new SPSite(txtListUrl.Text))
{
  using (SPWeb web = site.OpenWeb())
  {
    SPList list = web.GetListFromUrl(txtListUrl.Text);
    DataTable items = list.GetItems(list.Views[new Guid(cmbListView.SelectedValue)]).GetDataTable();

    ExportToExcel(items);
  }
}
Or, if you plan to place the WP in the list view page - here it is working with the SPContext.Current.List:
SPList list = SPContext.Current.List;
DataTable items = list.Items.GetDataTable();

ExportToExcel(items);

Ok, so now we have the DataTable, all we have to do is implement the code that will export the DataTable to excel using Data Grid:
private void ExportToExcel(DataTable items)
{
  theGrid = new DataGrid();
  theGrid.DataSource = items;
  theGrid.DataBind();

  Page.Response.Clear();
  Page.Response.ContentType = "application/vnd.ms-excel";
  Page.Response.Charset = "utf-8";
  Page.Response.AddHeader("Content-Disposition", "attachment;filename="+DateTime.Now.ToString("yyyyMMdd_hhmmss")+".xls");

  System.IO.StringWriter oStringWriter = new System.IO.StringWriter();
  System.Web.UI.HtmlTextWriter oHtmlTextWriter = new   System.Web.UI.HtmlTextWriter(oStringWriter);
  theGrid.RenderControl(oHtmlTextWriter);

  Page.Response.Write(oStringWriter.ToString());
  Page.Response.End();
}

And guess what? It is that simple!

Enjoy,

Shai Petel
KWizCom VP Professional Services

Wednesday, September 10, 2008

Catalog: AnchorProject. A master merge was started due to an external request.

Today I was getting this warning in my server event log:
event id 4164 and 4103
Catalog: AnchorProject. A master merge was started due to an external request.

Since it was flodding my event viewer I didnt even see the other issues there... but one of the servers CPU was in max usage all the time (100%, but since we had 2 CPU task manager shows 50% total usage)...

Well, as I was digging up more info here is what I came up with and how I solved this issue:

1: I was getting an error on a certain page from within a site ( a custom list view ) that referenced the wrong master page - /_layouts/application.master. Since the celler page was in the list and not in the /_layouts/ folder this was blocked by ASP.NET
2: The caller user was my search user, lucky it is a unique user so I could be sure it was invoked by the indexer

So, after I fixed / deleted these 2 pages - the indexer stopped trying to index them, and 30 seconds after that the errors were gone and CPU back to normal...

Hope this helps you guys too, I will update if I get more info on this.

Thursday, August 21, 2008

How to add MOSS search to internet explorer 7 search box

This is a rather easy and cool task...

May time people ask me how they can add their SharePoint search to the internet explorer 7 search box:


Now, I know... if you have internet access - there is no problem. Just click on the "Find more providers" and follow the instructions and you are done.

But - some customers do not have internet access on their client machine, or some administrators would like to publish this configuration through an organization... so a little registry tweaking will do the trick!

Simple take this text:
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\SearchScopes\{33093C07-A5A2-418A-AB53-C187BC95DAED}]
"DisplayName"="KWizCom Portal Search"
"URL"="http://portal.kwizcom.com/searchcenter/Pages/Results.aspx?k={searchTerms}"


Replace the "KWizCom Portal Search" with the search provider title you want,
Replace the URL address with the one of your search page (to find out what it is - Simple do a search and copy the resutls page address), and replace the word(s) you searched for with the {searchTerms} token.

Save it as a search.reg file using notepad, and run it!

Also, you can add almost any other search provider in the same way, for example to search in KWizCom addons site you can use this search address:
http://www.kwizcom.com/search.asp?SearchString={searchTerms}&pageID=1


Easy, isn't it?

Thursday, August 7, 2008

How to add rating field to MOSS search results?

This guide will show you how to add custom fields – specifically a KWizCom Rating field to the MOSS search results page.

This article will only demonstrate how to add the field to the results, but much more things can be achieved using simple XSL editing like: Add sorting or grouping by special fields.

This task is mainly done in 2 parts:
Part 1: Add the Rating field to the search Index Engine
Part 2: Customizing the search results page

This article assumes you have installed KWizCom Rating Field Type and created a field in a list named: “Rate” of type “Rating”. If you haven’t done so please complete these requirements before you continue.

Part 1: Add the Rating field to the search Index Engine

1. Open SharePoint Central Administration
2. Browse to your Shared Services Provider (SSP)
3. At the SSP home page, please click “Search Settings”
4. Go to “Metadata Property Mappings” link
5. Click “New Managed Property”
6. Set property name to “Rating”, Type = “Decimal”
7. Select “Include values from a single crawled property based on the order specified”
8. Click on “Add Mapping”
9. Search for your tags fields. If you do not see any of your tags fields – you may have to manually crawl the SharePoint content source before you can continue.
10. If you have more than one property of type Rating – please search all of them and add them to this list.
11. Click OK twice to confirm the new managed property.

Part 2: Customizing the search results page

12. Browse to your search site
13. Go to the results page ( or simple perform a simple search go get there)
14. Click Site Actions -> Edit Page
15. Locate the “Core Results” web part
16. Choose to modify the web part properties
First – we will add the Rating managed property to the results XML:
17. Open the “Results Query Options” group, and click to edit “Selected Columns” property
18. Add the Managed Property “Rating” to the Column Names.
19. Next, we will have to edit the XSL for the result item template.
20. Expand the “Data View Properties” tool part, and click “XSL Editor”
21. Locate in the XSL the template “<xsl:template match="Result">” and update it to look like this:
<!-- This template is called for each result -->
<xsl:template match="Result">
<xsl:variable name="id" select="id">
<xsl:variable name="url" select="url">
<span class="srch-Icon">
<a href="{$url}" id="{concat('CSR_IMG_',$id)}" title="{$url}">
<img align="absmiddle" src="{imageurl}" border="0" alt="{imageurl/@imageurldescription}" />
</a>
</span>
<span class="srch-Title">
<a href="{$url}" id="{concat('CSR_',$id)}" title="{$url}">
<xsl:choose>
<xsl:when test="hithighlightedproperties/HHTitle[. != '']">
<xsl:call-template name="HitHighlighting">
<xsl:with-param name="hh" select="hithighlightedproperties/HHTitle">
</xsl:call-template>
</xsl:when>
<xsl:otherwise><xsl:value-of select="title"></xsl:otherwise>
</xsl:choose>

<xsl:if test="rating > 0">
User Rating: <b><xsl:value-of select="rating"></b>
</xsl:if>

</a>
<br/>
</span>

<xsl:choose>
<xsl:when test="$IsThisListScope = 'True' and contentclass[. = 'STS_ListItem_PictureLibrary'] and picturethumbnailurl[. != '']">
<div style="padding-top: 2px; padding-bottom: 2px;">
<a href="{$url}" id="{concat('CSR_P',$id)}" title="{title}">
<img src="{picturethumbnailurl}" alt="" />
</a>
</div>
</xsl:when>
</xsl:choose>
<div class="srch-Description">
<xsl:choose>
<xsl:when test="hithighlightedsummary[. != '']">
<xsl:call-template name="HitHighlighting">
<xsl:with-param name="hh" select="hithighlightedsummary">
</xsl:call-template>
</xsl:when>
<xsl:when test="description[. != '']">
<xsl:value-of select="description">
</xsl:when>
</xsl:choose>
</div >
<p class="srch-Metadata">
<span class="srch-URL">
<a href="{$url}" id="{concat('CSR_U_',$id)}" title="{$url}" dir="ltr">
<xsl:choose>
<xsl:when test="hithighlightedproperties/HHUrl[. != '']">
<xsl:call-template name="HitHighlighting">
<xsl:with-param name="hh" select="hithighlightedproperties/HHUrl">
</xsl:call-template>
</xsl:when>
<xsl:otherwise><xsl:value-of select="url"></xsl:otherwise>
</xsl:choose>
</a>
</span>
<xsl:call-template name="DisplaySize">
<xsl:with-param name="size" select="size">
</xsl:call-template>
<xsl:call-template name="DisplayString">
<xsl:with-param name="str" select="author">
</xsl:call-template>
<xsl:call-template name="DisplayString">
<xsl:with-param name="str" select="write">
</xsl:call-template>
<xsl:call-template name="DisplayCollapsingStatusLink">
<xsl:with-param name="status" select="collapsingstatus">
<xsl:with-param name="urlEncoded" select="urlEncoded">
<xsl:with-param name="id" select="concat('CSR_CS_',$id)">
</xsl:call-template>
</p>
</xsl:template>
22. You can only add the following to the existing XSL you already had there instead of pasting the entire tag:
<xsl:if test="rating > 0">
User Rating: <b><xsl:value-of select="rating"></b>
</xsl:if>
23. And you should get results that will resemble this:
24. For debugging reasons, should you wish to view the results RAW XML, copy the existing XSL to notepad for backup, and use this XSL instead:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes">
<xsl:template match="/">
<xmp><xsl:copy-of select="*"></xmp>
</xsl:template>
</xsl:stylesheet>


Hope this helps, if you have trouble doing it yourself we offer this customization as a part of our remote consulting services, contact sales at kwizcom.com by email for more information on that.

Thanks, Shai Petel.

Friday, August 1, 2008

STSADM Restore Error - Version does not match

Another thig you learn the hard way -

When you are using STSADM -o export
You should use STSADM -o import

So far so good... buy when the time in the night gets late - and you try to use STSADM -o restore... that can take a while to figure out :)

So - wierd thing is you will get an error saying the backup is from a newer SharePoint version and you need to update your installation... Naturally - I wasted a good hour making sure I have latest version intalled.

Goggle did not help on this one... Finally I noticed I am using the wrong command - So if you googled this in the same situation - make sure you are using the correct command!

Backup - Restore
Export - Import

:)

Good luck!

Thursday, July 31, 2008

SharePoint Configuration Wizard Fail

Hey,

Just installed a KB from microsoft on my SharePoint server and when I tried to run the configuration wizard afterwards I got a strange error message:
Could not start service SPSearch

Naturally, I went to have a look in "services" and I found that the "windows sharepoint services search" service was stopped, and could not start...

Starting it says it cannot login due to wrong username / password... strange...
I updated the correct password - started it - OK,

So - back to the wizard... running the wizard - same error message - checking the service - login failed...
strange...

After 4 or 5 times my stuck trace overflowed I guess, so I started thinking... why would the wizard change my service user name / passwor?

Than it came to me: I updated the SP admin user password a while back, and thought I updated it every where. Even used some stsadm -o upgradefarmcredentials and other credential updates...

But - than I came accross this command:
stsadm -o spsearch -farmserviceaccount domain\spadminuseraccount -farmservicepassword xxxxx

After runnign this command the wizard completed successfully.

I must say that the only reason I knew it had anything to do with the SPSearch is by watching every step of the wizard. The after-crash log file they propose is useless!!!

Well, when failing the wizard - here is another thing to keep in mind!

How to add Source parameter to SharePoint links automatically?

Hi,

You know when you click a link to view item in SharePoint list and when you click Close it goes back to the page you came from?
Or when you edit an item - clicking OK returns you the page you original came from?

Well, you may have noticed SharePoint does that by adding the "Source=" url query string parameter to the address, and uses it to knwo where to go after we user is done.

So, basically - you can use that to redirect the user anywhere you want after he finishes with the form you sent him to, but - what if you want it to automatically be set to the current page's address?
Of course you can hard code the page's address, but what about additional query string parameters, of multiple addresses to the same page (different host headers)?

There is an easier way - the way SharePoint adds the "Source" parameter -
simply add this bit to your a link in HTML:
ONCLICK="GoToLink(this);return false;"

so that your link will look like:
<a href="/Docs/Lists/Announcements/DispForm.aspx?ID=1" ONCLICK="GoToLink(this);return false;">view item</a>

The GoToLink will automatically add thye current page's address before navigating to the HREF you entered!

Shai Petel

Monday, July 28, 2008

VM Server cannot connect to network after restore from save state

Ok, I know I am a bit off topic here, but we all use VMs, Right?

So let me start by congratulating MS for their Win2k8 64bit Hyper-V server (Amazing!), but for most of us we still use the Virtual Server on Win2k3, right?

Well, after installing the SP1 for the virtual server R2 i started having this problem:

I Saved state of my machine
Restarted the server (host)
Resumed the virtual machine and boom - the virtual server service halt and crashed, and after manually starting it i got an error starting virtual network connection and no more network for that machine...

Here is the error message:
The virtual machine cannot connect virtual network adapter 1 because another virtual machine with the MAC address is already running. This virtual network adapter will be left disconnected.

Only solution I found (worked some times) was to restart the server, start another machine first (dummy one i dont use) stopping it and than i had a 60% chance that the problem was solved for that session.

Now, for my network I have to use Static MAC address for network cards so i cannot change the MAC address on the VMs.

Today I found a new solution for that issue:
I went to the network card where the virtual network is connected, clicked properties, and unchecked the "virtual machine network services".

I clicked OK, waited for things to proccess my change, and than went back in and checked it again.

And what do you know? Things started to work again - no restart... no removing the virtual machine...

Well, hope it helps you guys, I seen a lot of posts on this but none reported a solution like that.

Shai.

Monday, July 21, 2008

How to hide a field in edit or new item form

I get this question a lot...

How can we hide a field from a specific user, or completely from the edit or new form?

Well the hard way (and SharePoint approved) would be to write some .NET code against the SharePoint API and changing the field visibility - I will not go into it now.

Other way - still hard, is to change the field CAML definitions (Xml files) - also for existing fields not recommended at all - I will not go into it now as well.

There is a much easier way, no code envolved, simply by adding a content editor web part to the page with some javascript that will hide the field content form the user.

It is not perfect, sure. It can be fooled, right.
But for those of you that just need it for cosmetic reasons mostly, this is the perfect solution.

I actually covered that in an older post, I just think its title was not clear enough - please follow this link for the complete how-to manual.
http://kwizcom.blogspot.com/2007/08/managing-field-control-visibility-way.html

Thanks, Shai.

Thursday, July 3, 2008

Creating a view for birthday

Well, I struggled with this for an hour or so until I finally found a solution...

Scenario:
our customer has a list of users with a date field with their Birthday.
He wishes to see the upcoming birthdays for users in the upcoming week.

Problem:
The birthdate field holds the actual birthday of the user (i.e. July 24 1980), but he wants to see it as July 24 2008... July 24 2009... and so on.

Well, since we cannot use the [Today] field in calculated column (all tricks wont work - the field won't update!), I have conjured this solution that only asks for a yearly update to the column:

First, we have to create a calculated column that results in the current year birthdate
(from July 24 1980 to July 24 2008)

1 - create a date column to hold real birthday (named: BDay) or type date.
2 - create a calculate column to hold this year's BDay (named: YBDay).
3 - set the output type of the calculated value to "Date and Time"
4 - use this formula to generate its value:
=DATE(2008,MONTH(BDay),DAY(BDay))


Now, the rest is easy:
You create a view and set filter to 2 conditions:
where [this year birthday] >= [Today]
And
where [this year birthday] <= [Today] + 7


Now, you see all birthdays for the upcoming week!

Just remember - next year you will have to update the formula of the calculated field.

Hope this helps you - sure did saved me :)

Monday, June 30, 2008

Add content to SPList Item view form

Hi,

I am sure this is a shared whim to many SharePoint implementation -
You have a list of cusotmers or what not, and you want to add more information on the view item form, like so:


So basically when you view an item on that list - you will see additional information like:
* Results on that customer from google on an iframe
* Stock information for that customer
* Information from external system - showing in a frame that gets the customer ID in query string

And much much more.

Right so first thing you have to do is to learn that the list forms (edit, new and display) are actually normal web part pages, with one web part by default.

You can very easily add more web parts to that form, all you have to do is to add this to the query string of the form and you will go into edit mode of that page:
&ToolPaneView=2



Another way is to paste this into your address bar:
javascript:MSOLayout_ChangeLayoutMode(false)

I know you can use SharePoint Designer - but this is much easier and does not involve nothing more than your browser...

Now that you got into edit form of the current item - you can add any web part you want.

Inside your web part code - you can make use of the SPContext.Current.Item to get the current item that is being loaded to the form and use it to render what ever you like.

But wait!

Actually, I just finished creating a new product called "Current Item Property" that does that and more:

By adding it to a list item form or to a WCM publishing page (or to a web part page in a document library for that matter) you will be able to do almost anything you wish.

How does it work?
2 simple properties of the web part:
First - allows you to specify what fields from the current item you want to use
Second - allows you to choose how to format that information in C# syntax (using {0},{1} etc).

After you set up the information you want - this web part can either send it by connection to another web part to use (like RSS viewer as the RSS feed url) or is can simply write it to the page (when you want to create HTML from the information, or writing an iframe with changing URL).

So - lets go over what can be done with this (few examples from my customer)

We are starting with a simple list:


1 - Showing RSS information for partner


- Create a field in the list called "Stock", and set the stock ID for each partner
- Add the "Current Item Property" web part to the page


- Set it to use "Stock" field
- Set the format to a RSS URL: http://finance.yahoo.com/rss/headline?s={0}


- Add an RSS Viewer to the page


- Connect the two web parts using the RSS viewer "Get RSS URL" connection


Done!


2 - Showing Stock infromation for customer


- Create a field in the list called "Stock", and set the stock ID for each partner
- Add the "Current Item Property" web part to the page
- Set it to use "Stock" field
- Set the format to the iframe: <iframe style="WIDTH: 400px; HEIGHT: 150px" src="http://ichart.finance.yahoo.com/t?s={0}" frameborder="0"></iframe>

- Check the property "Show Content"


Done!

3 - Showing google search results for issue


- Add the "Current Item Property" web part to the page
- Set it to use "Title" field
- Set the format to the iframe: <iframe style="WIDTH: 400px; HEIGHT: 150px" src="http://www.google.com/search?q={0}" frameborder="0"><iframe>
- Check the property "Show Content"
Done!

This way it took me 5 minutes to add more content to the list items!
The product will be released soon and it will come with few format templates for: RSS, IFrames etc - this is what we are working on now: how to package it and how to use it.

If you want more information on this - email us at sales@kwizcom.com or visit http://www.kwizcom.com

Thanks, Shai.

Friday, June 27, 2008

CRM 4 Web Service 401: Unauthorized error

Hi all,

Been upgrading some of our CRM 3.0 components to CRM 4.0 version, just to find out a lot was changed in the web services access.

For one, now that CRM supports hosted mode, more than one organization could be configured so now you have to set up the organization you are working on with your web services serquests.

This did not took me long to find out - just call the CrmDiscoveryService, create a new RetrieveOrganizationsRequest request, and execute it.
Code:
crmDisco.CrmDiscoveryService ds = new KWizCom.CRM.Utility.crmDisco.CrmDiscoveryService();
ds.Url = CrmWebServicesUrl + "AD/CrmDiscoveryService.asmx";
ds.PreAuthenticate = true;
ds.UseDefaultCredentials = true;
//create request
crmDisco.RetrieveOrganizationsRequest r = new KWizCom.CRM.Utility.crmDisco.RetrieveOrganizationsRequest();
crmDisco.RetrieveOrganizationsResponse rr = (crmDisco.RetrieveOrganizationsResponse)ds.Execute(r);
SetOrganization(rr.OrganizationDetails[0]);


And now that you got your organization (first one in the array), you need to use it when calling all other web service (example: creating CrmService and MetadataService
Code:
crmMeta.CrmAuthenticationToken token = new crmMeta.CrmAuthenticationToken();
token.OrganizationName = this.Organization.OrganizationName;
token.AuthenticationType = Enums.AuthenticationType.AD;

this.metadataService = new crmMeta.MetadataService();
this.metadataService.Url = this.Organization.CrmMetadataServiceUrl;
this.metadataService.CrmAuthenticationTokenValue = token;
this.metadataService.PreAuthenticate = true;
this.metadataService.UseDefaultCredentials = true;

crm.CrmAuthenticationToken token2 = new crm.CrmAuthenticationToken();
token2.OrganizationName = this.Organization.OrganizationName;
token2.AuthenticationType = Enums.AuthenticationType.AD;

this.crmService = new crm.CrmService();
this.crmService.Url = this.Organization.CrmServiceUrl;
this.crmService.CrmAuthenticationTokenValue = token2;
this.crmService.PreAuthenticate = true;
this.crmService.UseDefaultCredentials = true;


Now you are all set for using the web services Under The Current User Account!!!.

What if, like me, you need to call the web service using a user name and password?

The logical to do is impersonation in web services 101:
Create a NetworkCredential Object, and set it to your crmService.Credentials,
like so:
ICredentials WebServiceCredentials = new System.Net.NetworkCredential(userName,password,domain);
this.crmService.UseDefaultCredentials = false;
this.crmService.Credentials = WebServiceCredentials;


Right? Wrong!

CRM web service will return 401 error (unauthorized access) every time you do it.

The solution for this was found in a great msdn post:
http://msdn.microsoft.com/en-us/library/cc151049.aspx

The I found that the web service credentials must not be changed at all.
What needs to be done it to make the request under a user with permissions to the CRM (like administrator or something), and pass the user name and password in the request itself.

For getting the organization, you will need to modify your code like this:
crmDisco.CrmDiscoveryService ds = new KWizCom.CRM.Utility.crmDisco.CrmDiscoveryService();
ds.Url = CrmWebServicesUrl + "AD/CrmDiscoveryService.asmx";
ds.PreAuthenticate = true;
ds.UseDefaultCredentials = true;
//create request
crmDisco.RetrieveOrganizationsRequest r = new KWizCom.CRM.Utility.crmDisco.RetrieveOrganizationsRequest();
if (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password))
{
r.UserId = this.Domain + "\\" + this.UserName;
r.Password = this.Password;
}

crmDisco.RetrieveOrganizationsResponse rr = (crmDisco.RetrieveOrganizationsResponse)ds.Execute(r);

SetOrganization(rr.OrganizationDetails[0]);


And also - you will have to get a ticket for the other web services authentication:
RetrieveCrmTicketRequest ticketRequest = new RetrieveCrmTicketRequest();
ticketRequest.OrganizationName = Organization.OrganizationName;
ticketRequest.UserId = this.Domain + "\\" + this.UserName;
ticketRequest.Password = this.Password;
ticketResponse = (RetrieveCrmTicketResponse)ds.Execute(ticketRequest);


Using the response later when you configure your other web services like so:

crmMeta.CrmAuthenticationToken token = new crmMeta.CrmAuthenticationToken();
token.OrganizationName = this.Organization.OrganizationName;
token.AuthenticationType = Enums.AuthenticationType.AD;
if( ticketResponse != null )
token.CrmTicket = ticketResponse.CrmTicket;

this.metadataService = new crmMeta.MetadataService();
this.metadataService.Url = this.Organization.CrmMetadataServiceUrl;
this.metadataService.CrmAuthenticationTokenValue = token;
this.metadataService.PreAuthenticate = true;
this.metadataService.UseDefaultCredentials = true;

crm.CrmAuthenticationToken token2 = new crm.CrmAuthenticationToken();
token2.OrganizationName = this.Organization.OrganizationName;
token2.AuthenticationType = Enums.AuthenticationType.AD;
if (ticketResponse != null)
token2.CrmTicket = ticketResponse.CrmTicket;

this.crmService = new crm.CrmService();
this.crmService.Url = this.Organization.CrmServiceUrl;
this.crmService.CrmAuthenticationTokenValue = token2;
this.crmService.PreAuthenticate = true;
this.crmService.UseDefaultCredentials = true;


Now, you should be able to call the web services with impersonation to other CRM accounts...

Hope this helps you, I sure got stuck on this for a while.

Thanks, Shai.

Tuesday, June 24, 2008

Unable to add selected web part(s).

You know this error?

You just developed a new web part, all excited and ready to test it and wham!

Unable to add selected web part(s).
[Web Part Title]: One of the properties of the Web Part has an incorrect format. Windows SharePoint Services cannot deserialize the Web Part. Check the format of the properties and try again.

Well, this keeps happening to me (not the first time, and definitly not the last) so I thought I'd share one of the reasons for this message to appear.

This meesage can apear in various situations - so feel free to comment with your own "check list" for this error.

Reason 1:
Check your class definitions. In most cases - if you forget to mark it as "public class" you will get this error.

Reason 2:
Check your properties definitions. Could it be that custom logic in get/set throws and exception?

Reason 3:
Check your DWP/Webpart file. It may point to a property that does not exist (removed / spelling mistake), or the assembly is not registered correctly. Best way to troubleshoot this is: Go to your site collection settings, to web parts gallery, click "new" and add your web part to the gallery. Try the new DWP/Webpart file created - does it work?

Reason 4:
For Bin installations - make sure your DLL is in the bin folder of the current web application. Make sure it is registered as safe control in the web.config with no spelling mistakes.

Reason 5:
For GAC installations - make sure your DLL is in the GAC, if you changed it recently try an IISRESET. Also - Make sure it is registered as safe control in the web.config for each web application with no spelling mistaked.

Ok, this is what I can come up with now... Share your experience, this error can get pretty annoying!

Hope I helped save lifes on this (or at least, made the world a better place with less developers screaming in the middle of the night).

Brought to you as a public service by Shai, KWizCom :)

Wednesday, June 18, 2008

How to improve SEO of you WCM sites

Well, as many of you might know - the most important thing for an internet facing web site is to be found easily in the leading search engines.

Because it does not matter how nice and sexy you "pimped" your web site, nor how relevant and profound is the content - if no one can find it your web site is as good as dead.


Ok, so you will be happy to learn that WCM (Web content management) sites that are created in SharePoint 2007 are pretty SEO-aware (Search Engine Optimization), and this comes a long way for you.


Some key features you enjoy with no hard work:


* Navigation, is configured OOTB (Out Of The Box) to reach all pages, expose them to the search bot / spider / what-you-might-call-it. All links are true a href links, no scripts.
* Zero to none use of hidden frames (only place you'll find them is in authoring mode
* Caching support and special attention for anonymous users (used by the search engines)


And much much more...



But - we are here to see what can we do to make it even better? How can I improve my site SEO?



Well, from a little research I did for a customer of mine while back we found 3 things that are actually can improve our SEO greatly.
(Important: I and not teaching how to cheat search engines! This is very dangerouse to play with. Simply how to make your site friendlier to search engines. You still have to have good content, incoming links and such to get good ratings on your site)



1: Turning off the view state.
2: Adding a site map for google.
3: Adding meta-tags for keywords and description for relevant content pages (advanced)

Ok, so let's go over these options and see what is the benefit and how it can be achieved:


Turning off the view state


What is gained?


If you right click->view source on any content page in MOSS you will see right at the beginning of the body tag you will see a input type hidden tag with id=__VIEWSTATE... then, its value will pretty much take your entire page so you'll have to scroll down several times...

So, apparently this gigantic piece of information is something that most search engines do not like to say the least. Especially when it comes before you true content of the page - it ruins your content rating in the search results!

Another obvious reason is, your page is larger... and larger pages are slower to load, and search engines will mark your page as a slower page... we don't want that.

How is it done?


Removing the view state from your WCM web application is rather easy. Simply go to your web application root directory (usually smth like: c:\inetpub\wwwroot\wss\xxxx),backup web.config file, and open it for edit in notepad. Look for enableViewState="true" and change it to false.

No need for IISRESET, but you site will experience a very small delay on the next request.

Adding a site map for google.

What is gained?

When a search engine (google in my example) starts indexing a web site it first of all checks to see if someone had prepared a "work order" for him. This "work-order" is what we call a sitemap / site map XML file that will allow us to make special requests for the crawler when it is working on our site.

If we do not have such a sitemap file, the engine will just open the home page of our web site and start crawling all links it can find on it for sub pages and so on and so forth...

This is usually good enough, except for cases where:

We want to have a section in our site that is not exposed by a link at the top site. Like http://www.kwizcom.com/ will not show a link to www.kwizcom.com/support (only example) which will hold our products support forum.

In this case - with no site map, our /support site will not be available at google at all.

Another problem we can prevent using a site map file is, when you have the same content in 3 different pages on your web site. 1 at the home page, and twice at the specific product information pages... Google will think you keep duplicate content and will lower your web site rank!

Using a sitemap, you can choose specifically what pages you want google to crawl, what pages are more important than others and what pages you don't want him to load.

One last benefit you gain by using a site map is that you can tell the engine what is the lifespan of each of your pages. Meaning: how often does its content change - monthly? weekly? so google will be sure to check it up every once in a while and update its content. Cool, eh?

How is it done?

Well, building a site map for MOSS (or any site for that matter) can of course be done manually, but you have to keep in mind that we are talking about a lot of pages to add to the XML files and this can be very time consuming!

Furthermore, you have to rebuild your site map every once in a while to reflect changes, additions and deletions...

You can develop a utility that does that for you, or use our site map builder here:

http://www.kwizcom.com/ProductPage.asp?ProductID=737&ProductSubNodeID=738

Once you got your hands on a site map generator, your work is just starting:

You will need to make changes in the XML to hide pages you don't want to show, change rating for more important pages and customize other information on it to match your requirements.

Adding meta-tags for keywords and description for relevant content pages (advanced)


What is gained?

By adding a meta tags of keywords and description to your pages you will let the search engine what content is your web site or web page targets.

This helps to raise the quality of the content in your web site. You may want to add specific keywords /description to all pages, and allow some pages to have additional information added to them.

How is it done?

Doing this can be very simple or very complex depends on your needs...

In the most simple straigh forward way - just edit your web site's master page and add the meta tags for keywords + description to the HTML head node like so:

<meta name="Description" content="KWizCom, knowledge worker components">

<meta name="Keywords" content="buy web parts, products, sharepoint, wss, moss">

But, if you requier your content to be changed according to the information of the current page (let's say you wish the page's title to go in to the description along with the site's name, and you have a metadata field named: keywords you wish to be loaded into the keywords tag), things get a little tricky.

But not to fear! I have created a control that will allow you to plant it in the master page and define what exactly you wish to see in these meta tags... it's just that using it is a bit tricky, so for now I don't have time to elaborate. But if you want it anyway before I manage to write a post about it - write me to shai at kwizcom.com and I will send it to you and try to help you configure it.



Ok, that concludes my post so far... it's been a very long while since I posted here, just in case you wondered - I relocated myself to Thornhill ON and didn't have enough time for nothing...

Hope this helps some of you,

Thanks,

Shai Petel

Specifying the web part you need to your developers

Hi All As a part of a SharePoint solution analysis and specifications work, a system analysts has to specify various web parts that need to be developed. When specifying a web part, we should keep in mind some important features that should be clearly defined to the implementing developer:
web part properties - A web part may have a set of dynamic properties that can be configured in run-time by a site administrator. When you specify a web part's requirements you must not forget to define its dynamic behavior - all properties that you wish that a site admin will be able to configure (this actually what makes the web part dynamic).
web part connections - SharePoint (WSS/MOSS) provides a framework which enables web parts to communicate and pass values from one to another in run-time. This framework is called "web part connection framework". This framework defined a standard for any web part to send/receive values from/to other web parts. This way choosing some value for example in one web part, can filter the displayed values in another web part. When you specify a custom web part, don't forget to define the connections that this web part should support.
Standard GUI - SharePoint has a large set of defined styles. Obviously, if your new web part will be displayed inside some portal, you would like it to have the same styles as all other web part on the page. Further more, if a site administrator changes the site's theme (the overall schema of fonts/ colors etc), you will want it to apply also to your custom web part. This means that the web part should be implemented using these standard SharePoint styles and NOT some propriaty styles.

I have created a short web part specifications document to be used as a basic template for defining a custom developed web part.
Download the web part specifications document:
http://www.kwizcom.com/
Click "Specification documents for SharePoint solutions" item in the "KWizCom News" scroller.

Nimrod
http://www.kwizcom.com/

Tuesday, June 17, 2008

SharePoint & e-learning

Hi everyone
Recently i have been working on some MOSS 2007-based elearning projects, using MOSS 2007, SharePoint Learning Kit (SLK) and OCS.

The following presentation presents these technologies and provides some friendly explenations about Web content standards and SCORM:

http://www.kwizcom.com

(Click the "New SharePoint E-learning presentation" link in the news scroller)



cheers
Nimrod Geva
www.kwizcom.com

Friday, April 18, 2008

Rendering list field control manually

Recently I had many customer requesting me to do several development that all required one thing:

Render a field control manually inside my web part.



One development was creating a SharePoint list aggregator. This (upcoming new product on our site soon) web part will get data from several lists and aggregate them into one view.
What we had to support is rendering each item with all of it's fields, even custom field types.

Another development, was to create a web part (also, should be published as a new product on our site soon) that connects to a list, and allows the user to create or edit items in the list - only editing will be done one field at a time using a wizard-like mechanism, where every field you fill will save your changes and will move you to the next field (I called it ItemEditorPlus :) ).

In both cases I needed to load a list item, and display one or more of it's fields using the designated field control - in display mode, or in edit mode, it doesn't matter.

Well, I found this to be a bit tricky to do since after getting the correct field control for the current field type, I found out that each field type acts different when rendering it.

Apart from that, I found 2 methods of doing that. One using a CompositeField control (the easiest way) and the other interrogating the SPField itself.

Using the CompositeField control


This is rather easy, all you need to do is:
1. Get a reference to the SPList and SPListItemyou want to edit
2. Add a CompositeField control to your this.controls collection
3. Set the ListId, ItemId and FieldName properties of the CompositeField control
4. Done!

Here is an example of what should be in your CreateChildControls method:

FieldControlNextField = new CompositeField();
FieldControlNextField.EnableViewState = false;
FieldControlNextField.ListId = list.CurrentList.ID;
FieldControlNextField.FieldName = GetNextFieldName();
FieldControlNextField.ID = "FieldControlNextField";
if (IsEditingMode() )
{
FieldControlNextField.ControlMode = SPControlMode.Edit;
FieldControlNextField.ItemId = this.CurrentItemID;
}
else
{
FieldControlNextField.ControlMode = SPControlMode.New;
}
this.Controls.Add(FieldControlNextField);

So, that done I was able to render just about any field I testes, including our Rating field type and Tagging field type (which are very composite fields to render, I can assure you).

On the other manual method of rendering a field I will take the time to complete my investigation and publish on a later post. It is possible since I have it working, but it just seems too complicated to do so I think I am missing something...

Well, anyways - This is my first post since I moved to Ontario, Canada... Finally got my fast Internet installed at home - so if any of you emailed me and didn't get a response - I'm getting there!

Happy weekend all,
Shai Petel.

Wednesday, February 13, 2008

Register a new workflow action to wss.actions file

After creating the new action in VS using WF extentions, you will need to register it to your sharepoint server.

This is usually done by registring your action in the built in WSS.ACTIONS file.

WSS.ACTIONS file is a core file, that may be overriden in service packs or future fixes, and was not meant to be altered.

Instead, create a new file named *.actions (i.e. myActions.actions) in the same directyory as WSS.ACTIONS file, and add the following content to it:
<?xml version="1.0" encoding="utf-8"?>

<WorkflowInfo Language="en-us">
<Actions>
<Action Name="NewAction">
... definition...
</Action>
</Actions>
</WorkflowInfo>


And register your actions under tag, where you see the NewAction example.

this way you avoide editing the SharePoint core files needlessly.

Thanks, Shai.

Wednesday, January 30, 2008

Controlling the "add web part" menu

Hi, Recently I had a customer that asked me to control what web parts users can add to a web part zone.
First, I thought of setting up a “suggested web parts” group for that zone, and go to web part gallery and associate the web parts he wanted to this group.
To make your web part zone focus on a specific web part group, open the page in SharePoint Designer and set the zone's property “QuickAdd-GroupNames” to: "MyGroup"
(should turn out like: <WebPartPages:WebPartZone runat="server".... QuickAdd-GroupNames="MyGroup"..... >)
Also - to hide current site lists from the popup window, in the same manner set QuickAdd-ShowListsAndLibraries="false".
Although this makes it easier to add these web parts (not having to search the list for them) the customer insisted on have 2-3 web parts "as one click to add each".
What he meant was, to have along the "add web parts" menu something like: Add CalendarPlus Add Picture Library Viewer....
Well, I found out this can be done by some javascript manupulation.
We have to follow these steps:
1 - Get the uniqueId of the web part zone.
2 - Get the add web part popup result for adding the web part you want.
3 - Call __doPostBack(uniqueId,result);
4 - Done!
Wait... I know... the web part zone id is pretty easy to figure out... but...
How can you tell the dialog result?!?
Well, I have a trick that will allow you to create a popup with that information...
1 - Open the page in sharepoint designer
2 - Add this script block at the end of the file (before the body tag ends)
<script>
function __doPostBack2(eventTarget, eventArgument)
{
alert("zone id = "+eventTarget + "\ndialog result = " + eventArgument);
__original(eventTarget, eventArgument);
}
var __original = __doPostBack;
__doPostBack = __doPostBack2;
</script>
Now, we found out all the information we needed...
All we have left to do is to add above every web part zone a new "add WP" button using the zone's ID and the web part's id you found out earlier.

The HTML would look something like this:
<input onclick="__doPostBack(this.uniqueId,this.wpid);" type="button" value="Add Calendar" uniqueid="ctl00$PlaceHolderMain$Left$ctl00" wpid="lvwpguid:06c0b9b5%252D3a45%252D404a%252Db834%252D0677341aad5c;%25D7%259C%25D7%2595%25D7%2597%2520%25D7%25A9%25D7%25A0%25D7%2594">

Well, I was amazed it actually works, but it does!

Hope it’s not too complicated, it’s been a challenge trying to put it into words…

Sunday, January 20, 2008

Cache profile for WCM internet site

Hmmm… this took me a while to understand… but the solution is rather simple.

I wanted to activate cache profile for my customer WCM site, so that only anonymous users will see a shared cached version of the page.

Naturally – all anonymous users see the same version of the page and do not have editing rights nor can they see draft versions – so typically all you need to do is:
1: Go to site actions à site settings àsite collection administration à site collection output cache
2: Set the anonymous cache profile to “public internet (purely anonymous)
3: Click OK

And you are done.

But – I noticed there were no improvement in system-load (FE and DB servers) per requests and overall performance did not improve.

I went back to site collection output cache settings page and selected the “Enable debug cache information on pages” checkbox. Enabling this will append to the HTML a debug message stating when the current page was rendered and if cache was in use.

To my surprise (or not) I found this message:
"8 Output cache not used. Reason: User can view an unpublished version of the current page."

This meant that caching was not activated for anonymous users because they had access for unpublished version of current page? Not!

After contacting the WCM team, I got an interesting reply from Kai Lee (Thanks!) saying that this message will come up if the current user (anonymous in my case) have editing access or can view draft versions ANYWHERE IN THE SITE COLLECTION!

Well, I still have to check where anonymous users have this access in my site collection (worrying…) but there is (thank god!) a nice workaround.

Going into the “public internet” cache profile allows you to set "Allow Writers to view cached content" to “true”.

This is important to understand: for authenticated users, who can edit pages and suppose to view draft versions – this is BAD. But for my scenario – where I have no interest of allowing anonymous users to view these contents anyhow – it is a good workaround and what do you know?
It solved the problem!!!

So thanks Kai Lee again,

Hope this will save some time to the rest of you…

Thanks, Shai Petel.

Tuesday, January 8, 2008

Working with sub folders in list

Hi all,

As you all know, in 2007 SharePoint introduced a new feature to lists - creating items in sub folders. But apparently the API was not modified in an easy way to support working with this feature...

In my last project I had to create sub-folders in lists and list items in these folders from code, and found that it is not so simple.

We are doing a rating solution for SharePoint items (coming soon on our web site, for more information contact sales@kwizcom.com), and wanted to create a new "item rating" list to store all ratings for all items on the same site.
For performence issues we wanted to create a sub folder for each list in the site and a second level folder for each item and create all ratings and comments in that folder.

The outcome of that project was 3 utilities methods that manages all that I need for working with folders and I thought it would be nice to publish them here - mainly because when I googled for it I didn’t find any good posts for that.

Here is how to use the utilities methods in your project:

SPList list = GetOrCreateList(web);//create your own...
//Create subfolder named "first level"
SPListItem folder = GetOrCreateFolderInList(list, list.RootFolder, "first level");
//Create subfolder named "second level"
folder = GetOrCreateFolderInList(list, folder.Folder, "second level");
//Create item in "second level" folder
SPListItem item = AddListItemInFolder(folder);
//Update meta data of new item
item["Rating"] = 5;
item["Comments"] = "";
item["ListID"] = list.ID.ToString("N");
item["ItemID"] = "ITEM_ID";
item["UserName"] = "shai...";
item.Update();


Here is the code for the utilities:

private SPListItem AddListItemInFolder(SPListItem parentFolder)
{
return parentFolder.ListItems.Add(parentFolder.Folder.ServerRelativeUrl, SPFileSystemObjectType.File);
}
private SPListItem GetOrCreateFolderInList(SPList parentList, SPFolder parentFolder, string folderName)
{
folderName = folderName.ToLower();
string parentFolderUrl = parentFolder == null ? "":parentFolder.ServerRelativeUrl.ToLower();
//Look in existing folders
foreach (SPListItem f in parentList.Folders)
if (f.Folder.ServerRelativeUrl.ToLower() == parentFolderUrl + "/" + folderName)
return f;//Found! return it!

//not exists - create
SPListItem folder = parentList.Items.Add(parentFolderUrl, SPFileSystemObjectType.Folder, folderName);
folder.Update();
return folder;
}


Well, hope this helps you - it sure did help me :)
Shai Petel,