Sandeep's Blog: This blog is no longer updated, please visit http://sandeepnakarmi.com.np for latest posts

September 30, 2009

Host WCF Service in SharePoint

Filed under: Sharepoint 2007 — Tags: , , — sandeep nakarmi @ 6:57 AM

Recently, I had been working on how to get a WCF service hosted in SharePoint. The requirement was to host a WCF service in SharePoint and a custom webpart would access the service. So in this post, I will illustrate how to host WCF in SharePoint.

Download SourceCode

Environment:

  • Microsoft SharePoint Server 2007
  • Visual Studio 2008
  • Visual Studio Extensions for WSS 3.0 v1.3 March CTP

1)      First let’s create a WCF service and its implementation. For this, create a project of type WCF Service Library. Name it SPService. This will create a default interface “IService.cs” and its implementation “Service.cs”. 

2)      Delete the defaut IService.cs and Service.cs files. 

3)      Add a new item of type WCF Service named SPService

4)      Modify the ISPService interface as shown below.

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace SPService
{
    // NOTE: If you change the interface name "ISPService" here, you must also update the reference to "ISPService" in App.config.
    [ServiceContract]
    public interface ISPService
    {
        [OperationContract]
        string SayHello(string name);
    }
}

5) Modify SPService class as shown below.

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;

namespace SPService
{
    // NOTE: If you change the class name "SPService" here, you must also update the reference to "SPService" in App.config.
    [AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
    public class SPService : ISPService
    {
        #region ISPService Members

        public string SayHello(string name)
        {
            return string.Concat("Hello ",name);
        }

        #endregion
    }
}

6) Modify the web.config file as shown below.  

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicBinding">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Ntlm" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <services>
      <service behaviorConfiguration="NewBehavior" name="SPService.SPService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicBinding"
          name="basicBindingEndPoint" contract="SPService.ISPService" />
<!--<host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/SPService" />
          </baseAddresses>
        </host>-->      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="NewBehavior">
          <serviceDebug />
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

7)      Sign the project .

sign the project  

8)      Now run the project. This will bring up the WCF Test Client wizard. Test remote method by invoking the method. It should respond you as shown below.

WCF Test Client

WCF Test Client

9)      Now create a SharePoint project of template type Empty. Name it “SharePoint.WSP”. Select the option to Deploy it to GAC.

 GAC 

10)   Create the folders “RootFiles”, “ISAPI”, “SPService” in the structure as shown below. We will host the service in the folder “SPService”.

Soln

11)    Rename the “App.config” file in project SPService to “web.config”. Now in project, SharePoint.WSP, select the folder SPService and select to add an existing item. Navigate to web.config file and add it as a link.

 web config link 

12)   Similarly, add a link to assembly SPService.dll also.

 assembly link 

13)   Then in folder SPService, add an item of type “SPService.svc”. Modify the file to following. 

<%@ Assembly Name="SPService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ee2ed923e46a9fcd" %>
<%@ ServiceHost Service="SPService.SPService,SPService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ee2ed923e46a9fcd" %>

You can retrieve the full assembly signature using a reflector.

 reflector 

14)   Go to the WSP view (View – > Other Windows -> WSP View). The manifest.xml file should look like below.

 manifest 

15)   Now set site url in the properties of project SharePoint.WSP where the solution will be deployed. Then deploy the solution.

prop 

16)    Now try to access the service with the url http://sandeep-pc/_vti_bin/spservice/spservice.svc . At this point you may receive an VirtualPath error like below.

 err 

Exception: System.ArgumentException: virtualPath
at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) 

at Microsoft.SharePoint.ApplicationRuntime.SPRequestModule.IsExcludedPath(Stri­ng virtualPath) 
at Microsoft.SharePoint.ApplicationRuntime.SPVirtualPathProvider.FileExists(St­ring virtualPath) 
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceA­vailable(String normalizedVirtualPath) 
at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(St­ring relativeVirtualPath)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest() 
at System.ServiceModel.Activation.HttpHandler.ProcessRequest(HttpContext context)
 

The problem here is that SPVirtualPathProvider isn’t coded to handle URLs that start with ‘~’;

        See workaround references for this:

17)    As a workaround, follow the procedure below.  

18)   Add a folder named WCFSupport, in the project SharePoint.WSP. In this folder, add a new class file named “WCFVirtualPathProvider” and add the following lines of code.

