Tuesday, December 14, 2010

Ways To Migrate SharePoint Metadata Term Store

Share/Save/Bookmark

How to migrate metadata term store in sharepoint 2010?
the next moment i try to get a solution for the above problem i get more questions raised....

is it gonna be on the same farm or different?
will migration maintain the consistency in GUID of termstores/terms?

so lets look what sharepoint 2010 got for us in this relevant.

TaxonomyClientService - This service exposes the methods that can help in migrating the
metdata at group level, on top of it, doesnt accept GUID as parameter.
seems like this is built more of the different purpose than it come in use for developers.

TaxonmySession looks promising in migrating termstores from one sitecollection to other sitecollection(on different webapps) like shown here. But got limitation when migration comes to different farms.

There is no OOB webservice that can get us the SPSite object that can be used in the above code.
So the only possibility i see is to get the termstore info to a defined xml and make this as a base and recreate terms on the other farms. I'm sure same thing can be achieved using powershell as well.
Did you just find a better way of doing this?? then please let me know.



  Subscribe

Monday, December 13, 2010

Migrate Sharepoint 2010 Metadata or Taxonomy

Share/Save/Bookmark

Below is the simple code that migrates metadata or taxonomy from one store(metadata service) to other on same farm.


public class TaxonomyUtility
    {
        public void MigrateTaxonomy(SPSite sourceSite,SPSite destinationSite,string srctermstoreName, string destermStoreName string termGroup, string termSet)
        {
            TaxonomySession srcTSession = new TaxonomySession(sourceSite);
            TaxonomySession desTSession = new TaxonomySession(destinationSite);
            TermStore srcTermStore = srcTSession.TermStores[srctermstoreName];
            TermStore desTermStore = desTSession.TermStores[destermStoreName];

            Group desGroup;
            TermSet desTermSet;
            Term desTerm;
            foreach (Group g in srcTermStore.Groups)
            {
                // Carry permisssions
                //foreach (SPAce groupManager in g.GroupManagers)
                //{
                //}

                desGroup = desTermStore.CreateGroup(g.Name);
                foreach (TermSet tSet in g.TermSets)
                {
                    desTermSet = desGroup.CreateTermSet(tSet.Name, 1033);
                    foreach (Term t in tSet.Terms)
                    {
                        desTerm = desTermSet.CreateTerm(t.Name,1033);
                        getLabels(t,desTerm);
                        getTermsRecursive(t,desTerm);
                    }
                }
            }
            desTermStore.CommitAll();
        }

        public void getTermsRecursive(Term srcTerm, Term destTerm)
        {

            if (srcTerm.Terms.Count > 0)
            {
                foreach (Term sTerm in srcTerm.Terms)
                {
                    destTerm = destTerm.CreateTerm(sTerm.Name, 1033, sTerm.Id);
                    getLabels(sTerm,destTerm);
                    getTermsRecursive(sTerm, destTerm);
                }
            }
            else
            {
                return;
            }
        }

        public void getLabels(Term srcTerm,Term desTerm)
        {
            foreach (Label l in srcTerm.Labels)
            {
                desTerm.CreateLabel(l.Value, 1033, l.IsDefaultForLanguage);
            }
        }
    }
}

Voila ...u did it ;-)
Other ways of migrating metadata term store in sharepoint 2010 and their limitations are discussed here.

  Subscribe

Saturday, November 27, 2010

HTTP Module in sharepoint

Share/Save/Bookmark

In one of the scenario i got to replace the application page(new.aspx) with my custom application page(customnew.aspx). so quickly i got the new application page but then started wondering how to link this page to sharepoint without adding a new link but just replacing the existing link?
here is one of the solution implementing IHTTPModule..

public class Class1 : IHttpModule
    {
        public void Init(HttpApplication app)
        { 
            app.PreRequestHandlerExecute +=new EventHandler(app_PreRequestHandlerExecute);

        
        }
        void app_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            if(context.Request.Path.Contains("/_layouts/new.aspx"))
            {
                string url = "customnew.aspx";
                if (!context.Request.QueryString.Equals("{}"))
                {
                    url = url + '?' + context.Request.QueryString;
                }
                context.Response.Redirect(url);
            }
        }
        public void Dispose()
        {
        }
}


