Thursday, December 03, 2009

Publishing Image does not get indexed

This is a nasty one if you want to use search to get publishing content displayed somewhere.

The short version

Here’s the short version if you’re not interested in the full monty:

On an article page, you can set an image in a field of the type “Publishing Image”. If you want to display this image in the search results, you’d expect you can use the “ows_PublishingPageImage” property to map in a managed property. Well, this won’t work. Microsoft Support doesn’t call it a bug (“SharePoint cannot crawl the content of a compound control”)and suggests, as a workaround, to store the ImageUrl value in another field using an event handler and then to map this field in a managed property.

Background

The problem first showed at a customer where article pages created in one site collection should be show in another. The configuration of the farm is like the following:

clip_image002

Note: this only conceptually reflects the infrastructure.

In Site collection 1, there is a site with a pages library. In this page library, pages with the content type Article Page (standard MOSS content type and page layout) are created for news.

Article created in the page library on Site collection 1 should be shown in Site collection 2 (without content deployment). As there is a boundary between site collections, the search index is used to make content from site collection available in the other. All users have at least read rights on all site collections.

Using either the default Search Core Results web part or a third party web part, it proved impossible to show the page image and roll up image in Site collection 2. The title and page content were shown without problems.

The next section shows repro steps taken.

Repro steps

For reproducing the problem, only one site collection is required as it will show the problem as well.

In the site collection, use a page library to store the Welcome or Article pages (both can be used for this scenario).

Each page has at least the following fields filled:

  • page content --> stored in the field “Page Content” (internal name: PublishingPageContent)
  • image --> stored in the field “Page Image” (internal name: PublishingPageImage)
  • roll up image --> stored in the field “Rollup Image” (internal name: PublishingRollupImage)

The images are displayed on the page by the standard Publishing Image control in the page layout (out of the box). The images are stored in an image library in Site collection 1. For testing purposes, images of both the default created image library “/PublishingImages/” and a newly created image library called “Pictures” (/Pictures) were used.

Below is a screenshot of the page properties of the page used for testing:

clip_image004

The page used for testing was published as a major version.

After that, the index was run with an incremental crawl. When searching for the word “welcome”, the Search Center displays the results correctly:

clip_image006

What I want to achieve now, is to show the Page Image (field: PublishingPageImage) instead of the icon. At my customer, I’m using a third party web part to display the articles, but the concept can be shown by using only standard functionality.

To make this possible, a few steps need to be followed:

  1. create a managed property mapping to the page field
  2. run a full crawl on the index
  3. change the Core Results web part settings to include the new managed property as a column
  4. change the XSLT for the search result to render an image using the new column

Step 1

In the SSP, I created a managed property called PublishingPageImage. This property maps to the indexed field ows_PublishingPageImage:

clip_image008

Note: the name of the managed property should match the mapped property as closely as possible to avoid problems.

Step 2

To make this managed property usable, a full crawl should be done. After the full crawl, you can already see the problem:

clip_image010

There are no items found using this property. However, as you can see in the page properties (first screen shot under Repro steps), the field does have a value!

Conclusion: the field ows_PublishingPageImage is not indexed properly!

Step 3

Steps 3 and 4 are actually obsolete as step 2 already shows us no content will be returned. However, to get the picture, I’ll show them anyway.

In the site collection Search Center, go to edit mode and go to the properties of the web part Search Core Results. Under Results Query Options, Selected Columns, open the columns editor and add

<Column Name="PublishingPageImage"/>

clip_image012

This will ensure our new managed property can actually be used in the search results. Click OK to close the editor dialog.

Step 4

In the web part property pane, click the XSL Editor button. In the editor, search for

<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>




This text displays the default icon clip_image014.



What I want to achieve is that the publishing page image is shown, when available. To do so, replace the xsl text above with something like the following:





<xsl:if test=” publishingpageimage != ‘’”>


 <img>


  <xsl:attribute name=”src> 


   <xsl:value-of select="publishingpageimage"/>


  </xsl:attribute>


 </img>


</xsl:if>


 


<xsl:if test=” publishingpageimage = ‘’”>


 <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>


</xsl:if>




Note: as step 2 already makes sure we don’t get any results, it’s not sure if the creating an <img> is necessary. If the field stores complete html , the following would be OK:





