Tom Clarkson

SharePoint, Startups and some other stuff

Default Values for Lookups with a Custom Field Type

with 10 comments

The requirement:
The metadata attached to an uploaded document is fairly complex, and users should not need to specify values manually. Instead the values should be set based on where the user clicked to upload the document.
 
The solution:
A custom field type is created that extends the out of box lookup field and reads values from the query string. Standard query string parameters will work well for adding list items, but not for uploads as the upload page will not pass values through to the edit form. For uploads we can add the same properties to the Source query string parameter, which is used to redirect after the item is saved. To do this properly you would need a custom script to set the source parameter, but it is easily tested by adding the parameters to the address bar before clicking the upload button on a standard list page.
 
To create a custom field type, you need at least two files on top of the standard solution package structure – an xml file with a name like fldtypes_LookupDefaultFromQuery.xml in 12\TEMPLATE\XML and a class that extends SPField.
 
The class itself is fairly simple – just extend SPFieldLookup to override SPFieldLookup. Only default value needs to be changed - we can use the existing edit controls for both the value and the field properties. The value to use will be the id of the item to select in the lookup. 

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace LookupFieldTypes
{
    public class LookupDefaultFromQuery : SPFieldLookup
    {

        public LookupDefaultFromQuery(		SPFieldCollection fields, 		string fieldName)
            : base(fields, fieldName)
        {
        }

        public LookupDefaultFromQuery(		SPFieldCollection fields, 		string typeName, 		string displayName)
            : base(fields, typeName, displayName)
        {
        }

        public override string DefaultValue
        {
            get
            {
                try
                {
                    System.Collections.Specialized.NameValueCollection qs = 			System.Web.HttpContext.Current.Request.QueryString;

                    // First look for the value in the page query string
                    string dv = qs["Selected" + this.InternalName];
                    if (!string.IsNullOrEmpty(dv))
                    {
                        return dv;
                    }

                    // if the value wasn't found, try the source url                   
                    string source = qs["Source"];

                    Uri uri = new Uri(source);
                    return System.Web.HttpUtility.ParseQueryString(uri.Query)			["Selected" + this.InternalName];
                }
                catch (Exception ex)
                {
                    return base.DefaultValue;
                }

            }
            set
            {
                base.DefaultValue = value;
            }
        }

    }

}
The xml file is a little harder to get right, since there is no useful documentation available and copying any of the out of box fieldtype declarations from fldtypes.xml doesn’t work. Bits that seem to be particularly important:
  • FieldTypeClass needs to point to the custom class above. Even if that class doesn’t override anything from the base class, specifying SPFieldLookup as the out of box lookup field does will not work. It even stops the standard lookup field from working properly.
  • FieldEditorUserControl is the control that appears when creating a new field. The out of box control can be used, although there are issues around switching to multiple selection that aren’t handled by this code.
  • SQLType needs to be int to store the id. Various things break if it isn’t specified.
  • InternalType is what allows the LookupColumn and URL cmd=”Lookup” elements in the renderpatterns to work properly.
  • RenderPattern elements are copied from the Lookup field type in fldtypes.xml and are excluded from this post because they are really long and complex. You can make changes to them if you want, but the only documentation I have seen is the view schema at http://msdn2.microsoft.com/en-us/library/ms439798.aspx, which is only slightly helpful.
 
<?xml version=“1.0″ encoding=“utf-8″ ?>
<FieldTypes>
  <FieldType>
    <Field Name=TypeName>LookupDefaultFromQuery</Field>
    <Field Name=TypeDisplayName>LookupDefaultFromQuery</Field>
    <Field Name=TypeShortDescription>Lookup with default value from query string</Field>
    <Field Name=UserCreatable>TRUE</Field>
    <Field Name=FieldTypeClass>LookupFieldTypes.LookupDefaultFromQuery, LookupFieldTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5296a18ab0247d05</Field>
    <Field Name=FieldEditorUserControl>/_controltemplates/LookupFieldEditor.ascx</Field>
    <Field Name=SQLType>int</Field>
    <Field Name=InternalType>Lookup</Field>
    <Field Name=Sortable>TRUE</Field>
    <Field Name=Filterable>TRUE</Field>

    <RenderPattern Name=HeaderPattern>

    </RenderPattern>
 
  </FieldType>
</FieldTypes>
 
 

Advertisement

Written by Tom Clarkson

