Sharepoint Search Webpart – Displaying results in a new window

IE is my bitch.  Thats what I said when I finally cracked this one.  Its not true of course, IE and its convoluted system of non-standardisation and obscure bugs will make idiots of us all as we attempt to develop for it, but occasionally solving a particular problem makes you feel so good you’ve just got to throw down.  This was one of those problems.

One of the things that made this so is the fact that on the surface it seems so easy.  Load up a new page and send your results to it rather than displaying them on the main page.  It would be that easy too, if not for the fact we’re developing a sharepoint webpart, not a web application.

What does this mean? It means we don’t have a raft of things we’re used to having access to.  We don’t have a page object at easy beck and call for instance, with its nice httpcontext and response objects.  We don’t have access to any sort of control over the page posting process, because we’re a lowly webpart, not a page ourselves.  All we really have access too is the amount of page space granted us by sharepoint, and we can only access that by overriding a control render function to manually render a couple of controls.

Thats ok though, the main way to launch new windows is using javascript, and we can do that right?  Well, not exactly.  Its true we can set up a button, give it a javascript onclick event and process things that way, the particular search part I was working on is a glossary webpart that searches a database for its results.  Even if this is possible to do in javascript, the idea of using javascript to access my nice production database server?  No.  Really, just no.

So, obviously we need a combination. Javascript -and- code-behind c# code.  Its possible to use both on the one pass through. Unfortunately, it works the wrong way.  Javascript is called first, followed by code-behind.  We would have to display the results, before we’ve had a chance to get them.  p@in.

So, javascript event handling is out the window, doesn’t work for us.  Where did that leave us?  With an asp.net literal object and a hell of a lot of test debugging.

The solution is to do your processing in a code-behind function, get your database results, and then fill a literal control with javascript that creates the window and fills the results.  After the code-behind function finishes, the page is refreshed and your new javascript code is called, displaying the results.

So, in effect, we have code (C#) that creates code (Javascript) that creates code (Html).  And yeah, it ends up looking just as complicated as it sounds.  But it works.  Here are some snippets to serve as an example, should you decide to try it out for yourself.

Note: These are snippets cut from the code themselves, not an entire code file.  You need to take care of some things yourself if attempting to implement this example, such as declaring the control variables etc 😉

// We need to be able to create child controls – to show you what sort of interface we’re using
protected override void CreateChildControls()
{
    enterText = new Label();
    enterText = “Enter the term to search for:”;
    this.Controls.add(enterText);

    searchBox = new TextBoxt();
    …. define and add

    searchButton = new Button();
    searchButton.Click += new EventHandler(searchButton_Click):
    .. Define and add

    searchResults = new Literal();  // Our all-important javascript enabling literal
    searchResults.ID = “searchResults”; //and a way to access it.
    this.Controls.Add(searchResults);
}

I’ll leave rendering them as an excercise to the reader, its a simple matter of setting up the controls how you like and calling the render command on the controls where necessary.

private void searchButton_Click(object sender, EventArgs e)  //Where the magic happens
{
    ….. skip a whole lot of database connectivity stuff that you can read about elsewhere.

    System.Data.SqlClient.SqlDataReader gloddRead = glossCommand.ExecuteReader();

    System.Text.StringBuilder script = new System.Text.StringBuilder();

    script.Append(“<script language=\”javascript\”>”);
    script.Append(“var w = window.open(\”\”, \”results\”, \”height=600,width=800,scrollbars\”);”);
    script.Append(“var d = w.document;”);

    script.Append(“d.open();”);
    script.Append(“d.write(‘<html><head>’);”);
    script.Append(“d.write(‘<title>Results</title>’);”);
    script.Append(“d.write(‘</head><body’);”);
    script.Append(“d.write(‘<h1 class=\”header\”>Results</h1>’); “);
    script.Append(“d.write(‘<table class=\”result\” width=\”100%\” cellpadding=\”3\” cellspacing=\”0\”‘>’);”);
    script.Append(“d.write(‘<tr><th>Term</th><th>Context</th><th>Literal</th><th>Definition</th><th>Link</th></tr>’); “);

    while (glossRead.Read() )
    {
       script.Append(“d.write(‘<tr>’);”);
        script.Append(“>’);”);
        script.AppendFormat(“d.write(‘<td width=\”5%\”>{0}</td>’);”, glossRead[“Term”]);
        script.AppendFormat(“d.write(‘<td width=\”5%\”>{0}</td>’);”, glossRead[“Context”]);
        script.AppendFormat(“d.write(‘<td width=\”20%\”>{0}</td>’);”, glossRead[“Literal”]);
        script.AppendFormat(“d.write(‘<td>{0}</td>’);”, glossRead[“Definition”]);
        script.AppendFormat(“d.write(‘<td><a href=\”{0}\”>{0}</a></td>’);”, glossRead[“Link”]);
       script.Append(“d.write(‘</tr>’);
    }

    script.Append(“d.write(‘</table>’);”);
    glossRead.Close();

    script.Append(“d.write(‘</body></head></html>’);”);
    script.Append”</script”);

    searchResults.Text = script.ToString();
}

There, a semi-illustrative example.  You might have to go over it a few times, it looks a lot more complicated than it actually is.

It wont look particularly nice, but it will work.  My finished version embeds css styles in the head section to beautify the result a bit.  I’m thinking about adding some images and such too, but i’ve not finished up to that point yet.  Feel free to leave any comments or questions.

Advertisements

2 thoughts on “Sharepoint Search Webpart – Displaying results in a new window

Leave a Reply

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

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s