class WCFVirtualPathProvider : VirtualPathProvider
    {
        public override string CombineVirtualPaths(string basePath, string relativePath)
        {
            return Previous.CombineVirtualPaths(basePath, relativePath);
        }

        public override System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedType)
        {
            return Previous.CreateObjRef(requestedType);
        }

        public override bool DirectoryExists(string virtualDir)
        {
            return Previous.DirectoryExists(virtualDir);
        }

        public override bool FileExists(string virtualPath)
        {
            // Patches requests to WCF services: That is a virtual path ending with ".svc"     
            string patchedVirtualPath = virtualPath;
            if (virtualPath.StartsWith("~", StringComparison.Ordinal) &amp;&amp;
              virtualPath.EndsWith(".svc", StringComparison.InvariantCultureIgnoreCase))
            {
                patchedVirtualPath = virtualPath.Remove(0, 1);
            }
            return Previous.FileExists(patchedVirtualPath);
        }

        public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath,
                   System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
        {
            return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }

        public override string GetCacheKey(string virtualPath)
        {
            return Previous.GetCacheKey(virtualPath);
        }

        public override VirtualDirectory GetDirectory(string virtualDir)
        {
            return Previous.GetDirectory(virtualDir);
        }

        public override VirtualFile GetFile(string virtualPath)
        {
            return Previous.GetFile(virtualPath);
        }

        public override string GetFileHash(string virtualPath, System.Collections.IEnumerable virtualPathDependencies)
        {
            return Previous.GetFileHash(virtualPath, virtualPathDependencies);
        }

        protected override void Initialize()
        {
            base.Initialize();
        }
    }

19)   Create another class file named “WCFVPPRegModule” and add the following lines of code.

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Hosting;

namespace SharePoint.WSP.WCFSupport
{
    class WCFVPPRegModule : IHttpModule
    {
        #region IHttpModule Members

        public void Dispose()
        {
            // do nothing
        }

        public void Init(HttpApplication context)
        {
            if (!wcfProviderInitialized)
            {
                lock (locker)
                {
                    WCFVirtualPathProvider wcfVPP = new WCFVirtualPathProvider();
                    HostingEnvironment.RegisterVirtualPathProvider(wcfVPP);
                    wcfProviderInitialized = true;
                }
            }
        }

        #endregion

        static bool wcfProviderInitialized = false;
        static object locker = new object();
    }
}

 
20)    Now after we have created the HttpModule, we need to register this in the web.config file of the root web application. This can be done manually or by creating a feature receiver which will apply the modification to the web.config file. I am going to use the later one. These feature receiver will be scoped at WebApplication and enabling this feature will apply the necessary modification to get the service running.  

21)   Add a new class file named “WCFSupportReceive.csr” in the folder “WCFSupport” and change it to below.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Security;

namespace SharePoint.WSP.WCFSupport
{
    [Guid("1860F007-6E2B-4a95-A8B6-371AB8F6B012")]
    class WCFSupportReceiver : SPFeatureReceiver
    {
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
            if (webApp != null)
            {
                foreach (ModificationEntry entry in Entries)
                {
                    webApp.WebConfigModifications.Add(CreateModification(entry.Name, entry.XPath, entry.Value));
                }
                SPFarm.Local.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
            }      
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
            if (webApp != null)
            {

                foreach (ModificationEntry entry in Entries)
                {
                    webApp.WebConfigModifications.Remove(CreateModification(entry.Name, entry.XPath, entry.Value));
                }

                SPFarm.Local.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
            }    
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties){}

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties){}
      
        private struct ModificationEntry
        {
            public string Name;
            public string XPath;
            public string Value;
            public ModificationEntry(string Name, string XPath, string Value)
            {
                this.Name = Name;
                this.XPath = XPath;
                this.Value = Value;
            }
        }

private ModificationEntry[] Entries = {
              new ModificationEntry(
                  "add[@name='WCFVPPRegModule']",
                   "configuration/system.web/httpModules",
                   @"<add name=""WCFVPPRegModule"" type=""SharePoint.WSP.WCFSupport.WCFVPPRegModule,SharePoint.WSP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1948038ea0d4e8e4"" />"
                   )
            };

        public SPWebConfigModification CreateModification(string Name, string XPath, string Value)
        {
            SPWebConfigModification modification = new SPWebConfigModification(Name, XPath);
            modification.Owner = WebConfigModificationOwner;
            modification.Sequence = 0;
            modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
            modification.Value = Value;
            return modification;

        }
        private const string WebConfigModificationOwner = "SharePoint.WSP";
    }
}