<xsl:if test=” publishingpageimage != ‘’”>


 <xsl:value-of select="publishingpageimage"/>


</xsl:if>


 


<xsl:if test=” publishingpageimage = ‘’”>


 <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>


</xsl:if>




Click OK, and Apply. Click OK on the web part tool pane to close it.



The expected result would be that the image of the page is shown in the results



Other information



Please note that the images themselves (as library items) can be found with the search. The problem is the page field, creating the link between the page and the image. It looks like this field is not indexed properly, making it impossible to show images related to an article via Search.



Please note that if we use an out of the box picture field (not the publishing image), the contents are stored and indexed. However, this is not the behavior we want as we want to use the publishing features, not the WSS types.



Solution from Microsoft



For this problem, I opened a support case that ran for ages. After almost a year (!) mailing back and forth, I got the following solution:



Dear Sjoert,



As agreed your existing support case SRQ[…] will now be archived. Customer Satisfaction is very important to us and we would like to be sure that you are very satisfied with the service you have received.



If I can be of any further assistance on this case or if you have any suggestions for improving our service please do not hesitate to contact myself or my manager […] so we can ensure you receive our immediate attention.



Here is a summary of your case:



[ARCR]



ACTION:



You want to customize Search results Page, so that found pages are listed with an Image which is stored in the Web Part "Page Image".



You mapped the ows_PublishingPageImage with the internal name "PublishingPageImage" of the web part "Page image".



You also customized the web part "Search Core Results", so that the query returns also the mapped property "ows_PublishingPageImage" and modified the XSLT of this web part, so that it should additionally display the "PublishingpageImage"  as a picture left of the url of the page.



RESULT:



The Image in the "Page Image"  of the found page is not displayed in the Search Core results web part.



CAUSE:



The mapped property "ows_PublishingPageImage" is not crawled in that way, that we can use it as an image blob. SharePoint cannot crawl the content of a compound control.



RESOLUTION:



Workaround: You need to add the url to the image to the Pages Library List. We used the column "comment" for that purpose. We provided an EventHandler which receives and handles the events "ItemUpdating" and "ItemAdding" events(executed if you change or add a picture to the picture library).



public override void ItemUpdated(SPItemEventProperties properties)



        {



            SPListItem item = properties.ListItem;



            string imageUrl = ((Microsoft.SharePoint.Publishing.Fields.ImageFieldValue)(item["PublishingPageImage"])).ImageUrl;



            item["Comments"] = imageUrl;



            item.Update();



        }



Use this picture library for adding picture to the web parts "Page Image" or "Rollup Image".



Run a full crawl. Map the meta property ows_Comment to the column "Comment". Run a crawl again. Used this property name in the Search results Core Web Part in the query options and modify the XSLT.



Conclusion



I still think this is a bug: SharePoint cannot crawl the content of a compound control. However, there’s a workaround. I suggest not to use the Comments field as suggested by Microsoft but a dedicated field instead.

Thursday, November 19, 2009

Installing SharePoint Foundation 2010

I’ve been insatlling SharePoint Foundation 2010 beta today and although some blogs are already out there with good support on installation, I thought it might be handy to provide some visuals. Might be helpfull if you’re about to install or just want to know what it looks like without installing it yourself.

Development machine

I’m running VMWare Workstation on a Lenovo T61p with 4GB of Ram. Windows Server 2008 R2 is my OS on the VM and I had all prerequisites installed, including SQL Server, before making a linked clone on which I’m now installing SharePoint Foundation. Using a linked clone is a good thing: if the installation fails, you have a base VM to start over again.

Starting the installation

When you run the executable, the SharePoint Foundation installation window opens, offering a few options:

image

If your machine does not have all prerequisites installed, be sure to start with the option “Install software prerequisites”. Might also be a good idea to check Ji Lie’s blog post for some inportant hotfixes. Please note that the WCF fix he mentions for R2 is not available yet. However, things seem to install fine on my R2 machine!

Install software prerequisites

I was pretty sure I installed the lot, but you never know. So I started the installation of the prerequisites, which takes you into a wizard that tells you what is going to be done. Nice!

image

Next step is to accept the license agreement. Did I actually read it?

image

Select and click Next, which starts the various checks and installations. This will take a few minutes, depending on how well you prepared your machine. When it’s done, you get to the “Installation Complete” screen. Why do Americans start every word with a capital? Are they German?

