Monday, November 23, 2009

SDK design considerations

SDK Design Considerations


API design principles

Following list summarizes some of the rules and laws which should be adhered to build a complete API for a SDK

1. Easy to learn

2. Make interfaces easy to use correctly and hard to use incorrectly.

Interface should not be misleading to use it incorrectly. You should define contracts preciously to avoid mistakes by the person who is using it.

3. Consistent API design

An interface that is predictable serves better than one which is locally optimal but inconsistent across the whole set.

4. It should be sufficiently powerful to satisfy the requirements, but should not be over complex.

5. Don’t try to please everyone by making the API generic.

6. Do not return resources that the caller is responsible for releasing.

Always try to encapsulate the resource releasing, cleaning and destructing logic.

7. Namespaces, Type names and function names should reflect the intended use.

8. Consider the API evolvement and extend over time.

Need to facilitate to effectively evolve an API to keep it relevant and useful over time, without having to throw it away and start over every 18 months.

Consider the coexistence with other versions when evolving

Other SDK requirements

1. SDK should be able to easily setup and configure(installation pack)

2. SDK should clearly define the development platforms which supported.

3. It should be able to maintain different versions and their coexistence.

4. SDK should contains following artifacts

a. Libraries

b. Documentation and tools utilizing the APIs

c. Samples

d. Licensing agreements

e. Source code(if open-source)

Development best practice

1. Code consistency using coding best practices, coding standards and basic frameworks

2. Unexpected behaviors need to be avoided.

3. Ensure graceful termination of unavoidable situations while providing proper information to the client.

4. SDK should be well tested before release.

5. Modularization should be done for reuse.

6. Access modifiers should be properly defined.

Monday, May 18, 2009

Localizing Sharepoint web sites and web parts

Localizing Websites and webparts in SharePoint

Internationalization is not a topic which is widely discussed by sharepoint communalities. Recently when I was researching this topic I came across with several interesting strategies of accomplishing the localization of sharepoint websites and webparts, which I think worth to discuss here. I will discuss these two areas separately and first let's discuss about internationalizing websites.

Localizing Sharepoint sites

Internationalization of web sites provided by sharepoint can be done only by installing relevant language packs which can be download from Microsoft web site. Once relevant language packs are installed site collections and sites are available with specific language options with a dropdown list to select.


So before you create the site you have to select the desired language of the web site or collection. Once you create by specifying the language, site is created using the specified language's template files.

Following languages packs and service packs need to be installed. After installing each pack, setup will ask to run the SharePoint configuration wizard. Run configuration wizard for successful completion.

  1. Install Windows SharePoint Services 3.0 Language Pack

    http://www.microsoft.com/downloads/details.aspx?FamilyId=36EE1BF0-652C-4E38-B247-F29B3EEFA048&displaylang=en

  2. Install Windows SharePoint Services 3.0 Language Pack Service Pack

    http://www.microsoft.com/DownLoads/details.aspx?familyid=05046B1D-DD7B-456A-8838-8D978C5F3579&displaylang=en

  3. Install 2007 Office System Language Pack. When downloading select the correct language at the language drop down to get the service pack of specific language.

    http://www.microsoft.com/downloads/details.aspx?FamilyID=2447426b-8689-4768-bff0-cbb511599a45&displaylang=en


 

  1. Install the 2007 Microsoft Office Servers Language Pack Service Pack 1. When downloading select the correct language at the language drop down to get the service pack of specific language.

    http://www.microsoft.com/DownLoads/details.aspx?familyid=3A6C26FD-0BEB-40D5-8CBA-15164FAAB150&displaylang=en


 

That's it. SharePoint language specific configurations and templates are installed into your Sharepoint front end server and now it's ready create new sites using new language.

Localizing sharepoint custom web parts

The default web parts provided by Sharepoint installation are automatically localized according to the language you select once you install the language pack. But when you develop custom web parts for your business needs, those web parts need to be localized using different language resource files.

Normally sharepoint sites are not localized according to user's browser language, but according to the language you use to create the site. So all the web parts inside the site should also behave in the same manner. Let's see how we can accomplish this.

  1. Create a library project in Visual studio (VS). I name it "langwebpart".
  2. Add a Reference to Microsoft.SharePoint.dll
  3. Update assembly version and and allow partially trusted callers
    1. In Solution Explorer, double-click the AssemblyInfo file

    [assembly: AssemblyVersion("1.0.0")]

    1. Add the following line to the top of the file:

    using System.Security;

  1. Add the following line to the bottom of the file

    [assembly: AllowPartiallyTrustedCallers]


 

  1. Add a new class. I name it as "userinfowebpart"
  2. Inherit userinfowebpart from Microsoft.SharePoint.WebPartPages
  3. Override the render method of WebpartPages

    protected
    override
    void Render(HtmlTextWriter output){};


     

  4. Create two resource files for English and Norwegian named userinfo.resx and userinfo.nb-NO.resx and add relevant language strings values with their key names.
  5. These localized strings can be used inside your programming code as follows.

    nameLbl.Text = langwebpart.userinfo.name;


    langwebpart is the namespace


    userinfo is the language file name

    name is the key.