Note: The ModificationEntry[] is used to define the set of configurational changes needed to be made to web.config file. For now, we just need to register a http module, so there is just one entry defined. Use reflector to find the full signed signature of the assembly. Make sure that the PublicKeyToken matches to that of the assembly.

22)   Then go to WSP View (View – > Other Windows-> WSP View). This is how it looks in WSP View.

 wsp 

23)   Change the feature.xml of the WCFSupportReceiver as shown below.

<?xml version="1.0" encoding="utf-8"?>
<Feature Id="1860f007-6e2b-4a95-a8b6-371ab8f6b012"
         Title="WCFSupportReceiver"
         Description="Enable WCFSupport for SPService"
         Scope="WebApplication"
         Version="1.0.0.0"
         Hidden="FALSE"
         ReceiverAssembly="SharePoint.WSP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1948038ea0d4e8e4"
         ReceiverClass="SharePoint.WSP.WCFSupport.WCFSupportReceiver"
         DefaultResourceFile="core"
         xmlns="http://schemas.microsoft.com/sharepoint/">
  <ElementManifests />
</Feature>

The key things to note here are:

  • The feature is scoped at WebApplication since we are making change in the web.config file of the web application. Also this means that in each web application, this feature has to be activated in order to acecess WCF Service.
  • Use the reflector to get the full assembly signature for the ReceiverAssembly. 

24)   Now everything set, deploy the project. Go to “Manage Web Application Features” of the web application into which the solution was deployed. Activate the WCFSupportFeaure feature if it  is not yet activated. You can also verify this by opening web.config file of web application and see for the entry for “WCFSupportReceiver”.

 config

 25)   Navigate to the url again: http://sandeep-pc/_vti_bin/spservice/spservice.svc .You should see a response like below.

 25 

26)   So the service has been hosted. To test the service, following the procedures below.

  1. Create a console application.
  2. Add the service reference to the above hosted service.
  3. Modify the client code to the following.

using System;
using System.Collections.Generic;
using System.Text;

namespace TestClient
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Service.SPServiceClient client = new TestClient.Service.SPServiceClient();
                string response = client.SayHello("sandeep");

                Console.WriteLine(string.Format("Response from server: {0}", response));
            }
            catch (Exception exc)
            {
                Console.WriteLine(string.Format("Error:{0}", exc.Message));
            }
            Console.ReadLine();
        }
    }
}

This is the output of the client application.

 output

 I would suggest you to have a look at the following references that I went through to get this done.

References:

September 23, 2009

Create a simple WCF Service and Client application.

Filed under: WCF — Tags: — sandeep nakarmi @ 8:04 PM
In this post, I will demonstrate how to create a simple WCF client and service console application. This post is intended for beginners who can follow the following steps to get a basic WCF Service up and running.

Minimum requirement: .Net framework 3.0.

Download SourceCode

For this, we will create three projects.

  • A service class Library: This library will contain the Service Contract, Operation Contracts and Data Contracts that will be shared by both WCF service and client applications.
  • WCF service application: A console application that will host the service.
  • WCF client application:  A console application that will call a remote wcf service method and display the response from the service.

Lets start by creating the service class library.

1) Create a class library application and name it WCFServiceLibrary.

2) Delete the default Class1.cs file and add new interface file named “IService.cs”.

3) Add reference to the Syste.ServiceModel in the project and then add the corresponding using directives.  Then make the following change in the IService interface.       

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace WCFServiceLibrary
{
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        int GetProduct(int x, int y);
    }
}

Here we add a definition for method GetProduct which will return the product of two numbers passed in as parameter.

4) Add another cs file named “Service.cs”. Implement the “IService.cs” interface and its method. 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WCFServiceLibrary
{
    class Service : IService
    {
        #region IService Members
        public int GetProduct(int x, int y)
        {
            return x * y;
        }
        #endregion
    }
}

5) Now since we have the service library with a method exposed, lets create a service application now.

6) Create a console application named “WCFService” and add reference to the WCFServiceLibrary project. Also add reference to System.ServiceModel. Add the following using directive.

using System.ServiceModel
using WCFServiceLibrary;

7) Lets now create a configuration file for the WCF Service. This configuration file will define the Endpoint binding, endpoint address and behaviors for the service. Add a new app.config file to the WCFService project.

8) Open the WCF Service Configuration Editor, Tools -> WCF Service Configuration Editor. Then select the app.config file created in above step. You can now follow the wizard to create the binding for the service.