image

Click Finish to return to the main setup screen. Now click “Install SharePoint Foundation”.

Installing Foundation

The installation wizard will first take you to the license terms:

image

Select and click Continue. You get to a screen with an important choice to make:

image

I strongly recommend you choose Server Farm. Standalone will use SQL Express, which has limited functionality. After clicking “Server Farm”, you’re faced with basically the same choice:

image

Select “Complete” and click the tab “Data location”. Here you can set the location of the index files. I recommend you choose a location not on the C drive:

image

Click “Install Now” to start the actual installation:

image

When all is fine, you get to the last screen of the installation wizard. Check the checkbox and click “Close” to start the configuration wizard:

image

Running the configuration wizard

The wizard starts with a welcom. Click “Next” to continue:

image

The wizard asks you if some services might have to be started or reset. Click “Yes”:

image

You are now asked if you want to connect to an existing farm or create a new one. I presume this is the first time you create one with SharePoint Foundation, so select “Create a new server farm”:

image

You are now asked to fill in some details for the database settings:

image

The next thing to fill in, is a passphrase for new servers to join the farm:

image

Make sure the passphrase is secure enough (using capitals, numbers and special characters). If your passphrase is not secure, you’ll get an error message:

image

The next screen asks you some settings for the Central Admin, like port number and authentication provider (NTLM or Kerberos):

image

Click “Next” to get to the summary page:

image

If you click the “Advanced Settings” button, you are taken to a screen to enable AD account creation mode:

image

Back in the summary screen, click “Next” to start the actual configuration. This might take some time:

image

When all goes well, you’re taken to the last screen in the wizard:

image

Click “Finish” to close the wizard and to be taken to the Central Admin page.

Central administration

When going to the Central Admin for the first time, the first question you’re asked is if you want to participate in the customer experience improvement program:

image

Of course you want to, to make a great product even better!. Click “OK” to move on. You’re now asked if you want to configure everything yourself or via a wizard:

image

If you have loads and loads of free RAM, choose the wizard. If you’re running this in a VM on a laptop with 4GB with Vista as host, don’t! I’m getting the error message “There is insufficient system memory in resource pool 'internal'” after a few minutes. Luckily, there’s a link to go back to Central Admin and nothing seems to be broken. Giving my VM more memory to try this again (the link to the wizard is available in the left menu) only means my Vista is getting slower, beyond the point of dying alltogether…

So, the final step is to configure the lot yourself, but that’s out of scope for this blog. Happy installing, happy buying more RAM!

Sunday, November 15, 2009

Playing around with custom fields, part 2

In my previous post on this topic, I described some of the architectural choices on creating my custom field. That post was, more or less, non technical. This posting will be more code oriented.

In this second post, I’m taking you with me on my journey and the challenges underway. The third and final post will be about how I fixed it in the end.

As said before, I’ve not created a full working solution; that was not my intention and I just don’t have enough hours in a day to create one (and my wife will kill me if I try…). However, the bits below helped me gaining more insight, which was the purpose of this exercise in the first place.

The goal

Just as a reminder of what I’m trying to achieve, here’s a brief mission statement:

  • create a custom field that stores rating settings and displays the average rating with stars(1 to 5) in both display mode as well as list views. Store rating history and possibly user comments as well.
    image

The result

This article is about the process of getting somewhere, namely a custom field with some specific rendering. Along the way, I’ve tried many things that didn’t do the trick so keep on reading for the lot. If you just want to hear about the result, here it is:

  • create a custom field that inherits from SPFieldNumber
  • when creating the field, in the OnAdded event create a related computed field automatically and use a specific naming convention to keep a link with the custom field
  • the related computed field will not store any data but is only there for rendering purposes
  • hide the custom field from the view and show the computed one
  • write some code to update the custom field data (not implemented)

Read on if you’re interested in the background information.

Creating the field type

You need to create a fldtypes*.xml file to store information on your custom field. In my case, the field is of the type “Number”. The file fldtypes_rating.xml goes into 12\TEMPLATE\XML:

<?xml version="1.0" encoding="utf-8" ?>


