Friday, April 24, 2009

Customize list form (cont.)


I wrote on this topic a little bit in the past.
http://murmurofawebmaster.blogspot.com/2008/11/customize-list-form.html

The motivation at that time was, and still is to evaluate, to see what it can, how easily, and what not.
The thing that I picked up (some functionality of the web site to implement using this technique) was the feedback form (I have to have it anyway in one way or another).
The challenges were:
1. It sends an email message. The address is given.
# The current form takes the address from QueryString. With the new SharePoint based website, you find it in the PropertyBag of each site. So idealy, depending on where a link to the feedback is clicked, when it is opened, it should already knows where to send email.
2. An anonymous visitor can give him/her feedback.

For the email, I used the SPD Workflow.
The first prototype takes the address from QueryString, just like our current form. I do not think I can get it from the site’s PropertyBag unless I make the form as an Application Page with code behind.
With some JavaScript, I pick up the email from QueryString and set to a field of the list. You can send a message to it from Workflow.
Nice. Done. (I thought…)

Then, I realized that I can not access the custom insert form of the list anonymously.
After having spent sometime, I now guess that it is probably because the site being in the lockdown mode.
http://technet.microsoft.com/en-us/library/cc263468.aspx
OK, then, I can make it as a page under the Pages library.

An error. “The data source control failed to execute the insert command.”
Again spent time on the net to find someone say the following.
“I’m finding out that the dealbreaker with anonymous access is the association with the SPD created workflow. … Design a workflow and associate it with the list and the form will bomb any time that the workflow is initiated.”
http://blogs.devhorizon.com/reza/?p=498

This person ended up doing it with an Application Page with code behind. I guess I would follow the path…

Wednesday, April 8, 2009

Content Query Web Part


My goal was to have multilingual summary links.
I tried to implement it through the combination of custom list and content query web part.
Our web site is in multiple languages. Image you have the OOBT summary links placed on pages in different languages, and that you update them one by one. It would be so painful for a person who does not speak the language(s). And it would br very tidious as well.
So my idea was that I have a custom list containing all links, each marked with a language. And using content query part to filter them. For instance if it is on an Arabic page, it picks up only links marked as in Arabic.

First, I defined my multiligual link content type as an inherited type of the built-in link type.
Then I added; language column (built-in), ImageUrl column (custom) of publishing image (comes with the UI that allows my users to browse thru image libraries to select an image) and LinkSortOrder column (custom. Useful also to group links to the same contents in different languages).

Next, I created a custom list of the type.
# I do not think defining the type, and then defining it as the type of the list was required. You could have a list with those columns directly defined. It was a design choice.

Then I prepared a page layout per language. Again a design choice. I may be able to have just one layout to serve all different languages.

Now to customize the presentation.

As you know, it is to write a XSLT code to render the XML returned from CQWP in a way you like.
First, we want to have a look at the XML. I found a good post here
http://www.sharepointblogs.com/radi/archive/2009/03/17/content-query-web-part-getting-a-full-dump-of-the-raw-xml.aspx.

However, the challenge was to figure out how to tell the web part to use my XSL rather than the default one.
I have the CQWP placed on a page layout, not a page. I did not find many who do this on the net. At the beginning, I did not think this export/upload was a solution to my case. I gave it a try nevertheless and found out that it is a hidden attribute. “hidden” here I mean, you do not see it by just creating an instance of the OOTB CQWP. So all you have to do is just add it manually.

<PublishingWebControls:ContentByQueryWebPart … MainXslLink="/Style Library/XSL Style Sheets/myContentQueryMain.xsl" … >

In the XML that I finally managed to look into, of course I do not see those columns I added. So I specified the following value to another hidden attribute.

CommonViewFields="URL, URL;ImageUrl, Image"

The URL is a column defined with the built-in Link type.
To determine the types (comes after comma for each column) was a challenge too. It still is, when I do this again for other purposes.
This document
http://msdn.microsoft.com/en-us/library/aa981241.aspx is the most explanatory that I found, but still not stisfactorily clear.
For instance, in addition to the URL type, it says now we have another type called Link. I tried both but did not see the difference. They are the same in the XML. I think Microsoft should give us a table where we see the matching between Content Column type and type should be used in the CommonViewFields and other similar properties of CQWP…

Once you have those columns you added appear in the XML, the rest is just usual XSLT coding that many already talk about on the net.

After having gone thru this exercise, I think now that to deal with a custom list such as this one, a better, more beautiful way would be to have the completely own set of columns appear in the XML using yet another hidden attribute called ViewFieldsOverride. There is a nice article
http://sharepoint-tweaking.blogspot.com/2008/04/displaying-listname-and-sitename-when.html.

A better still would be that Microsoft, or somebody (though I would rather not to go to a third party solution) come up with a CQWP-like webpart that generates XML according to the custom list and/or content type specified. It may be difficult though, since then what I could have as the default XSL…

Wednesday, April 1, 2009

Cache-Control: public and Session


Recently one of our developers reported that session variables are not kept for him and asked me to look into.
After a couple of hours of investigation, I finally came to conclude that this is probably because he set Cache-Control to public in his page.

The below is my conclusion.
When Cache-Control is set tp public with your page, it is undestood that the page is the same for everybody at any time.
When a proxy server sees it, it caches the page, and the cookie, where your session is stored, will not reach the user browser.
Consequently, when the user makes the next request to your server, no cookie will be sent. The server sees it as a new session.

That the cookie does not reach the client is true. I do not see the Set-Cookie header in the response. I would see it if Cache-Control is set to private, the default.
But I was surprised by two things.

One: I found nobody talks specifically about this on the net. I think this is a pitfall that we could fall into easily.
Many says that when the page requires authentication, it has to be private, without explaining why in detail. So you may not see it related.

Two: By the fact that proxy strips cookie when Cache-Control is set to public.
Mmm… Maybe… because it first caches the response and then send it to you. Anyway, it was good to know