8.a) Since we are creating a config file for service, select the “Create a New Service” link.

8.b) In Service Type step,  browse to the WCFServiceLibrary.dll and select the type “WCFServiceLibrary.Service”. 

         8_b

        8_b_2

8.c) Click Next, and you will see the Contract for the service. 

        8_c

8.d) Click next; here you need to select the mode you want to use for binding, Http, Tcp, Named Pipes etc. Select Tcp and click next. Now set the endpoint address like below: 

        8_d

       8_d_2

 Click Next and finish the wizard.

8.e) Then go to “Endpoints” node and give the name for configuration as TcpBinding. Then save the project.

       8_e

8. f) Select root Services node and then create a binding configuration by selecting “(Default )Click to create”. Supply the name of the binding as NetTcpBinding. With rest set to default, save the config file.

9) Now add the following lines of code to the program.cs file of WCFService project.                                         


namespace WCFService
 {
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
               ServiceHost host = new ServiceHost(typeof(WCFServiceLibrary.Service));
                host.Open();
                Console.WriteLine(string.Format("The service is running....."));
            }
            catch (Exception exc)
            {
                Console.WriteLine(string.Format("Error: {0}",exc.Message));
            }
            Console.ReadLine();         
        }
    }
 }

                                                                                                                                                                                                          When you run the service you should see a console open up with message “The service is running…..”  

10) Now since the service is running, lets create a client to access the remote service. Create a console application named “WCFClient” and add the reference to the System.ServiceModel, WCFServiceLibrary project. Then add the following using directives in the program.cs file.


using System.ServiceModel;
using System.ServiceModel.Channels;
using WCFServiceLibrary;

11) Now let’s create the app.config file for the client. Again we are going to use the “WCF Service Configuration Editor”. The catch here is that, now we can just specify the app.config file of the service application and it will automatically generate the settings for the client according to the service. So follow the steps below to get this done.

  • Add a new app.config file to the WCFClient application.
  • Open the WCF Service Configuraiton Editor and select to open this app.config file.
  • Select the Client node in the left tree and on the right side you will see a link label Create a New Client. Click it.
  • Select the “From service config” option and browse to the app.config file of the WCFService application which we created at the end of step 8.
  • Proceed by selecting next, and provide “ClientTcpBinding” as name when you are prompted for the client configuration name. Proceed to finish and then save the config file.

         Remove the <identity> section if exists. The configuration file should look like this.


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
      <bindings>
          <netTcpBinding>
              <binding name="NetTcpBinding" />
          </netTcpBinding>
      </bindings>
      <client>
    <endpoint address="net.tcp://localhost:8080/Service" binding="netTcpBinding"
   bindingConfiguration="NetTcpBinding" contract="WCFServiceLibrary.IService"
         name="ClientTcpBinding">             
    </endpoint>
     </client>
  </system.serviceModel>
</configuration>

12) Now add the following codes of line to the program.cs file of WCFClient project.

namespace WCFClient
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
ChannelFactory<WCFServiceLibrary.IService> factory = new ChannelFactory<IService>("ClientTcpBinding");
                factory.Open();
                IService remoteService = factory.CreateChannel();
                int x=4;
                int y=4;
                int retVal = remoteService.GetProduct(x, y);

                Console.WriteLine(string.Format("The product of {0} and {1} is {2} ",x,y,retVal));
            }
            catch (Exception exc)
            {
                Console.WriteLine(string.Format("Error:{0}",exc.Message));
            }
            Console.ReadLine();
        }
    }
}

13) Now run the WCFService application first. Right Click WCFService->Debug->Start New Instance.

        13

14) Run the WCFClient project with WCFClient->Debug->Start New Instance. You should see the following output.

        14

So here we learned how to create a WCF Service, host it in console application, program the client to access this remote service exposed method. We also learned how to use the WCF Service Configuration Editor tool which saved us from manually editing the configuration file and saved our time. 

Happy Coding :-)

September 13, 2009

VSeWSS Service Error: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

Filed under: VseWss 1.3 March CTP — sandeep nakarmi @ 10:11 AM

I was working on VseWSS 1.3 March CTP version and i was trying to add the Enterprise logging ability in sharepoint web parts. Since in VseWSS 1.3 has the feature that the referenced assemblies are also included in package and are installed in GAC, i opted with this version, other wise i was working with version 1.2.