<FieldTypes>


  <FieldType>


    <Field Name="TypeName">RatingField</Field>


    <Field Name="ParentType">Number</Field>


    <Field Name="TypeDisplayName">Rating</Field>


    <Field Name="TypeShortDescription">Rating field</Field>


    <Field Name="UserCreatable">TRUE</Field>


    <Field Name="Sortable">TRUE</Field>


    <Field Name="AllowBaseTypeRendering">TRUE</Field>


    <Field Name="Filterable">TRUE</Field>


    <Field Name="FieldTypeClass">Eog.SharePoint2007.Fields.RatingField, Eog.SharePoint2007.Fields, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[mytoken]</Field>


  </FieldType>


</FieldTypes>




So far so good, this is quite easy.



Field class



It’s not only XML, it’s code as well. If your field is just an override of a standard one (but why would you do that), the code is fairly easy:





using System;


using System.Collections.Generic;


using System.Linq;


using System.Text;


using Microsoft.SharePoint;


using System.Xml;


 


namespace Eog.SharePoint2007.Fields


{


  class RatingField : SPFieldNumber


  {


    private SPFieldCollection _fields;


 


    public RatingField(SPFieldCollection fields, string fieldName)


      : base(fields, fieldName)


    {


      this._fields = null;


      this._fields = fields;


      this.DisplayFormat = SPNumberFormatTypes.NoDecimal;


    }


 


    public RatingField(SPFieldCollection fields, string fieldName, string displayName)


      : base(fields, fieldName, displayName)


    {


      this._fields = null;


      this._fields = fields;


      this.DisplayFormat = SPNumberFormatTypes.NoDecimal;


    }


  }


}




Make sure to add a reference to Microsoft.SharePoint as otherwise Visual Studio won’t know what SPFieldNumber is. I’ve left out a lot of stuff in the above example but we’ll get to that later. If you want to know why there are two constructors, I strongly advise you to read the USP Journal on SPTags by Bjørn Furuknap! There’s a ton of complex stuff related to custom fields and that’s very well explained in the journal. Another good source is the great article by Wouter van Vugt on MSDN: http://msdn.microsoft.com/en-us/library/cc889345.aspx.



Strongly name your assembly, add it to the GAC and do an IISReset. That’s all there is to it for creating a simple but useless custom field. The usefull stuff is still to come.



Field control



To display a field in a custom manner, a field control would seem like a logical option. Basically, create a field that inherits from one of the base types. In the constructor, specify the field type it is related to:





public RatingFieldControl(RatingField parentField)


{


  this.field = parentField;


}




In the field class, override the FieldRenderingControl method to hook up the field to the control:





public override BaseFieldControl FieldRenderingControl


{


 get


 {


  BaseFieldControl fieldControl = new RatingFieldControl(this);


  fieldControl.FieldName = InternalName;


  return fieldControl;


 }


}




To render UI, either do this in code (CreateChildControls) or with a control template. If you think “hold your horses, you’re skipping all the details”, you’re absolutely right. Why? A: there’s plenty of documentation on the web via your favourite search engine. B: this approach doesn’t work for what I want!



The rendering control works fine in display and edit mode, but not in list views! List views do not load your rendering controls and only display the contents of field as it is stored. And you know what: even your Field class is not called in the list view! I’ve set a dozen break points, but none of them fires when loading the list view.



But it looks like there’s another way…



Renderpattern



The RenderPattern is a piece of CAML in your field definition (fldtypes*.xml) that provides an alternative way of rendering your field’s data. Please refer to http://msdn.microsoft.com/en-us/library/aa544291.aspx for a full reference. You use the Name attribute to set DisplayPattern, which is the pattern used in the list view. Here’s an example:





<RenderPattern Name="DisplayPattern">


 <Switch>


  <Expr><Column/></Expr>


  <Case Value=""></Case>


  <Default>


   <Column />


  </Default>


 </Switch>


</RenderPattern>




In this example, an expression is used to check if the column contains data. If not, it doesn’t do anything. If it does, it displays whatever specified between the <default> tags. In this case, it only renders the column value. Quite useless because not specifying this pattern will do the same, but this example is to show you the potential.



For my solution, this could work with an expression:





