Search This Blog

Monday, January 26, 2009

Automatic Navigation Hierarchy for Content Pages

Simple but powerful...
WSS/MOSS allows an extensible Navigation system.
At times we need to display the hierarchy of pages. For example:
Articles Landing Page (shows a List of all Articles) --> Each Article is a page of its own.

Solution:
Create a subsite for Articles. Set the home page as Articles Landing Page (from site settings --> Welcome Page). Also set the navigation to show Pages
Now on the quick navigation on left

it will Show the following in Navigation
Site Name (which links to Landing Page)
Individual Article Page1 Title
Individual Artcile Page2 Title

That works Good. How about having Multiple Categories:
Category (each category is a site with Home Page) --> Sub Category (each subcategory is a Page only)

Hence we will see the navigation as:
Category 1 (site with a home page)
Sub Category 1 (page)
Sub Category 2 (page)
Category 2
Sub Category 1
Sub Category 2

So in above case we only created two sites i.e. for Category 1 and Category 2 and the remaining are content pages.

What if there were 3 levels;

Level 1 (site 1 with a Welcome Page)
Level 2 (site 2 with a Welcome/Home Page)
Level 3 (pages below Site 2)

Hope this helps...
Mohan

Hide the nested controls when a Publishing field value is blank

In a Page Layout, when a publishing field value is blank, it may occupy few pixel space which creates uneven format positions. So overcome this I had created a custom control which supresses the control nested inside this custom control when the value of the field is blank.

------------------------------

Please compile the below code and check for typos since I extracted this from a code doing other things as well. From within the page using SPContext we have access to the data for the same page, hence we can check its value and decide to either render or not render the nested control contents.

Here is how usage would look like:

<custom:HideWhenBlank runat="server" FieldNameToCheck="ImageFieldHere">
....
.. <...... Field="ImageFieldHere" >


</custom:HideWhenBlank>

so the value of "ImageFieldHere" will be checked before displaying the image and if it is blank, all the HTML and publishing controls inside the tags will not be parsed and vice versa, i.e. if the image does exist it will be shown.
Also as a note 1) this will work for all data types and not just image types.
2) It is not necessary to inherit from SPSecurityTrimmedControl and you could use other UI base control.
3) In SPD in design mode you will continue to see the nested controls (a check made in above code for design mode), since we would not have access to SPContext at that time. We can the see the end result when the page is shown in browser.


Here is the code:


1 [CLSCompliant(false)]
2 [ParseChildren(false)]
3 [Guid("please put a guid here")]
4 public class CustomTrimming : Microsoft.SharePoint.WebControls.SPSecurityTrimmedControl
5 {
6 public string FieldNameToCheck {get;set;}
7 protected override void Render(HtmlTextWriter writer)
8 {
9 SPListItem item = null;

if (!DesignMode)

{

10 if (SPContext.Current != null)
11 {
12 item = SPContext.Current.ListItem;
13 }
14 if ((FieldNameToCheck != string.Empty) && (item != null))
15 {
16
17 if (CheckIfNullOrBlank(item[FieldNameToCheck]) == false)
18 {
19 base.Render(writer);
20 }
21 }
}
else // to display the nested controls / html when in SharePoint Designer 2007
{

base.Render(writer);


}
22 }
23
24 private bool CheckIfNullOrBlank(object data)
25 {
26 if (data == null || (Convert.ToString(data).Trim() == string.Empty))
27 {
28 return true;
29 }
30 else
31 {
32 return false;
33 }
34 }
35
36 }
37

Add the above as a Class file, add SharePoint dll references, assign a Strong Name key. Assuming you are using VseWSS, this will create a WSP file.

Hope this helps.
Mohan

Tuesday, January 6, 2009

Parser and Lexer

There are 3 types of commonly used lexer/parsers i.e.

LL - Top down recursive parsers. Example: Antlr (www.antlr.com)
LR - Bottom up parser using tables. Example: Visual Parse++
GLR - Bottom up parser with lot more for handling ambiguities. Example: DParser


For Interactive environments like IDE: An incremental parser is the preferred choice.
Any of the above can come with Incremental parsing features, depends on which one we are using.

For batch conversions and ease of writing Grammars, LL would be the best.
Performance would be better with LR because of tables.
For good error handling and handling ambiguity, GLR would be good.

Moreover these can be with arbitrary lookaheads.
Example: LL(k) - k means infinite lookahead capability.
LL(1) - 1 is only 1 token lookahead capability.

SAP Integration with MOSS

To integrate with SAP, the tool used is the following:

SAP Enterprise services explorer
Version is 1.1

This is Web Services integration with SAP and works with Visual Studio .Net

Search for above on SAP site and you can get a link to download.

XHTML compliance for Rich Text in MOSS

Got this information from a blog item on Telerik (http://www.telerik.com/)
While the Rad Editor by Telerik is a good tool to save the rich html as XHTML,
but the built in save process in SharePoint will strip of the XHTML.

Solution: Instead of saving the Rich text data to a Rich Text field, save it to text field with multilines. In the Page layout use:

<Rad: field="plaintextfield" />

Where plaintextfield is field defined in the content type as Text field with multilines.



Getting the process id in Windows 2008 Server

While it was cscript iisapp.vbs in Windows 2003 (from \system32),
Windows 2008 has the following command for getting the process id:

appcmd list wp

appcmd is available in \system32\inetsrv
Both the commands are run from command prompt.

Why do we need these:

To attach to the correct W3p process from Visual Studio for debugging your application from Visual Studio .Net

Reading user profiles thru code

Here is a code snippet for reading the user profiles:

using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;
...
...
...

UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(HttpContext.Current));
foreach (UserProfile profile in profileManager)
{
/* if we know the field name this may help us to get the value directly instead of using the following loop. Have not tried running the line below so please... */
//string empName = profile["PreferredName"][0] as string;

// The following for loop is used for displaying all the Field Names for profile (and
// can be used for fetching or displaying values also
foreach (KeyValuePair val in profile)
{
System.Diagnostics.Debug.WriteLine("Key =" + val.Key);
}
}