December 7, 2007 at 9:53 pm

Posted in SharePoint

10 Responses

Subscribe to comments with RSS.

  1. Good idea! Thank you!

    Nguyen Van Minh

    September 16, 2008 at 8:32 pm

  2. Thanks for your excellent article, but does it break the rules? Here’s what Microsoft says: http://msdn.microsoft.com/en-us/library/aa544201.aspx

    ParentType:
    . It must never be empty in your custom field types. All custom types inherit from another type.

    InternalType:
    Optional String. Represents an internal base type. Do not use a element in your custom field type definitions.

    SQLType:
    Optional String. Represents the SQL data type that will be used to store the data in the content database. Do not use a element in your custom field type definitions.

    spmikey

    September 21, 2008 at 3:53 am

  3. I wouldn’t worry too much about those rules. They aren’t in the list of things that make your environment unsupported, so I read them as “don’t use this unless you know what you are doing”. This sort of customisation is often closer to developing internal SharePoint code than anything else.

    Besides, it doesn’t work without using those “internal use only” properties – Most of the functionality relies on reusing stuff from the standard lookup field, and I remember looking around in reflector and finding that in several places it is hardcoded to check if InternalType is “Lookup”.

    Tom Clarkson

    September 21, 2008 at 5:34 am

  4. I’m wondering how I could filter by a parameter in the query string.

    For Example:

    Column To Filter Lookup On: ProductID
    Type of Operator: Equal To
    Value to Filter Lookup On: – from http://sharepointsite/products.aspx?ProductID=101

    Is this what you are doing here? I am fairly new and trying to understand how to duplicate what you are doing.

    Thanks in advance.

    Mike

    October 31, 2008 at 5:43 pm

  5. This code is setting the default value rather than the available values, but you can use a similar approach for filtering – you could override the rendering of the dropdown so only valid values are included.

    If you’re just thinking list filtering, the query string parameters FilterField1/FilterValue1 may be useful.

    Tom Clarkson

    October 31, 2008 at 10:16 pm

  6. I was thinking along the lines of filtering the available values to only one value that I pass in the querystring. I would think that you would need to apply it to the CAML query of the lookup somehow, just not exactly sure how to do it :)

    Mike

    November 1, 2008 at 10:45 am

  7. I was thinking along the lines of filtering the available values to only one value that I pass in the querystring. I would think that you would need to apply it to the CAML query of the lookup somehow, just not exactly sure how to do it :)

    Mike

    November 1, 2008 at 2:50 pm

  8. I don’t think the query used to populate the lookups is exposed – I think the closest you will get is getting access to the dropdown control after it is generated and filter that using whatever filter you need.

    Tom Clarkson

    November 3, 2008 at 5:57 pm

  9. I’ve been creating my own Custom Field based on SPFieldLook, everything is working great, except i cannot use this new Field in SharePoint Designer, it’s recognised as a “String” not “List Item ID”. Can anybody help?

    Ian Cooper

    November 19, 2008 at 8:18 am

  10. Hi Tom,
    Sharepoint lookup field mapping to a remote lookup list

    Doing research and experimenting with a lookup field I’ve found that a lookup field (a site column which gets their data from a list) and a lookup list (from which a lookup field gets their data) must belong to the same site (or different sites if sites are a parent and child) within a site collection. There are also the cross-sites lookup field solutions where a lookup field and a lookup list might belong to different sites but again within the same website/site collection. All these known implementations do not allow separate a lookup field and a lookup list meaning to have them on different web applications and working together.
    Is this correct or am I missing something?

    There might be another scenario where a lookup field should be deployed on a few hundred client’s sites and these clients’ lookup fields must get their data from a remote lookup list being resided on separate admin web application. In this case remote lookup list might be maintained at one central place (admin web app) and feeds updated data for all clients’ lookup fields. The point here is to avoid creation of hundreds instances of a remote lookup list on the clients’ sites. Client sites’ lookup fields should map directly to a remote lookup list being resided on separate admin web application.
    Any idea, advise, discussion or references about a lookup field mapping to a remote lookup list implementation using CAML/C#/webservices will be appreciated.

    Thanks.
    Vadim.

    Vadim Dzyuban

    April 16, 2009 at 11:47 am


Leave a Reply

Fill in your details below or click an icon to log in:

Gravatar
WordPress.com Logo

Please log in to WordPress.com to post a comment to your blog.

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.