So in order to add the logging feature, i just created a new sharepoint web part project and referenced the following enterprise library references in the project.

  • Microsoft.Practices.EnterpriseLibrary.Logging.dll
  • Microsoft.Practices.EnterpriseLibrary.Common.dll
  • Microsoft.Practices.ObjectBuilder2.dll

Having created a simple hello world webpart, i tried to deploy the project. But just then, this error occurred.

Error 1 VSeWSS Service Error: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

Log file written to: C:\Windows\system32\config\systemprofile\AppData\Roaming\Microsoft\VSeWSS 1.3\VSeWSS1.3 service.log 

After searching a bit on the web, i was very disappointed that this is yet another problem in version VseWSS 1.3. The only solution for this was to add the assemblies to GAC manually, clean the project and perform iisreset. Then only it worked.

See the following links for references:

 Well i am looking for alternatives as a work around for this. May be the post build script solution suggested in the link above. :-(

September 10, 2009

How to create a custom site template with auto created list using visual studio extension for wss

Filed under: VseWss 1.3 March CTP — sandeep nakarmi @ 8:12 AM

 In this article, I will show you in steps how you can create a custom site definition with an auto created list that can be deployed easily as a solution file to sharepoint. 

I am using Visual Studio 2008 extension for WSS 3.0 v1.3 March CTP. You can follow these steps using VSEWSS v1.2 as well.

1) Create a new project of type “Sharepoint “ in visual studio. Select “Blank Site Definition”. Name the project as “DemoSite”. 

2) This will create a default “onet.xml” , “default.aspx” file and feature receiver files. Before working with “onet.xml” file, it is very necessary to come in terms with the structure of the onet.xml file. 

a

3) Delete the “SiteProvisioning Handler” folder. This is not needed for the purpose of this article. Use this if you need to add custom code and behavior when the site is being provisioned. 

4)  Go to “View->Other Windows->WSP View”. In the WSP view, you will see an additional file named “webtempDemoSite.xml”. Open this file. This file contains the configuration details of the “DemoSite”. You can have a look at the “webtemp.xml” file for a reference in location below: 

a

C:\Program Files\Common Files\microsoft shared\Web Server Extensions\12\TEMPLATE\1033\XML 

5) Make the following change to the file.

a

6) f you want to see the effect of the above change, build the project and select deploy (Right click-> Build and Right click – > Deploy).

7) Try creating a new site from SharePoint and you will see a new category and template to select while creating a site. Notice the description, template category and template.

a

8) Fill in the title, description, url and other parameters and create the site. 

a

9) Since we chose to create a “blank site definition” there are no lists created. So, let’s now try to add a document library that will be auto created when a site is created from this site definition. In the “DemoSite” project,  add a new item of type Sharepoint-> ListInstance and name it “DocumentLibraryInstance”.

a

10) Creating a ListInstance, will create the list automatically when the site is created. In the popup wizard select “Document Library”.

a

11) Make the following modifications to the newly created instance.xml file.Note the changes to the Title, url and description. Also, I want to show the created library to quick launch so I have added the OnQuickLaunch attribute to True

a

12) The list instance will be deployed to SharePoint as a feature. You can have a look at the SharePoint feature xml file in the WSP view. The feature will be deployed in “Web” scope. 

a

13) Go to WSP view -> DemoLib->Feature.xml. See that the scope of the feature is “Web”.

a

14) Copy the FeatureId.  In DemoSite->onet.xml file, find the node “WebFeatures” of configuration node with and add a new Feature node with the copied id like below. Since the fature is “Web” scoped, we place the feature in “WebFeatures” element. This will activate the web feature when site is created, and activating this feature will create the list instance document library DemoLib.

a

15) Create a new site collection of type DemoSite. See that now, creating a new site auto created a new document library DemoLib.

a

16) Go to SiteActions-> Site Settings – > Site Features to see the DemoLib feature installed and activated.

a

17) Also following files will be created if you have a look at the SharePoint 12 hive. Those files were created when we deployed the project into SharePoint.  The entire project is deployed as a solution file (WSP) into SharePoint. You can view this in the Solution Management section in central administration site.

C:\Program Files\Common Files\microsoft shared\Web Server Extensions\12\TEMPLATE\1033\XML \ webtempDemoSite.xml

C:\Program Files\Common Files\microsoft shared\Web Server Extensions \12 \ TEMPLATE \ SiteTemplates \ DemoSite 

a

 You can retract or revoke your solution directly from this UI.

How to create a custom site definition with a custom master page that can be easily deployed as a solution to SharePoint.

