in

SharePoint Blogs

The Best Place for SharePoint-related Blogs

Aaron Robertson-Hodders SharePoint Blog

February 2007 - Posts

  • Custom Search Web Part

    Been a while since my last post. Mostly because we have been working very hard to complete a custom search solution.

    The requirements for the solutions were:

    - Data from Treeview controls that is entered into items must be able to be search using the Treeview control to select the search terms.

    - Where there are Choice fields in the item columns these must be rendered as multiple select choices in the search UI.

    - Values must be searchable based on a fixed set of ranges, eg. 1 million to 5 million.

    - Date columns must be searchable based on a from date/to date range.

    - Wildcards using * should be possible but no assumed.

    - People fields should be searchable based on part of the name.

    - Export results to Word and Excel documents.

    Here's a sample of the sort of thing we came up with:

    Along the way we discovered some things about MOSS searching:

    - You cannot use the OOB web part to render your results unless you pass the query as a keyword query in the URL to a results page.

    - You cannot search ranges using the Keyword Syntax.

    - You cannot use FreeText or Contains to search People fields. LIKE works fine.

    - Using FreeText and Contains makes handling wildcards and phrases very easy when building your SQL query string.

    - You can stop Lists appearing in results by adding a search scope rule to exclude items where contentclass = STS_List_GenericList.

    - The ListID for the item does not get returned in the search results. So we created an event receiver to add this to a hidden column so we could use it to build a custom export URL. If you know of a better/easier way, let me know!

    - The StartRow for the SQL Query object is zero based, not 1 as I found much to my embarassment when no results came back from my single item list!

    - The sample XSL in the SDK for rendering results is a better place to start than the XSL in the core results web part, just because it's less complex.

    - Make sure you select the data type for a Managed Property Mapping before trying to find the property to map, as the list is filtered for you on data type - bit embarassing there too, esp the second time round!

    - You can re-use the date picker control that is used in MOSS. Although we did have some problem with the rendering of the DatePicker CSS on our production server...

    The best part of the solution is that it's all based on supported technologies (and no CAML in sight!) - Web Parts, Custom Field Controls, Custom ASP.Net Web Controls, XSL for rendering, Custom Search Scopes and Custom Search Tabs and Pages. Nice!

  • Return to Custom Field properties

    A while ago I posted about Custom Field Type, wherein I mentioned a problem I was having getting my custom properties to stick when saving a field.

    I posted a question to the MSDN Forum about this and received a pretty promising response, which goes half way but is still not the complete answer.

    The response from Anton Myslevich (thanks Anton!) has details of defining the properties in the propertyschema element, making them hidden, overriding the Update method to set the custom properties like this...

            public override void Update()
            {

                this.SetCustomProperty("MyProp", this.MyProp);
                base.Update();

            }

    ...and then using an Init method that is called from the constructors to set the values when the custom field is edited...

            private void Init()
            {
                this.MyProp = this.GetCustomProperty("MyProp") + "";
            }

    This works great for the edit/save/re-edit process, but it still does not save the properties when a new instance of the field is created. For my current purposes, this is ok, because I cam deploying the custom field type as part of a list definition and so my instance is created already and because editing now works ok, I'm saved - for now.

    I'm still pretty keen to know how to get the entire process working properly, and I'm wondering if I can perhaps modify the field definition to show the propertyschema fields initially, and then hide them and show the custom field editor control when the field is edited.

    If anyone has any further thought, I'd be more than happy to hear them...

  • Adding your own Administration Pages to Site Settings or Central Administration

    You can make your custom SharePoint Applications look more like a part of the SharePoint environment by adding any Administration Tasks (ie. settings pages) that you might require into the Admin Console or Site Settings areas.

    To do this you need a Feature and a definition of the new menu item to be added and where it links to. The Feature file is pretty standard:

    <?xml version="1.0" encoding="utf-8"?>
    <Feature  Id="34251A34-3B03-4149-94A3-A04C5F99E251"
              Title="My Administration Link"
              Description="Link to administration page for my product."
              Version="12.0.0.0"
              Scope="Web"
              Hidden="FALSE"
              DefaultResourceFile="core"
              xmlns="
    http://schemas.microsoft.com/sharepoint/">
        <ElementManifests>
            <ElementManifest Location="elements.xml" />
        </ElementManifests>
    </Feature>

    The Admin Page would normally be a part of a bigger feature for your application, but in this case, it's the entire thing, so the elements.xml just contains what is required to render the link and tie it to the page I want:

    <?xml version="1.0" encoding="utf-8"?>
    <Elements
        xmlns="
    http://schemas.microsoft.com/sharepoint/">
        <CustomAction
            Id="ManageMySettings"
            GroupId="SiteCollectionAdmin"
            Location="Microsoft.SharePoint.SiteSettings"
            RequireSiteAdministrator="TRUE"
            Sequence="45"
            Title="Manage My Settings">
            <UrlAction
                Url="_layouts/MyAppSettings.aspx" />
        </CustomAction>
    </Elements>

    This elements.xml file adds a link to the Site Settings Page (by setting the Location attribute), under the Site Collection Admin area (specified by the Group ID) and requiring Site Administrator Access to get to. The UrlAction element specifies where the link goes (in this case to an aspx page in _layouts).

    I can also insert links into the Central Admin area if needed just by specifying a different CustomAction:

    <?xml version="1.0" encoding="utf-8"?>
    <Elements
        xmlns="
    http://schemas.microsoft.com/sharepoint/">
        <CustomActionGroup
            Id="Mine"
            Location="Microsoft.SharePoint.Administration.ApplicationManagement"
            Title="My Applications"
            Sequence="100" />
        <CustomAction
            Id="MyAppSettings"
            GroupId="Mine"
            Location="Microsoft.SharePoint.Administration.ApplicationManagement"
            Sequence="11"
            Title="My App Settings">
            <UrlAction
                Url="/_admin/AppSettings.aspx" />
        </CustomAction>
    </Elements>

    In this case, I specified a CustomActionGroup so that I get my own section on the Application Management Page, but I could add it to an existing one by setting the correct GroupID. Note also, that the Location is different, and points to the Central Admin Application Area. I also put the page into the _admin area as it is an admin page - I'm not 100% on whether this is best practice, so happy to hear thoughts on that.

     

     

  • Content Types - To Seal or not to Seal

    If you have been following my recent posts, you will be aware that I have been trying to skill up on Content Types, and in thinking about them, I wondered if the vision I had of them is based in reality or not.

    My initial thoughts were that I could create a Content Type, ensure that it had all the fields I really wanted to capture about a piece of Content, deploy it and let my users use the Type without breaking it, but still allow them to add additional metadata to lists as required.

    A practical example of this might be a Project Task list, where I want to be sure I capture the Client and Project Names, and obviously task columns such as due date etc, but a user I have likes to add additional columns to any Task related lists, such as a purchase order number. For them this data is required on certain jobs as they don't get paid without it, but not on others. So, I don't want purchase order to be on my base list of columns as it is only used infrequently and it's not always required.

    So my plan was to created some sort of read-only Content Type which I could deploy and users could use in their task list - I might even make it part of a solution, but where the could also add their own relevant meta-data.

    Making a Content Type read-only is not really what I want though, because making it read-only through the UI from the Advanced Settings page, doesn't really cut it. Any user who has manage list rights can go and make it read-only, and my users need manage list rights in order to add their additional columns!

    The answer is to make the Content Type Sealed! Sealing a content type is something only a Site Collection Administrator can do, and you can't do it through the UI, only via a Feature or the Object Model (acontenttype.sealed=true;). Once a Content Type is sealed, no one can make any changes to it, the columns within it no longer have urls to edit pages and you cannot un-seal it as a user with Manage List rights.

    So I created a feature with a new site column and a Content Type to test the theory.

    Here is the Column definition and save it as SampleColumn.xml:

    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">

    <Field ID="{C5054CF3-6DFB-4af1-B395-AE5590E787FF}"
               Name="SampleNote"
      DisplayName="Sample Note"                       
            Group="Sample Site Columns"      
               Type="Note" ShowInListSettings="FALSE"/>

    </Elements>

    Note that I added the ShowInListSettings="FALSE" attribute too. This is because even though no one can edit my Content Type, people can still delete or edit the column once the Content Type is added to the List just by clicking on it - so I hide it so as not to tempt them!

    Now I create a Content Type and save it as SampleContentType.xml:

    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
          <ContentType ID="0x010100EB12092854E04d8aB59FDEFF336FA6B2"               
                         Name="Sample Content Type"
                        Group="Sample Content Types"
              Description="..."
                    Version="0" Sealed="TRUE">
                <FieldRefs>                     
        <!-- Add the Sample Site Column -->     
                      <FieldRef ID="{C5054CF3-6DFB-4af1-B395-AE5590E787FF}" Name="SampleNote" Required="TRUE"/>
                </FieldRefs>           
          </ContentType>   
    </Elements>

    And, finally a Feature.xml to install my bits:

    <Feature Id="61336D8A-984B-491c-99DA-A97ED1759950"
          Title="Sample"
    Description="This feature..."
        Version="1.0.0.0"  
          Scope="Site"
          xmlns="
    http://schemas.microsoft.com/sharepoint/">
        <ElementManifests>
                  <ElementManifest Location="SampleColumn.xml" />
                  <ElementManifest Location="SampleContentType.xml" />
          </ElementManifests>    
    </Feature>

    Then I install the feature, create a list and add the content type to it. So, not I have a content type no one can break, and a field people can see in the add and edit forms, and use in views, but can't delete or change the settings of!

    Almost there, but NOT! Now if I try and add a new field to the list the magic disappearing column problem happens. Because my Content Type is sealed, even when the Add to All Content Types checkbox is checked for the new field, it does not show up in the Add and Edit forms, because it can't be added to my Content Type.

    So, either I deal with the fact that users can't add their own columns and be happy that I can force them to use only my columns (without changing them), or I don't Seal my Content Types, and don't give anyone Manage List rights and the IT department (or some lucky person) gets to do all the changes to lists that I'm worried about.


Need SharePoint Training? Attend a SharePoint Bootcamp!

Posts (c) their respective authors. Everything else (c) 2007 SharePoint Experts