Welcome to EMC Consulting Blogs Sign in | Join | Help

Pawan Gulati's Blog

  • Localizing text in a custom DataFormWebPart

     

    Problem: Localize text displayed in the web parts based on user's selected language.

    Background:

    For a recent implementation of global collaboration and content management platform, we supported multiple languages. Content was displayed on the pages through custom DataFormWebParts that relied on underlying services that pulled data (xml) from variety of sources and transformed it using xslt. Content displayed on the SharePoint pages can come from a number of places:

    • For XML web parts, some strings (for buttons, titles etc) are embedded within the xsl files.
    • For server controls, content is build in server side code.
    • Any branding elements embedded within master pages + page layouts + css + javascript + jquery.

    Goal:

    Use a common set of resource file(s) for maintaining localized strings. Content should be displayed from these resource files irrespective of where it is being displayed from (server side, client side)

    Utilize an approach that minimizes changing every web part and coupling them tightly to the user interface. We had over 30 custom web parts and we need a design pattern that did not require us to maintain a copy of these web part for each instance needed on the site.

    Here are the options we came up with during our design stage.

    Option 1: Pass the appropriate resource file reference to xslt

    Based on the language setting, the appropriate resource file could be sent as a parameter to the xslt. The xslt can then read the resource file and retrieve localized strings as needed during the translation.

    Implementation Details:

    In the XSLT, define a parameter to accept the URL to the resource XML document for the selected language. Use the XPath 'document' function to read the XML with the translated strings. Define a parameter for each string used in the XSLT. Using parameters rather than variables allows the values to be overridden when the XSLT is transformed. Use xsl:value-of to display the translated text.

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:param name="resourcefile" select="'myresourcefile_en-US.xml'"/>

    <xsl:variable name="resourceXml" select="document($resourcefile)/*" />

    <xsl:param name="MyCustomText" select="$resourceXml/data[@name='MyCustomText']/value/text()"/>

    :

    <xsl:value-of select="$MyCustomText"/>

    :

    When the transform is processed, pass the URL to the resource XML document for the desired language.

    System.Xml.Xsl.XsltArgumentList objXsltArgs = new System.Xml.Xsl.XsltArgumentList();

    objXsltArgs.AddParam("resourcefile", "", "myresourcefile_sp-SP.xml");

    Feasibility: Yes

    The Document function is disabled by default and can be turned on by using the XsltSettings.EnableDocumentFunction Property.

    Recommended: No

    While technically feasible, this approach loads the resource xml as a document and reads the localized string value from the resource xml. This will consume additional memory for each xslt transformation as well as adding additional computational overhead.

     

    Option 2: Using special xPath syntax @Resources

    Resource strings can also be made available to XSLT transforms as XPath expressions that are used in <xsl:value-of> tags. To retrieve resources, SharePoint Foundation uses a special XPath syntax that is interpreted by the XPathNavigator object that is used by the XsltListViewWebPart object when the transform runs.

    Implementation Details:

    The syntax is specified as follows:

    <xsl:value-of select=”@Resources. resfile . resname ” />

    The following example retrieves the “noitemsinview_doclibrary” resource from the wss.resx file.

    <xsl:value-of select=”@Resources.wss.noitemsinview_doclibrary” />

    The “resource” attributes are actually something like pseudo-attributes of the source XML. There is no source XML at least in the form of a XML DOM container class like XmlDocument or XDocument. The trick is possible because the XLV uses a custom XPathNavigator (overriding the DataFormWebPart.GetXPathNavigator virtual method). This custom XPathNavigator queries directly the SPListItem data that the XLV web part retrieves from SharePoint and as an extra provides the “resource” pseudo-attribute support.

    Feasibility: No

    While this would be the simplest and an efficient way of consuming resources from the xslt, this option is only available for web parts based on XSLTListViewrWebPart. Unfortunately the “resource” pseudo-attribute “shortcut” is not available in the custom DataFormWebPart.

    Recommended: n/a

     

    Option 3: Use ParamaterBindings and Style sheet Params

    Resource strings can be made available to XSLT transforms via style sheet parameters (<xsl:param>) that are retrieved through <ParameterBinding> tags in the Web Part.

    This approach requires updating each web part to include a ParameterBinding element to pass in every localized string value needed by the xslt.

    The ParameterBinding element includes a Location attribute that specifies resource types. The syntax for this element is:

    <ParameterBinding Name=” parameterName ” Location=”Resource( resourceFile , resourceName )” />

    resourceFile
    The base name of a SharePoint Foundation resource file, without the extension. For example: wss, or core.

    resourceName
    The name of the resource string. For example: string1.

    Implementation Details:

    You can use the server object model to add a parameter binding to the collection of bindings for an XsltListViewWebPart object through the ParameterBindings property of the Web Part, or through the ParameterBindings property of the SPView object that is associated with the Web Part. You can also declaratively add a <ParameterBinding> tag to the <ParameterBindings> section of a View element in a list’s Schema.xml file to declare a parameter binding for use in XSLT. For example, the following tag makes a string available for display in document library list views when there are no items:

    <ParameterBinding Name=”NoAnnouncements” Location=”Resource(wss,noitemsinview_doclibrary)” />

    In the example, NoAnnouncements is the name of the resource for use in XSLT, wss is the name of the file that contains the resource minus the file name extension, and noitemsinview_doclibrary is the name of the resource as represented in the resource file.

    After the <ParameterBinding> tag is added to the <ParameterBindings> collection on the Web Part, it becomes available to the XSLT style sheet by defining a top-level <xsl:param> tag of the same name:

    <xsl:param name=”NoAnnouncements”/>

    You can then consume the resource by using an XPath expression anywhere in the style sheet, as in the following:

    <xsl:value-of select=”$NoAnnouncements” />

    Feasibility: Yes

    Recommended: No

    While the approach is technically feasible, it requires a change to every single web part to pass in the UI specific parameters. While this can still be achieved by setting the parameterbindings declaratively in the .webpart files, any changes (like using new resource keys within xslt) would require development effort and a new code build. In the absence of a better approach, this would be our fallback.

     

    Option 4: Calling an external function from Xslt

    Resource strings can be made available to XSLT transforms via an external function call. The Xslt will use a static method to read the localized strings from the resource files. This will allow us to utilize the recommended SharePoint approach (SPUtility.GetLocalizedString) for reading localized strings in the server side static method.

    Note: SPUtility.GetLocalizedStringmethod can retrieve a string value from a resource file located in the Resources folder that is just below the SharePoint Foundation installation root. The token that Visual Studio uses for this folder is {SharePointRoot}\Resources. The full path is %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\Resources.

    .NET XSL transformations implementation allows us to define a .NET class whose methods (rather static methods) can become available and be used from inside the XSL. Such “extension” class can also be used in a web part derived from the DataForm web part. The ModifyXsltArgumentList virtual method will have to be overridden to hook the custom extension object.

    Implementation Details:

    1. Implement a static method for reading the localized string values from the resource files. This method will read the mycustomresourcefile.resx file from the {SharePointRoot}\Resources\MyResources folder.

    public class PGLLocalizationResourceManager
    {
        public static string GetLocalizedValue(string name)
        {
            try
            {

    // sample code below the language code is being read from the current thread. In practice you could read the Thread Culture or cookie/session value where you are persisting the user’s language selection.

                int intLCID = System.Threading.Thread.CurrentThread.CurrentUICulture.LCID;

                return SPUtility.GetLocalizedString("$Resources: " + name, "Myresources\\mycustomeresourcefile", (uint)intLCID);
            }
            catch (Exception ex)
            {
            //TODO:
                throw ex;
            }
        }
    }

    2. Override the ModifyXsltArgumentList method in the custom web part class.

    protected override void ModifyXsltArgumentList(ArgumentClassWrapper argList)

    {

    argList.AddExtensionObject("EMC:ResourceManager", new PGLLocalizationResourceManager());

    base.ModifyXsltArgumentList(argList);

    }

    where EMC:ResourceManager' is the namespace URI to associate with the object and PGLocalizationResourceManager() is the object that provides the static method.

    3. Within the xslt, add a namespace for this extension object.

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:EMCRM="EMC:ResourceManager">

    4. Within the xslt, use the static method to get to the localized string.

    <xsl:variable name ="localizedtextstring" select ="EMCRM:GetLocalizedValue('Sample_Text_String')"></xsl:variable>

    <xsl:value-of select="$localizedtextstring"/>

    Or

    <xsl:value-of select="EMCRM:GetLocalizedValue(''Sample_Text_String)"/>

    5. Any server side code can use the same static library method to retrieve strings as needed.

    Feasibility: Yes

    Recommended: Yes (PREFERRED OPTION)

    Based on our analysis, this seemed to be the option that met our goals. Last week we successfully rolled out a solution based on this approach.


    References:

  • Error while creating or deleting a Web Application in SharePoint 2010

    Received an error that starts with “An update conflict has occurred, and you must re-try this action. The object SPClaimProviderManager Name=ClaimProviderManager was updated by domain\username…”

    If you check the SharePoint logs, the error message is similar to:

    “ UpdatedConcurrencyException: The object SPClaimProviderManager Name=ClaimProviderManager was updated by another user.  Determine if these changes will conflict, resolve any differences, and reapply the second change.  This error may also indicate a programming error caused by obtaining two copies of the same object in a single thread. Previous update information: User: DEMO\{MachineName}$ Process:OWSTIMER (2256) Machine:{MachineName} Time:November 02, 2010 12:00:42.0000  Current update information: User: DEMO\Administrator Process:w3wp (8040) Machine:{MachineName} Time:March 17, 2011 03:27:15.4446 …     ”

    To resolve this:

    1. Stop the SharePoint 2010 Timer service.
    2. On a Wndows Server 2008 R2 server, navigate to the folder: “C:\ProgramData\Microsoft\SharePoint\Config\{GUID}”. Delete all the files from this folder.
    3. Restart the Timer service
    4. You should be able to perform the activity on Web Application in SharePoint Central Admin now.
  • Running your code with system account (elevated) privileges

    If you are trying to perform an operation via the object model and the signed in user doesn’t have the appropriate permissions, you have to use elevated privileges. I have used the SPSecurity.RunwithElevatedPrivilege in the past to do that but there is another way. You can impersonate the system account. Here is how:

    To impersonate the System Account, we need to get the user token from the SYSTEM ACCOUNT.

    SPUserToken sysToken = SPContext.Current.Site.SystemAccount.UserToken;

    using(var systemSite = new SPSite(SPContext.Current.Site.ID, sysToken))
    {
        using (var sysWeb = systemSite.OpenWeb(SPContext.Current.Web.ID))
        {
            // Perform elevated actions here
        }
    }

  • SharePoint Object Model – Users

    Have you ever tried listing the users for a site collection from the object model and realized that the list isn’t what you expected? I ran into that recently and realized that there were several ways to get to the users and there are subtle differences in the results. Here is a quick listing:

    SPWeb.AllUsers Property (Microsoft.SharePoint)

    Gets the collection of user objects that represents all users who are either members of the site or who have browsed to the site as authenticated members of a domain group in the site.

    SPWeb.SiteUsers Property (Microsoft.SharePoint)

    Gets the collection of all users that belong to the site collection.

    SPUtility.GetAllAuthenticatedUsers Method (Microsoft.SharePoint.Utilities)

    Returns All authenticated users of a site

    SPAlertCollection.GetUniqueUsers Method (Microsoft.SharePoint)

    Returns a string array that lists all the users of a site, without listing them more than once, who receive alerts for list items.

  • EditPage in Site Actions is disabled (MOSS 2007)

     

    Have you ever tried to edit a page and found that the Edit Page was disabled or wouldn’t even show up under Site Actions.

    This may happen due to several reasons:

    1. By default all List's "NewForm.aspx", "EditForm.aspx" and "ViewForm.aspx" page's Site Action menu will show Disabled Edit Page menu item.
    2. If the page is currently checked-out by another user, it will show Disabled Edit Page menu item
    3. A master page customization may have hidden the site actions menu or a custom feature may have hidden the “Edit Page” menu item.

    So, how do we edit a page if we can’t see the “Edit Page” menu item and select it.

    A quick way to get any page into the Edit Mode is by adding “ToolPaneView=2” to the url.

    For e.g.:  If you are trying to get the default page at http://mysharepoint.corp.com/default.aspx in edit mode, change the url to: http://mysharepoint.corp.com/default.aspx?ToolPaneView=2. This will show you the same page in edit mode.

    Happy editing.

  • Adding SharePoint as IE Search Provider

    So you want to search the content on your enterprise’ SharePoint portal but your corporate intranet search isn’t integrated with your SharePoint implementation yet. Most organizations start with SharePoint as a collaboration tool that lives along with their other corporate intranet / internet platforms and isn’t fully integrated with their search platform.

    I am going to show you a simple way to search your SharePoint content no matter what site you are on assuming you are using IE as your browser. Trick lies with the IE search providers. As you probably know you can Manage Search providers on the IE browser. In the screen below, I have Google setup as my default search provider.

    image

    To create a custom IE Search provider:

    1. Go to : http://www.microsoft.com/windows/ie/searchguide/en-en/default.mspx

      image

    2. In the "Create your own" section:

      Note: To find out the correct URL for step 3, navigate to your SharePoint site and search for the term “TEST”. Copy and paste the url from your search results page.

    3. Install. You should see the new search provider “EMC SharePoint” show in your search providers.  

    image

    Enter a search term and try it out. Now you have the ability to search your SharePoint content directly from your browser.

  • Configuring Firefox to use Kerberos for SSO

    You can configure Firefox to use Kerberos for Single Sign-on. In order for this functionality to work correctly, you need to configure your web browser to send your Kerberos credentials to the appropriate KDC.The following section describes the configuration changes and other requirements to achieve this.

    1. In the address bar of Firefox, type about:config to display the list of current configuration options.
    2. In the Filter field, type negotiate to restrict the list of options.
    3. Double-click the network.negotiate-auth.trusted-uris entry to display the Enter string value dialog box.
    4. Enter the name of the domain against which you want to authenticate, for example, .example.com.
    5. Repeat the above procedure for the network.negotiate-auth.delegation-uris entry, using the same domain.

    image

  • Running multiple instances of Firefox

    Have you ever tried running a second instance of Firefox. With IE it is easy to open a second instance by opening a different window but even with different windows Firefox shares the same instance. That is because it uses the same profile for each Firefox window.

    If you are going to test an application by logging in with multiple user accounts, there is always a need to open multiple browser instances so you can impersonate different users. Here are the steps to run another instance of Firefox with a different profile.

    1. Start Firefox with the Profile Manager by opening a command prompt and running

    "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -no-remote -ProfileManager

    Note: Please check your Firefox path if the above path doesn't work. This is the path on my Win 7 x64 OS.

    2. Using the profile manager, we can create / rename / delete existing profiles. For now, we need to create a new profile. Select “Create Profile…”

    image

    3. This will start the “Create Profile Wizard”. Follow the wizard and create a new profile by giving it a unique name. I will name it “emctest” for this demo.

    image

    image

    4. That’s it. You can now run Firefox with the second profile “emctest”.

    Open a prompt and run "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -no-remote -P emctest

  • Stop the Annoying Beep in VMWare environment

    Have you ever used a VMWare image and experienced the annoying beep every time a dialog box is displayed or an error happens. It was driving me nuts for months.

    I tried turning off the VM speaker, attach the host sound card to the VM, change configuration settings but nothing seems to stop the beep.

    Guess what, there is a simple fix...

    Go to the command prompt on your VM and type

    C:\> net stop beep

     vmware_beep

    If you see the message above, Voila... there goes the Beep!

    Have a peaceful (no beep) day !

    FYI, you’ll have to do this every time the VM is rebooted.

    A permanent solution is to disable the hidden “Beep” device in device manager.

    Right-click “My Computer”/ Properties/ Hardware tab / Device Manager Button / “View” in the toolbar / select “show hidden devices” / expand the “Non-Plug and Play Driver” node / right-click “Beep” and click disable

  • Space in Filename changed to underscore when file is downloaded from SharePoint using IE

    Recently while doing a demo on versioning in SharePoint, I downloaded a file to my local machine, made some updates and uploaded it back to the site expecting to see a new version. However, I was surprised to see a second file in the library. Attributing this to “user” error, I decided to open the document through word, edit and save back and everything worked fine.

    I tried the steps again after the demo and realized when the file is downloaded using the “Send To –> Download a Copy” menu, the spaces in the filename are being converted to underscores by IE. (notice in the screenshot below, the filename has a space but the download dialog box converts it to “_”)

    sendto

    saveas 

    Note: The file is downloaded properly with spaces in the filename if you right click the file and select “Save Target As…”

    As I researched this further, I found this blog post entry by Sadalit Van Buren and several other blog posts that talk about the same issue.

    I also found a MS KB article (KB# 952730) where this issue documented. However, as per the KB article this is a IE7 issue. I am using Win 7 and IE 8 but still experience the same behavior so it hasn’t been fixed yet.

Powered by Community Server (Personal Edition), by Telligent Systems