<RenderPattern Name="DisplayPattern">


 <Switch>


  <Expr><Column/></Expr>


  <Case Value="">


   <HTML><![CDATA[<img src="_layouts/images/rating/rating0.gif" />]]></HTML>


  </Case>


  <Case Value="1">


   <HTML><![CDATA[<img src="_layouts/images/rating/rating1.gif" />]]></HTML>


  </Case>


  <Case Value="2">


   <HTML><![CDATA[<img src="_layouts/images/rating/rating2.gif" />]]></HTML>


  </Case>


  <Default>


   <HTML><![CDATA[<img src="_layouts/images/rating/rating0.gif" />]]></HTML>


  </Default>


 </Switch>


</RenderPattern>




But here’s the catch: I planned to store much more than I want to show in the list view and there’s no way to filter that out with CAML. The idea was to store the rating history as well, so having the Column element in my markup would show the history as well whereas I only want to show the average. I also can’t use the column value in an expression like the one above. There’s just no way to perform advanced data manipulation before it reaches the RenderPattern.



This is becoming a challenge:




  • the field type does not do rendering everywher (and is not even called in the list view)


  • the field control is of no use in the list view as it’s not used there


  • the RenderPattern is not suitable for transforming my data



Trying to work around the CAML constraints



My eye felt on an attribute of the Column element: ShowField. This attribute allows you to show the contents of another field. Aha: so what if have not one but two fields; one for storing the history and one for showing the current rating?



Looks like an interesting solution, but there’s a caveat: how do I know what the related field is? If the user creates a column based on my field, it is given a name that I don’t know in advance so I can’t guess the related field name to specify in the CAML.



Related field



So what about that Column attribute hidden in the SDK: UseRelatedField? This field gets the value of a related field (quite obvious!). RelatedField is a property of SPField, giving me the opportunity to create another field via code (and thus giving me control over its name) and then connecting it to my rating field:




  • somehow create another field when my custom field is instantiated


  • relate the two by <MyCustomField>.RelatedField = <MyCustomRelatedField>


  • Render the value using CAML



In the RenderPattern, the related value would be retrieved like the following:





<RenderPattern Name="DisplayPattern">


 <Switch>


  <Expr><Column UseRelatedField="TRUE"/></Expr>


  <Case Value="">


   <HTML><![CDATA[<img src="_layouts/images/rating/rating0.gif" />]]></HTML>


  </Case>


  <Case Value="1">


   <HTML><![CDATA[<img src="_layouts/images/rating/rating1.gif" />]]></HTML>


  </Case>


  <Case Value="2">


   <HTML><![CDATA[<img src="_layouts/images/rating/rating2.gif" />]]></HTML>


  </Case>


  <Default>


   <HTML><![CDATA[<img src="_layouts/images/rating/rating0.gif" />]]></HTML>


  </Default>


 </Switch>


</RenderPattern>




Now we’re getting somehere. There are still many questions to answer:




  • how do I make sure the user cannot edit the related field’s value directly?


  • what is the best way to render my field?


  • how do I show the correct field in the list view?



Where are we now?



In this post, I’ve gone into some of the basics of creating a custom field as well as some of the challenges I faced with the solution I have in mind. The third and final posting will contain the final bits so stay tuned!

Thursday, November 05, 2009

SharePoint 2010 BLOB storage

One of the disadvantages of using a database to store large files is performance; databases commonly just aren’t designed for large files.

