Products

Solutions

Resources

Partners

Community

About

New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.


Custom Search Results Module

Overview

I recently had a customer who wanted to display the search results using a custom format.  At first glance, I thought I might need to use a custom Search Input module along with a customized Search Results module.  With a little slight of hand, and some quick thinking, I was able to perform the task by copying two ascx files, creating a new .dnn file and uploading the new "module" to the website.

Because the format required used the standard "fields" already available on the core Search Results module, I figured I could just create a new "skin" page for the Search Results module and everything should just work.  Now you might be asking yourself how do you "skin" a module.  The answer is the same as how you "skin" a DotNetNuke site.  You create an ascx page that inherits from the common base class and then "register" that new ascx page as a module/module control.  You will now have a new module with the same behavior as the original, but with a different appearance.

Create the "Skin"

To create my skin, I just copied the standard Search Results module ascx and gave it a new name.  Since it is just a skin, I removed the codebehind attribute from the Control directive at the top of the file (see figure 1).

SearchResults.gif
Figure 1: SearchResults.ascx

Notice that I have also removed several tags from the second TemplateColumn/ItemTemplate.  This is the new layout that the client requested.  Because I am not adding any additional fields and I verified in the original codebehind that DotNetNuke does not directly reference any of the server controls in that template, then I should be done with editing this file.

Now that we have the search page complete, we can move on to the settings page.  This is a simple copy operation.  I chose not to change this screen because every control is referenced from the codebehind.  Since I do not want to rewrite the codebehind, I just left things as they were.  Again, I removed the CodeBehind attribute, but left the Inherits attribute (see Figure 2).

settings.gif
Figure 2: Settings.ascx

Package the Module

Now that we have our two user control "skins" complete, we are ready to package up our new module.  To do this we create a simple DNN module manifest file.

<dotnetnuke version="3.0" type="Module">
  <folders>
    <folder>
      <name>IP SearchResults</name>
      <friendlyname>IP Search Results</friendlyname>
      <foldername>IP SearchResults</foldername>
      <modulename>IP SearchResults</modulename>
      <description>This is a custom skin for the search results.
      </description>
      <version>01.00.00</version>
      <businesscontrollerclass>
      </businesscontrollerclass>
      <modules>
        <module>
          <friendlyname>IP Search Results</friendlyname>
          <cachetime>0</cachetime>
          <controls>
            <control>
              <src>searchresults.ascx</src>
              <type>Anonymous</type>
            </control>
            <control>
              <key>Settings</key>
              <title>Search Results Settings</title>
              <src>settings.ascx</src>
              <type>Edit</type>
            </control>
          </controls>
        </module>
      </modules>
      <files>
        <file>
          <name>searchresults.ascx</name>
        </file>
        <file>
          <name>settings.ascx</name>
        </file>
      </files>
    </folder>
  </folders>
</dotnetnuke>

One item to note in the manifest:  I have set the Key for the settings.ascx to the value "Settings".  The "Settings" value has magical qualities and as a result our settings screen will appear on the standard module settings screen as another settings block.  Without this value we would have no way to access our settings screen because the original code did not support a custom edit screen beyond this "special" version.

Now that our module manifest is complete, just add the three files to a zip file and you are done creating your custom SearchResults skin.  Upload it to your site and you are ready to go. 

To keep my work to a minimum, I decided to hijack the existing search results page.  It was already created and would be a great place for my new search module.  I fired up the website and entered a search term in my SearchInput text box, then hit return.  This took me to the hidden search results page.  I figure that this is much faster than going to the Admin/Pages screen and then finding the search results page and then selecting the view button.  This shortcut takes one step and can be done from any page on the site where the search box is located.  Being logged on as Admin, I was then able to delete the old search results module and add in my new module.

Houston we have a problem

It seems that the original Search Input skin-object for DotNetNuke uses a little trick to find out where to redirect the user to view the search results.  The skinobject gets the tabid of the tab on which the first "Search Results" module is located using the following code snippet:

Dim objModules As New Entities.Modules.ModuleController
Dim searchTabId As Integer = objModules.GetModuleByDefinition(PortalSettings.PortalId, "Search Results").TabID

This means that my custom search results module, whose module definition name is "IP SearchResults" will not be found and will result in an "Object reference not found" error on the page where we enter the search terms.  I figured that my clients web visitors would not find these "results" to be of much use so I needed to find a way to make things work.

Well, if the code is just looking for the tabid of the "Search Results" module, then why couldn't we just move the original search results module back to the Search Results page.  I went to the recycle bin and restored the module back to its rightful place.  But now I had two modules on this page which would display the results.  Clearly this is not what the customer wanted.  By making the original search results module viewable only by administrators, adding a header to the module from the module settings screen which explained the purpose of the extra module, and limiting the result set to 1 entry, I was able to minimize the performance impact and hide the "hack" from general site visitors.

All-in-all, not a bad hack for 30 minutes of work.  I now had a custom search results "module" for my customer, and I didn't have to write one single line of code to make it work.

You can download the code from my website:  TAG Software.

Comments

Comment Form

Only registered users may post comments.

NewsArchives


Aderson Oliveira (22)
Alec Whittington (11)
Alessandra Daniels (3)
Alex Shirley (10)
Andrew Hoefling (3)
Andrew Nurse (30)
Andy Tryba (1)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (37)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Bogdan Litescu (1)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (213)
Chris Paterra (55)
Clint Patterson (108)
Cuong Dang (21)
Daniel Bartholomew (2)
Daniel Mettler (181)
Daniel Valadas (48)
Dave Buckner (2)
David Poindexter (12)
David Rodriguez (3)
Dennis Shiao (1)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (80)
Francisco Perez Andres (17)
Geoff Barlow (12)
George Alatrash (12)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (274)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Kelly Ford (4)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matt Rutledge (2)
Matthias Schlomann (16)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Miguel Gatmaytan (3)
Mike Horton (19)
Mitchel Sellers (40)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Oliver Hine (1)
Patricio F. Salinas (1)
Patrick Ryan (1)
Peter Donker (54)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Sacha Trauwaen (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott Schlesier (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Steven Fisher (1)
Tony Henrich (3)
Torsten Weggen (3)
Tycho de Waard (4)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (40)
Will Strohl (180)
William Severance (5)
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out