Below is our code of the simple web part class.

namespace langwebpart{


public
class
userinfowebpart:Microsoft.SharePoint.WebPartPages.WebPart

{


Label nameLbl;


 


protected
override
void Render(HtmlTextWriter output)

{


try

{

RenderChildren(output);

}


catch (Exception e)

{


 

output.Write(e.StackTrace); ;

}


 


 

}


protected
override
void CreateChildControls()

{

nameLbl = new
Label();

nameLbl.Text = langwebpart.userinfo.name;

Controls.Add(nameLbl);

}


 


 

}

}


 

Developing localized web part is simple as mentioned above. Next step is to deploy the web part to the SharePoint server instance.

Deploying localized web part

There are several ways to deploy a web part to SharePoint. One of the easiest and simple way is to copy the relevant assemblies to bin directory of the SharePoint web application instance.

  1. Deploying to bin directory
  • Copy assembly DLL to either
    - /bin directory for a given IIS virtual server (e.g., c:\inetpub\wwwroot\bin) for globally available or to specific web application /bin folder to available only that web application.
  • Copy DWP file to C:\Inetpub\wwwroot\wpcatalog
  • Copy resources to C:\Inetpub\wwwroot\wpresources
  • Adjust web.config
    - Register as SafeControl
    - Select Code Access Security settings


     

  1. Deploying to as a Webpart package

A Web Part package is a cabinet (.cab) file that contains the following items:

  1. Manifest.xml (mandatory)
  2. Web Part assemblies (optional)
  3. Class resource files (optional)
  4. .dwp files (optional)

Creating a Manifest File for a .cab File

The Manifest file, a configuration file that describes the structure and contents of the .cab file, is the only required component for the .cab file. The Stsadm.exe tool uses this file to deploy the remaining content of the .cab file.

The following example shows a manifest file for a package that deploys two assemblies and their resources:

<?xml
version="1.0"
encoding="utf-8" ?>

<WebPartManifest
xmlns="http://schemas.microsoft.com/WebPart/v2/Manifest">

<Assemblies>

<Assembly
FileName="langwebpart.dll">

<ClassResources>

</ClassResources>

<SafeControls>

<SafeControl
Namespace="langwebpart"
TypeName="*"/>

</SafeControls>

</Assembly>

</Assemblies>

<DwpFiles>

<DwpFile
FileName="webpart.dwp"/>

<DwpFile
FileName="nb-NO\webpart.dwp"/>

</DwpFiles>

</WebPartManifest>


 

Creating a .cab File

Developers can use either of the following methods to create a .cab file:

  • Use Microsoft Visual Studio® .NET Professional to create a CAB Project.
  • Use MakeCAB.exe, a command-line tool included with Microsoft Windows 2000 and later.

Using Visual Studio

To use Visual Studio.NET Professional to create a CAB project, follow these steps:

  • Start Visual Studio .NET.
  • Create a new solution.
    • On the File menu, point to New, and then click Blank Solution.
    • Type a name for the solution, and then click OK.
  • Open the Web Part project within this solution.
    • In Solution Explorer, right-click the new solution, point to Add, and then click Existing Project.
    • Browse to the location of Web Part project that you want to add, click the project, and then click Open.
  • Create a new CAB project
    • In Solution Explorer, right-click the new solution, point to Add, and then click New Project.
  • Under Project Types, click Setup and Deployment Projects, and then under Templates, click Cab Project.
    • Type a name for the CAB project, and then click OK.
  • Add the Web Part project output to the CAB project.
    • In Solution Explorer, right-click the CAB project, point to Add, and then click Project Output.
    • In the Project box, click the Web Part project that you added to the solution in step 3.
    • Select all the appropriate file categories that appear in the list, and then click OK.

    Make sure that you select Primary output and Content Files. These categories add the Manifest.xml file, the .dwp files, and the Web Part assembly to the .cab file. Verify that the Manifest.xml file and the .dwp files are marked as content for build action in their respective properties sheets.

  • Build the solution to create the .cab file.

Using MakeCAB.exe

MakeCAB.exe is a tool included with Windows 2000 or later. To use MakeCAB.exe to create a .cab file, follow these steps:

  1. Create a directive file for makecab.exe, and save the file with a .ddf extension. The following sample directive file (named langwebpart.ddf) creates a .cab file for a simple Web Part library project:

;*** Sample Source Code MakeCAB Directive file example


 

