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

February 4, 2010

Column Limit Exceeded in SharePoint 2003

Filed under: Sharepoint 2003 — sandeep nakarmi @ 8:26 AM
Applies to:
  •  Windows SharePoint Services 2.0
  • Microsoft Office SharePoint Portal Server 2003
With Windows SharePoint Services 2.0, you can create the following numbers of each column type for each list or library:
  • 64 Single line of text and Choice (drop-down menu or radio buttons)
  • 31 Multiple lines of text and Choice (check boxes (allow multiple sections))
  • 32 Number and currency
  • 32 Hyperlink
  • 16 Date and time
  • 16 Lookup
  • 16 Yes/No
  • 8 Calculated

Note

  • In the first three items in this list, the number is the total for all lists of those types. For example, you can have 16 Number columns and 16 Currency columns, but not 32 of each type.
  • If the list is a survey, you can have up to 32 questions of the types “Multiple lines of text,” “Choice (check boxes (allow multiple selections)),” and “Rating Scale.”
  • You can have 32 Hyperlink columns if no “Single line of text” fields or “Choice (drop-down menu or radio buttons)” fields exist in the same list.

Source article : http://support.microsoft.com/kb/823555

December 23, 2009

Programatically Browser-Enable InfoPath form template in SharePoint

Filed under: InfoPath, Sharepoint 2007 — Tags: , , — sandeep nakarmi @ 3:33 PM
A BrowserEnabled InfoPath form template allows you to access and modify the item directly from the web browser like  Internet Explorer. Inorder to publish an InfoPath Form template that is browser enabled, the InfoPath template must be configured to be browser compatible along with the sharepoint server.  

In InfoPath, make sure you set the following parameters to make the template browser compatible:-        

  • When creating a new template, in Design a From Template wizard, check the “Enable browser-compatible features only”.
  • In Toosl->Form Options->Compatibility, make sure the checkbox that states “Design a form template that can be opened in a browser or InfoPath” is checked. 

With that, if you try to publish the template to SharePoint using InfoPath publish feature , and if you have not configured sharepoint to browser-enable the form templates, you will get a warning message in the publishing wizard:-

This form template is browser -compatible, but it cannot be browser-enabled in the selected site.       

Reason:
          This may be caused by one of the followings:
         

 

  • The Server is not running InfoPath Forms Services.
  • The necessary features are not available on the site collection.
  • The policy setting on the server does not allow to browser-enable form templates.    

Solution:     
You need to make sure that Sharepoint has been configured to browser-enable the form templates. Make sure that :            

  • InfoPath Forms Services or Forms Server 2007 has been installed on the server.
    In SharePoint Central Admin, verify that InfoPath Forms Services group is present under Application Management.
  • Form Services feature on the site collection is activated.
  • The policy in Central Admin allows you to browser enable the form templates.
    In Configure InfoPath Forms Services setting under Application Management,  allow users to browser enable form templates.
     

With these settings configured, publish the form template again which should work fine.       

From a sharepoint developer’s point of view, if you are interested in knowing how does InfoPath manage to publish these templates and browser-enabled it in sharepoint,  here’s a way to see what’s happening behind the scene.  

I use Fiddler, a web debugging tool, to monitor this. Just set the fiddler to capture data and start the process to publish InfoPath Form template to sharepoint, and you can see the web methods that InfoPath invokes during this process. Here are a couple snapshots with key operations during publishing of a browser compatible form template .             

Is Forms Service Enabled

Invoke WebService method to browser enable form template

Operations exposed by FormsServices.asmx WebService

 The implementation is in the assembly “Microsoft.Office.InfoPath.Server.dll” located in “C:\Program Files\Microsoft Office Servers\12.0\Bin” folder. You can use a reflector to look at the implementation of the operations.          

Implementation of web service operations

 

  So, along with FormsServices web service, you can programatically browser-enable the form template in sharepoint using this assembly in your the project, provided it runs in the sharepoint machine and meets the requirements stated above.       

October 27, 2009

Add Web service reference- Components required to enumerate web references not installed

Filed under: Visual Studio — sandeep nakarmi @ 5:24 AM

The solution

  1. Close all open Visual Studio instances
  2. Open the Command prompt available with Visual Studio and type devenv /resetskippkgs (You can directly type this to Run command or normal command prompt) 
  3. Add reference to the Web service/WCF service

http://weblogs.asp.net/cabhilash/archive/2009/10/13/add-web-service-reference-components-required-to-enumerate-web-references-not-installed.aspx

October 7, 2009

Embedding SqlServer Compact in application. Performance benchmarks and best practices

Filed under: SqlServer — Tags: , — sandeep nakarmi @ 5:20 PM

Thinking of implementing SQL Server Compact in your application. !!!

Have a look at the performance benchmarks and best practices tips presented in PDC 2008 in the video below. It will help a lot.

http://channel9.msdn.com/pdc2008/PC40/   

:-) Happy coding.

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:

Older Posts »

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

Follow

Get every new post delivered to your Inbox.