Filed under: Sharepoint 2007, VseWss 1.3 March CTP — sandeep nakarmi @ 7:57 AM

In this walkthrough topic, I will demonstrate you how to achieve the following things:

  • Create a custom site definition.
  • Specify your own master page to be used for that site.
  • Create a solution file(wsp) that can be easily deployed to sharepoint.

In this artice, I will not cover how to create a master page. I will just demonstrate how you can create a feature to deploy the custom master page and apply it to a site.

If you want to know about the types of master pages, creating one yourself in detail, follow this 6 part series on Master Page.

http://sharepointmagazine.net/technical/development/introduction-to-master-pages

The main objective of this post is not how to create a master page, but how you can create your custom site definition that has custom master page and deploy into SharePoint as a solution.

I am using Visual Studio 2008 Extension for WSS 3.0 v1.3 March CTP. You can use earlier version of this tool or use other tool like WSPBuilder. You will have to know how to use the tool.

Since I will not be creating a master page, I am going to use one of the sample master pages  provided by Microsoft. Download extract the master pages. I will be using the “block” sample master page.

So let’s start.

1)  Create a new project of type SharePoint and use the template “Team Site Definition”.

a

2) The template will create the default templates that are necessary to create a team site.There is also a folder named “Site Provisioning Handler”. We will not be using this for now so you can delete this folder.

a

3) This is how it looks in the WSP view (View->Other windows->WSP View).

a

4) Inside Site Definition folder, create a folder named “MasterPage” and add the master page file “block_lay4_blue.master” which was extracted from sample master pages. I have renamed the master page file to “customsite.master”.

a

5) In the WSP view, make the following changes to the elementManifest.xml file. Here we specify that the master page is to be added to the master page gallery of the site.

a

6) Next specify the folder where the images for the custom master page will be deployed in sharepoint. Normally this will be in “12\TEMPLATE\IMAGES” folder. So we create a folder named “CustomSite” in this path and put our images there. Create a hierarchy as shown below and put there the image files. Since the master page I chose was of theme blue, I chose the images only relevant for this mater page.

a

7) Similarly create a folder named “CustomSite” inside the “TEMPLATE\LAYOUTS\STYLES” directory. This folder will contain the styles used by the master page. 

a

8) Now since we have defined the place for images and the styles, let’s modify the master page to reference the necessary images and css file t the new location. Open the customsite.master page file and do the following: 

  a.  Update the reference for css files to the reference from layouts folder. Make the following change.

  Original

a

Modified

a

b. Search for the text below and update it 

  • src=”../../images/questionMark.gif” to src=”/_layouts/images/CustomSite/questionMark.gif”

c. Now look for any references that need to be updated in the css files. Open the file “color_layout4_blue.css” and update the following image references. 

  • “../images/lay4_blue_logo.gif”) to “/_layouts/images/CustomSite/lay4_blue_logo.gif”
  • “../images/lay4_blue_hover.gif” to “/_layouts/images/CustomSite/lay4_blue_hover.gif”
  • “../images/lay4_blue_nav_bg.gif” to “/_layouts/images/CustomSite/lay4_blue_nav_bg.gif”

d. Open the file template_layout4.css and make the following change.

  • “../images/lay4_stock.jpg” to “/_layouts/images/CustomSite/lay4_stock.jpg”

9) Till now we have create a site definition feature, add a custom master page with its necessary image and css files and updated the references according to the deployment of the files. Now we need to specify in the site definition the master page to use for the site.

10) Open the Onet.xml file and look for the “Configurations” node in the xml file.

a

You will see that there is a Configuration with ID=0 and name “Default”.

11) Add the following attributes to the Configuration node.

a 

Here we specified that the site with configuration ”0” would use the master page customsite.master The master page will be present in master page gallery. Step 5. 

12) Expand the WebFeatures node and add an entry for the master page feature within this section. To get the ID, go to the WSP view, open the feature.xml file and copy the id of the feature.

 a

      a

13) With this,  build and deploy the project. Go to project->properties->Debug and specify the url of a site in the “Start browser with URL” section. Build and deploy the project.

a

14) After deployed successfully, create a new subsite. Select the Deployment category and select the customsite template.

a 

15) See that the newly created site is aplied with the custom master page that we specified.

a

Go to the master page gallery in the site collection and see that the master page “customsite.master” has been added to the gallery.

a  

Go to the Operaitons->Solution Management section in the central admin web site to see the solution installed.

a

 Enjoy !!! :-)

Older Posts »

Theme: Shocking Blue Green. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.