.OPTION EXPLICIT ; Generate errors

.Set CabinetNameTemplate=langwebpart.cab

.set DiskDirectoryTemplate=CDROM

.Set CompressionType=MSZIP

.Set UniqueFiles="OFF"

.Set Cabinet=on

.Set DiskDirectory1=langwebpart.CAB

Manifest.xml

webpart.dwp

langwebpart.dll

.Set DestinationDir=nb-NO

nb-NO\webpart.dwp

;*** <the end>

  1. Copy all the files that you want to include in the .cab file into the directory where you created the .ddf file. In this example, these files are the Manifest.xml file, the WebPart.dwp file, and the langwebpart.dll file.
  2. Open a command prompt, change to the directory that contains the .ddf file and the files that you want to include in the .cab file, and then run the following command:

    Makecab.exe /F langwebpart.ddf

MakeCAB.exe creates a directory named langwebpart.cab, and in this directory MakeCAB.exe creates a .cab file named langwebpart.cab that contains the all the files listed in the langwebpart.ddf directive file.

Creating a CAB File with Localized Resources

Visual Studio does not support creating .cab files with internal directories. However, localized Web Parts may require a .cab file with internal directories. Because of this you must use a tool like MakeCAB.exe or another, third-party CAB utility to deploy localized Web Parts.

Deploying a Web Part Package

Administrators can use the Stsadm.exe tool to deploy .cab files created by developers. Stsadm.exe is a command-line tool that you can use to manage a Windows SharePoint Services computer. Three Stsadm.exe options apply to Web Part package deployment:

  • AddWPPack
  • DeleteWPPack
  • EnumWPPacks

For more information about a specific Stsadm.exe command-line option, type the following line at a command prompt:

stsadm –help option

Adding a Web Part Package

To use the Stsadm.exe command to deploy a Web Part package on a server computer running Windows SharePoint Services, open a command prompt, and then type the following command:

stsadm.exe -o addwppack 

-filename Web_Part_Pack_name

[-url URL]

[-globalinstall]

[-force]

If you want to install a Web Part package on a virtual server when the Web Part package is already installed on another virtual server on the same computer, use the following command:

stsadm.exe -o addwppack

-name Web_Part_Pack_name

[-url URL]

[-globalinstall]

[-force]

Deleting a Web Part Package

To delete a Web Part package from specified virtual servers on a computer running Windows SharePoint Services, open a command prompt, and then type the following command:

stsadm.exe -o deletewppack

           -name Web_Part_Pack_name

           [-url URL]

To decide whether to install a Web Part package in the GAC or in the Bin directory, ask the following questions:

  • Do you want to make this package available to all virtual servers on your computer?
  • Do you trust the assemblies and resources of the package completely?

If you answer "yes" to both of these questions, install the Web Part package to the GAC. Assemblies in the GAC are fully trusted and are available to all virtual servers.


For more info http://msdn.microsoft.com/en-us/library/dd583149.aspx

Tuesday, May 05, 2009

ORganization culture Change ...A Nightmare???

Organizational culture is the identity and personality of the organization which makes the uniqueness. This personality is glued with collection of values and norms that are shared by people and groups in an organization and that control the way they interact with each other and with people outside the organization and comprised of the shared assumptions, values, shared priorities and norms, tangible artifacts of organization and behavioral patterns of organizational members. Once the members are incepted, they soon come to sense the particular culture of an organization and become part and parcel of it. Relationship diagram of cultural entities are very complex and very difficulty explain and distinguish, because they are interconnected, randomly changing and very volatile.

Due to this nature, today organizations attention towards the culture management has dramatically increased, because it is the engine of the organization which drives it towards achieving organizational goals and objectives. So the interested parties of the organization always try to keep the engine running while executing minimum or no changes. This concept of minimum changes concept implies that culture change is difficult and it should be carefully advocated.

Normally people are attached and frozen with current comfortable culture. They resist changing the situation and show strong reactions. Following are some of the key issues found.
1. Comfort with current situation. When people work in a culture for a long time a social environment is built around them and they are trapped within it.
2. Fear of collapse. Not all the organizational changes are going to be successful. There are thousands of user stories of failure.
3. Unpredictability of new system.
4. Unwillingness to learn and experience new things. Different types of personalities can be found in an organization. Some are self motivated and willing to experience new things. But most of the people do not want to do so.
5. Difficulty in defining the complete change model. It is evident that modeling a change for all the organizational requirements is hard and even harder to define a flexible model which caters for changing requirements.
6. Feeling of the participants that their autonomy and their security are threatened.

Careful handling of these situations while building safety nets and preventing frustration from developing into resistance helped to a successful culture change.

Monday, January 12, 2009

Thread Safe Dictionary in C#