Add the reference of this new httpmodule in web.config under HttpModules.

  Subscribe

Thursday, November 4, 2010

Programmatically read MetaData Store

Share/Save/Bookmark

Here is the code that you can reuse to read the complete managed metadata store or taxonomy in SharePoint for a specific site collection.
Below code writes the metadata to a xml file following a very basic schema also presents it on console in a formatted style.

For basic understanding, the classes or the taxonomy hierarchy(new in SharePoint) is like below

Taxonomy Session 
            |
    Term Store
            |
       Group
            |
      TermSet
            |
        Term

Microsoft.SharePoint.Taxonomy is the dll that's used here to play around with SharePoint taxonomies.


namespace MetaDataReader
{
    class Program
    {
        static string fmt = "---------"; // used for formatting the hierarchy while displaying on console
        static XmlTextWriter writer = new XmlTextWriter("metadataStore.xml", null);
        public static void Main(string[] args)
        {
            try
            {
                SPSite site = new SPSite("http://mywebappurl");
                TaxonomySession txSesssion = new TaxonomySession(site);
                writer.WriteStartDocument();
                foreach (TermStore store in txSesssion.TermStores)
                {
                    Console.WriteLine("TermSTORE : " + store.Name);
                    writer.WriteStartElement("TermStore");
                    writer.WriteStartElement("Name");
                    writer.WriteString(store.Name);
                    writer.WriteEndElement();
                  
                    foreach (Group g in store.Groups)
                    {
                        Console.WriteLine("...TermGROUP : " + g.Name);
                        writer.WriteStartElement("TermGroup");

                        writer.WriteStartElement("Name");
                        writer.WriteString(g.Name);
                        writer.WriteEndElement();

                        foreach (TermSet tSet in g.TermSets)
                        {
                            Console.WriteLine("......TermSET : " + tSet.Name);
                            writer.WriteStartElement("TermSet");

                            writer.WriteStartElement("Name");
                            writer.WriteString(tSet.Name);
                            writer.WriteEndElement();

                            foreach (Term t in tSet.Terms)
                            {
                                Console.WriteLine(fmt + "TERM :" + t.Name);
                                writer.WriteStartElement("Term");

                                writer.WriteStartElement("Name");
                                writer.WriteString(t.Name);
                                writer.WriteEndElement();
                                getTermsRecursive(t);
                                writer.WriteEndElement();
                            }
                            writer.WriteEndElement();
                        }
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
                writer.WriteEndDocument();
                writer.Close();
            }
            catch (Exception ex)
            {//Do not swallow ;}
        }

        public static void getTermsRecursive(Term t)
        {
            if (t.Terms.Count > 0)
            {
                fmt += "---";
                foreach (Term sTerm in t.Terms)
                {
                    Console.WriteLine(fmt + "TERM :" + sTerm.Name );
                    writer.WriteStartElement("Term");
                    writer.WriteStartElement("Name");
                    writer.WriteString(sTerm.Name);
                    writer.WriteEndElement();
                  
                    getTermsRecursive(sTerm);
                    writer.WriteEndElement();
                }
            }
            else
            {
                fmt.Remove(fmt.Length-3);
                return;
            }
        }
    }
}



 Subscribe

Monday, October 4, 2010

Configure BCS in Sharepoint 2010

Share/Save/Bookmark

Lets get started with BCS in sharepoint 2010 with a small demo thats compiled as step by step instruction:

1. Open any MOSS site using Sharepoint Designer 2010

2. Select External content Types on left menu under Site Objects



3. Click on External Content Type, (seen on ribbon) to create a new one

4. Provide name and select  click here to discover external system where the data is residing to add external data source system





5. Click on Add connection to add a data source. Here our data source type is SQL server as the external data is a table in SQL server.





6. Provide server properties to connect to sql server



7. After successfully connecting to the new external data source through the data connection, add operations(read,insert,update,delete) by right clicking on the table(here EMP) that needs to be pulled through BCS.

8. Create New Read List Operation


9. Run through the wizard where operation parameters (Filter/Return) can be specified. Note the errors and warnings that are self explanatory for which, properties of each element can be changed accordingly to resolve them.



10.   For any external content type to be of use, it should at least have the read list and read item operations created. The same information can be seen in the External Content Type Operations panel.



11.   Now Create Read Item operation(follow steps 8 & 9)

12.   Save

13.   Open CentralAdmin to see the new External Content Type that is created




14.   Click on Set Object Permissions or Set Metadata Store Permissions to provide relevant permissions to the users who ever should access the external data pulled out by the external List, created based on the External content type. Note that missing this step would give Access Denied to Business Connectivity Services when tried to view external list. 



15.   Create External List using designer to see the output that we are waiting for. External list can also be created through the site.




  16.   Navigate to the External list (here DemoExCTList) in the site and here is the external data in sharepoint.





  Subscribe

Saturday, September 25, 2010

Add system.serviceModel to web.config

Share/Save/Bookmark

Here is the code built on the Sharepoint API that will add WCF/web service configuration, system.serviceModel to web.config.


            SPWebConfigModification item = new SPWebConfigModification();
            item.Name = "system.serviceModel";
            item.Value = " <>... ";
            item.Path = "configuration";
            item.Sequence = 0;
            item.Owner = "owner";
            item.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
            try
            {
                SPWebApplication parent = properties.Feature.Parent as SPWebApplication;
                if (parent != null)
                {
                    parent.WebConfigModifications.Clear();
                    // To know why i have used Clear(), read this
                    parent.Farm.Services.GetValue().WebConfigModifications.Clear();
                    parent.WebConfigModifications.Add(item);
                    parent.WebService.ApplyWebConfigModifications();
                    parent.Update();

                }
            }

Same code can be used to add any entires to web.config by giving respective path.
To know other approaches of modifying web.config read Ways to Modify web.config

  Subscribe

Tuesday, September 14, 2010

Ways to modify web.config

Share/Save/Bookmark


All about modifying web.config in Sharepoint environment.

Following are the different approaches that i have figured out that can possibly be used to modify web.config:

1. Rich API SPWebConfigModification
2. Declarative approach by having the changes in webconfig.*.xml
3. using ASP.net configuration
4. Modifying it as just another xml file

1. SPWebConfigModification

Sharepoint api is compiled so well that the changes that are written to web.config
can be easilty removed as well. A code sample to add the WCF/webservice entry using this API can be found here.

2.Declarative approach

When we are so used to do everything as a xml file. Ofcourse its the easiest way of
implementing things in sharepoint and so in this case.

In this approach the modifications to the web.config can be defined in a XML file
that will named as webconfig.*.xml,placed in 12\config folder.
When a  new webapplication is getting created sharepoint looks up for the files with pattern webconfig.*.xml
under 12/config and merges those changes with the web.config
Please note that this works only for new webapps and it impacts all webapps but not a specific
webapp.

To have these new changes to be included in web.config for existing webapp the following stsadm command
can be run:
stsadm -o copyappbincontent

3..Net Configuration API
All the elements/nodes and attributes of web.config are implemented as various classes and properties.
This will be a large chunk of code once you are used to SPWebConfigModification API.
Below is the code sample using Configuration class that will modify a entry in appSettings section.

public void Modify(string key, string value)
{

Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");

AppSettingsSection appSettingsSection = (AppSettingsSection)configuration.GetSection("appSettings");

   if (appSettingsSection != null)

   {

       appSettingsSection.Settings[key].Value = value;

       config.Save();

   }

}


4.As an xml file.
Best way to parse the xml files is to use XMLReader/XMLTextReader,XMLWriter/XMLTextWriter,XPathNavigator
but it would be a pain to write the changes as each node and attribute.
Again it depends on the requirement what to add/modify?

Sample code:

                XmlDocument document = new XmlDocument();
                document.Load(file);// file - web.config opened on FileStream

                XmlNode node = document.SelectSingleNode("/configuration");
                node.InnerXml = node.InnerXml + serviceModelChange;
                document.Save(file);

more details can be found at http://www.west-wind.com/Weblog/posts/2423.aspx


I summarize that SPWebConfigModification is the best/safe way of modifying web.config programmatically.

  Subscribe

Friday, September 10, 2010

SPWebConfigModifications throws exception all time

Share/Save/Bookmark


{Expression must evaluate to a node-set.}
{'' is an invalid expression}

Are you victim of the above error messages?
Is SPWebConfigModification throwing exceptions all the time when modifying the web.config?
And you think it should not give that message for the flawless code that you have written?
then root cause could be because of the corrupted entries in webconfigmodification collection that still persist.
So how to get rid of them?

Call SPWebApplication.WebConfigModifications.Clear() before adding the entries(SPWebApplication.WebConfigurations.Add(EntryItem))

In a very special case of mine the above call didn't succeed and i have to call
SPWebApplication.Farm.Services.GetValue().WebConfigModifications.Clear() too.

So what did we really do just now, The call SPWebApplicaiton.WebConfigModifications.Clear()
cleared the bad entries on the current webapp where we are trying to add the entries.But there
could be bad entries still existing on the other webapps because of which error might be thrown though
there is nothing wrong in your code.
So to clear out all the corrupted entries we have called SPWebApplicaiton.Farm.Services.GetValue().WebConfigModifications.Clear()
Internally this call will reload all the web.config entires and modifies the current webapp
web.config to include the new changes.


  Subscribe

Thursday, June 24, 2010

Deployment Tools for Sharepoint

Share/Save/Bookmark




Deployment Tools for Sharepoint

stsdev

generate Visual Studio project files and solution
files to facilitate the development and deployment of templates and
components for the SharePoint


Wspbuilder

WSP) creation tool for WSS 3.0 & MOSS 2007


SPVisualDev

to develop features and artifacts with Visual Studio
2008 and many more features


Share Infopath Forms

Makes infopath forms
deployment easy


Manage configuration modification feature

Feature to manage the configuration modifications



Subscribe

Wednesday, June 23, 2010

MOSS Standard DevelopmentTools

Share/Save/Bookmark





Standard Development Tools for Sharepoint

Reflector

Explore and analyze compiled .NET assemblies, viewing
them in C#, Visual Basic, and IL


GhostDoc

free Visual Studio extension that automatically
generates XML documentation comments for methods and properties based on
their type, parameters, name, and other contextual information


DumySMTP

Command line utility that simulates a
smtp server.


CAML Query Builder

will help in build, test
and execute CAML Queries


Fxcop

is a free static code analysis tool
from Microsoft that checks .NET managed
code assemblies for conformance to Microsoft's .NET Framework
Design Guidelines


SPdisposecheck

help you to check your assemblies that use the SharePoint API so that
you can build better code. It provides assistance in correctly disposing of
certain SharePoint objects to help you follow published best practice. This
tool may not show all memory leaks in your code


Resource Refactor               

easy way to extract hard coded strings from the code
to resource files


SharePointLoggingSpy

allows real time diagnostics of multiple servers in a sharepoint farm using a single console view


WSS/MOSS Log file reader

View, search and filter SharePoint ULS log files
directly from within Central Administration


AD Explorer

use AD Explorer to easily navigate an AD database


XML NotePad

provides a simple intuitive user interface for
browsing and editing XML documents


WinDiff               

Graphical file comparison tool similar to Beyond
Compare


SharePoint Data Population Tool

a capacity planning and performance testing tool that populates
data for testing SharePoint deployments.


Resharper

provides solution-wide error highlighting
on the fly, instant solutions for found errors, over 30 advanced
code refactorings, superior unit testing tools,
handy navigation and search features, single-click code formatting and
cleanup, automatic code generation and templates,


Snippet Compiler




Sandcastle help File builder

used for creating MSDN-style documentation from .NET assemblies
and their associated XML comments files.


Sandcastle

Documentation compiler for managed assemblies


CKS

is a set of best practices, templates, Web Parts,
tools, and source code


Fiddler

 to inspect allHTTP(S) traffic,
set breakpoints, and "fiddle" with incoming or outgoing data


Procmon

Process monitor tool


Stsadm.webconfig

Make SharePoint web config
modifications using a config file, rather than
having to hard-code static strings in a class file


MOSS Feature Generator

includes Site Columns, Content Types and ListTemplates (including schema.xml
and forms)



allows a developer to explore the scopes and managed properties of a
given SharePoint Search SSP. Also builds queries in either Keyword or SQL
Syntax, submit those queries and examine the raw web service results




Subscribe