If you use SQL Server 2008, however, you have the option to store blobs using FILESTREAM (see http://www.microsoft.com/sqlserver/2008/en/us/wp-sql-2008-manage-unstructured.aspx or http://blogs.msdn.com/sqlrbs/).

With SharePoint 2007, you have to write your own APIs and libraries to achieve External BLOB Storage (EBS). We’ve done some implementations for customers, but it always turned out to be a hassle.

One of the key features that is promoted for SharePoint 2010, is the ability to have data storage outside the SharePoint DB build in using Remote BLOB Storage (RBS). So no need to create custom APIs and libraries anymore! Found some more details on http://sharepointsolutions.com/sharepoint-help/blog/index.php/2009/10/externalizing-blob-storage-in-sharepoint-2010/.

You can write your own providers to hook into RBS although I can’t think of any now. Perhaps write BLOBs to a Distributed File System?

Friday, October 23, 2009

SharePoint 2010 reference on MSDN

Wish I’d been in Vegas at the SPC, but luckiliy, a lot of information on SharePoint 2010 is now becoming available. One good starting point is MSDN: http://msdn.microsoft.com/en-us/library/dd776256.aspx.

Happy reading!

Thursday, October 22, 2009

Error when creating a SharePoint database with PSCONFIG

At a customer, we’re building a dev environment where each developer has his own VM, running Windows Server 2008 (64 bit) with a domain controller (each dev machine is its own domain) , SQL Server 2005 Development edition and MOSS 2007 SP2.

We’re using scripts to automate as much of the setup as possible but run into a problem with PSConfig when creating a MOSS database. This is the command we’re running:

psconfig -cmd configdb -create -server %SQLSRV% -database %DBNameConfig% -user %ServerFarmAdminAccount% -password %ServerFarmAdminAccount_Password% -admincontentdatabase %DBNameAdminContent%

When running the script, we receive the following error:

A connection was successfully established with the server, but then an error occurred during the login process. (provider: TCP Provider, error: 0 - The specified network name is no longer available.)

In the Event Log, an event is created with ID 5586.

First, we’ve checked and double checked all variables:

  • user and password are OK
  • users are members of the appropriate domain groups
  • users are known in SQL and have been assigned appriopriated rights
  • script is run with admin priveleges
  • db server exsists (the database itself is created, psconfig fails on configuring it. See below for more info.)

Looking in more details at the event log, an SQL server error preceeds the SharePoint one:

EVENTID 17810: Could not connect because the maximum number of '1' dedicated administrator connections already exists. Before a new connection can be made, the existing dedicated administrator connection must be dropped, either by logging off or ending the process. [CLIENT: ::1]

As said above, the database is created but psconfig hangs on configuring it. The same script works fine in our test environment! The difference is that we’re using multiple machines and SQL Enterprise in the test farm.

We do not have any other connection to the database open when running the script so it looks like something inside psconfig.

Google doesn’t provide much help on this and none of my collegues has seen this before so if anyone knwos the key, please don’t hesitate to post a reply!

Tuesday, September 22, 2009

Playing around with custom fields

It had been some time since I used Visual Studio so I thought it was time to play around a bit.  I wanted to do something that might be of use in a customer-based scenario but not something necessarily production ready, more stuff to gain more in-depth knowledge.

This is the first of a two articles I’m going to write about this topic. In this first one, I’m focussing on the solution I have in mind and the architecture. Please mind that due to time constraints, I didn’t write a complete solution. However, that was never my goal but I found some things on my path to share with you.

The second article will be about some more technical details.

the scenario

I was triggered by a customer request for a feature to allow feedback or rating on articles written by their experts. The requirement is that on an article page, a reader can give a rating or post a comment.

I know, I know: there are solutions readily available and for a customer I would definately look at these first, but remember I’m doing this for fun…

Some existing solutions:

To keep it simple, I decided to go for a rating solution only. The basics for that solution would definately provide enough input for later enhancements.

architectural decissions

The first solution I thought of was a pretty easy one:

  • create a hidden list to serve as a container for the rating. This list will have the appropriate columns to store my values (user, datetime, rating etc)
  • create a control/web part that interacts with this list: add new ratings and retrieve existing ones. The control would use metadata values of the containing page (ID and so).
  • add the control/web part to the publishing page

Using a control would give me more flexibility to add it to a page layout and show it on article pages already created and as I didn’t need configuration, a control would be the right choice.

concept1

 

This solution would work for all cases where the content is an article page, but not for regular list items as list items do not allow a web part to be added. List items only display their fields.

Although having rating enabled on anything other than articles was not a requirement per se, I felt my solution had too many limitations. Back to the drawing board!

When the requirement is to allow rating on any type of list item, a custom field is your best choice.

image

The advantages of the custom field are:

  • it is available on the New, Display and Edit forms
  • its value can be displayed on the List form
  • it can be added to any item
  • it can also be added to a page
  • its value can be picked up by a web part on a publishing page

So what type of field do I need? Obviously, this depends on what I needed to store. I thought of two options:

  1. store a whole lot of information with the feedback and rating, in a structured way to make sure I can apply filtering or perform calculations.
  2. keep it simple and only store only the total rating.

Due to time constraints, I ended up with option 2, although option 1 was what I started with. Custom fields can be notoriously difficult to develop, but some excellent guidance is available. More on that in the second article, following soon.