I have been working with a project where concurrent requests are accessing a Dictionary. If you check from msdn the Dictionary class http://msdn.microsoft.com/en-au/library/xfhwa508(vs.80).aspx is not Thread safe.

Thread Safety

Public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

To overcome this one can use Hashtable.http://msdn.microsoft.com/en-us/library/system.collections.hashtable.aspx
Hashtable is thread safe for use by multiple reader threads and a single writing thread. It is thread safe for multi-thread use when only one of the threads perform write (update) operations, which allows for lock-free reads provided that the writers are serialized to the Hashtable. To support multiple writers all operations on the Hashtable must be done through the wrapper returned by the Synchronized method, provided that there are no threads reading the Hashtable object.

But for multiple writes you need to get the Synchronized Hashtable as follows.
Hashtable myHT = new Hashtable();
Hashtable mySyncdHT = Hashtable.Synchronized( myHT );

But to make the dictionary you have three things to do.
1) Create a sub-class of System.Collections.Generic.Dictionary
2) Create a utility class for modifying the collection safely
3) Creating your own thread-safe dictionary from scratch.


I have written written a utility class which keeps a instance of Dictionary and modify it in a thread safe manner with ReaderWriterLockSlim. Check the advantage of ReaderWriterLockSlim over ReaderWriterLock here.http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx.

Following is my code sample.

public class SerializableDictionary : IXmlSerializable
{

//This is the internal dictionary that we are wrapping
IDictionary dict = new Dictionary();

#region IDictionary members
[NonSerialized]
ReaderWriterLockSlim dictionaryLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);


public virtual bool Remove(TKey key)
{
dictionaryLock.EnterWriteLock();
try
{
return this.dict.Remove(key);
}
finally
{
dictionaryLock.ExitWriteLock();
}
}


public virtual bool ContainsKey(TKey key)
{
dictionaryLock.EnterReadLock();
try
{
return this.dict.ContainsKey(key);
} finally
{
dictionaryLock.ExitReadLock();
}
}


public virtual bool TryGetValue(TKey key, out TValue value)
{
dictionaryLock.EnterReadLock();
try
{
return this.dict.TryGetValue(key, out value);
}
finally
{
dictionaryLock.ExitReadLock();
}
}


public virtual TValue this[TKey key]
{
get
{
dictionaryLock.EnterReadLock();
try
{
return this.dict[key];
}
finally
{
dictionaryLock.ExitReadLock();
}
}
set
{
dictionaryLock.EnterWriteLock();
try
{
this.dict[key] = value;
}
finally
{
dictionaryLock.ExitWriteLock();
}
}
}


public virtual ICollection Keys
{
get
{
dictionaryLock.EnterReadLock();
try
{
return new List(this.dict.Keys);
}finally
{
dictionaryLock.ExitReadLock();
}
}
}


public virtual ICollection Values
{
get
{
dictionaryLock.EnterReadLock();
try
{
return new List(this.dict.Values);
}
finally
{
dictionaryLock.ExitReadLock();
}
}
}


public virtual void Clear()
{
dictionaryLock.EnterWriteLock();
try
{
this.dict.Clear();
}
finally
{
dictionaryLock.ExitWriteLock();
}
}


public virtual int Count
{
get
{
dictionaryLock.EnterReadLock();
try
{
return this.dict.Count;
}
finally
{
dictionaryLock.ExitReadLock();
}
}
}


public virtual bool Contains(KeyValuePair item)
{
dictionaryLock.EnterReadLock();
try
{
return this.dict.Contains(item);
}
finally
{
dictionaryLock.ExitReadLock();
}

}


public virtual void Add(KeyValuePair item)
{
dictionaryLock.EnterWriteLock();
try
{
this.dict.Add(item);
}
finally
{
dictionaryLock.ExitWriteLock();
}
}


public virtual void Add(TKey key, TValue value)
{
dictionaryLock.EnterWriteLock();
try
{
this.dict.Add(key, value);
}
finally
{
dictionaryLock.ExitWriteLock();
}
}


public virtual bool Remove(KeyValuePair item)
{
dictionaryLock.EnterWriteLock();
try
{
return this.dict.Remove(item);
}
finally
{
dictionaryLock.ExitWriteLock();
}
}


public virtual void CopyTo(KeyValuePair[] array, int arrayIndex)
{
dictionaryLock.EnterReadLock();
try
{
this.dict.CopyTo(array, arrayIndex);
}
finally
{
dictionaryLock.ExitReadLock();
}
}


public virtual bool IsReadOnly
{
get
{
return this.dict.IsReadOnly;
}
}


public virtual IEnumerator> GetEnumerator()
{
throw new NotSupportedException("Cannot enumerate a threadsafe dictionary. Instead, enumerate the keys or values collection");
}
#endregion
}