Monday, January 10, 2011

Ajax Integration with sharepoint


Master Page

1. Add the following tag just below the form tag of master page

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" />

Web.Config
1. Add safe control

<SafeControl Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI" TypeName="*" Safe="True" />

2. Add the http handler inside <httpHandlers> tag of web.config

<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" />
3. Add the HttpModule inside <httpModules> tag of web.config

<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
4. Add the assembly inside <assembly> tag of web.config

<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

5. Add controls Tag inside <pages> tag of web.config
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</controls>
If you are adding <system.webServer> tag inside <configuration> like following then you could avoid step 2 and 3


<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</handlers>
</system.webServer>



Saturday, January 8, 2011

Double Hope Issue in Sharepoint/Asp.net application with IIS

This is a common issue called Double Hope issue in IIS and troubles most Sharepoint / Asp.net application which consume the resource in other servers .In application development most of the one talks to different application resides in multiple servers.

Problem
This issue occurs when you try to access the resource outside server with current logged in user credentials. In this scenario first hope occurs when user access the page from client browser that time its authenticate the user with his own windows credentials. The second hope occurs when IIS try to access the other server with the current user credential. In SharePoint world most of the application uses windows authentication to authenticate the user and impersonation also set to true. Our application want talk to other application.Let say for example a webservice in another physical server or a sharepoint service in another Farm .In this scenario during the second hope IIS will pass the credentials with hashed password ,so the other server cannot understand credentilal.


You could also read more about this issue in msdn http://msdn.microsoft.com/en-us/library/ms817871
How to solve the issue
Approach 1 : Use Same Encryption and Decryption
Use same encryption and decryption key in web.config of both servers. This way we could force the servers to use the same key.
< machineKey
validationKey ="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7
AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281B"
decryptionKey ="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
validation ="SHA1"
decryption ="AES"
/>
Read more about it http://msdn.microsoft.com/en-us/library/ff649308.aspx





Approach 2 : Use IIS Application Pool Identity User
In this approach we need to use the application pool identity user for communication with other server. Here we change impersonation context application pool identity user when we communicate with the other applications.After the consumption of other application we will revert back to the current user.

WindowsImpersonationContext appPoolContext = null;
//Imperosonate application pool UserIdentity
appPoolContext = WindowsIdentity.Impersonate(System.IntPtr.Zero);
//**************
//Call all the web services here
//************
//After the execution revert back to current user
appPoolContext.Undo();

Approach 3 : Communicate with specific user credential
Another approach you could communicate with specific domain user credential. In this approach we will be setting the credential explicitly to a specific domain user by passing user name and password. In this approach you could keep

//Create the service client
MyWebServiceclient = new MyvewebserviceViews(weburl + "/_vti_bin/views.asmx");
//Set the credential of a domain user
MyWebServiceclient.Credentials = new System.Net.NetworkCredential("MyUser", "Password", "domain");
//Call the service
MyWebServiceclient.GetView(listname, viewName);
You could keep the user information in web.config and encrypt it.
1. Creat web.config entry
< section name ="UserInfoSection"
type ="System.Configuration.SingleTagSectionHandler"/>

< UserInfoSection username ="value1" password ="value2" domain ="value3"/>

2. Encrypt the section
Go to visual studio command prompt and run
aspnet_regiis –pef UserInfoSection

3. Read the value from code

MyUserData = (System.Collections.IDictionary)
System.Configuration.ConfigurationSettings.GetConfig(" UserInfoSection ");

Tuesday, January 4, 2011

How to find Sharepoint DB

In sharepoint world you should know where the sharepoint database is to trouble shoot database related issues.Some one come to you and say i am getting unable to connect to database error or my sharepoint is down.So you may not know the details of the environment.In first step you need to identify the  servers so you have to find the configdb and content db servers.

How to find the Config DB

Configuration database connection string is stored in Registry key. So sharepoint look for that entry to identify the database.

In Sharepoint 2007 you could see the config DB conection string in Following Registry Key

My Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0\Secure\ConfigDb


In Sharepoint 2010 you could see the config DB conection string in Following Registry Key

My Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0\Secure\ConfigDb


The Next thing you have to find the Content DB attached to Web application.Here you have to remember one thing a web application could hold multiple site collection.So it will have multiple ContentDB

1. Go to Central Admin
2. Go to Application Management
2. Go to Database section and click on Manage Content Database
3. From the list Select your web Application
4.Click on the content DB  it will take to details page.
Content DB details page you could identify the DB Server

Loop Back Issue in Sharepoint


Issue
 Browse a SharePoint Web Application which uses a fully qualified domain name from a WFE in the farm you will get a 401.1. This error code means there is a problem with the user credentials but nothing to do with invalid credentials.
Windows Server 2003 SP1 introduced a loopback security check. By default this feature enabled in Windows Server 2008. The feature prevents access to a web application using a fully qualified domain name (FQDN) if an attempt to access it takes place from a machine that hosts that application and shows a 401.1 Access Denied from the web server and a logon failure in the event log.

How to Solve this
You need to create a DWORD registry key called DisableLoopbackCheck and set it to 1.

Steps
1. Start -> Run, type regedit
2. Go to following registry key
   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
3. Add a new DWORD Value in LSA key.
4. Type DisableLoopbackCheck, and then press ENTER.
5. Modify DisableLoopbackCheck and set Value to 1.
6. Exit Registry Editor
7. Restart your computer.

Wednesday, December 15, 2010

JQuery Integration with Sharepoint

JQuery changed the way we write javascript and easy to use.So JQuery become a must have for most of the developers around the world. We all are start working with sharepoint 2010 so one of the intresting question around the sharepoint world is Did Sharepoint 2010 ships with JQuery?. I was also curious about it so I was searching in the 14 hive folder in 2010 but there is no luck.So final answer to the JQuery Integration will be No Its not part of the Sharepoint 2010.
So it will be interesting to see how we could use JQuery in Sharepoint. Now JQuery could be used in two different way.
1. CDN Hosted JQuery
A number of large enterprises provide hosted copies of jQuery on existing CDN networks that are available for public use.

http://code.jquery.com/jquery-1.4.4.min.js Minified version
http://code.jquery.com/jquery-1.4.4.js Source version

Read More

2. JQuery from Local Server

Next approach will be download JQuery from the official site and save in your local server , then refer like any other JS file.

How to use in a Sharepoint page?
Download the JQuery jquery-1.4.4.min.js and copy to the layout folder (c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS) in 14 hive (12 hive for sharepoint 2007) .Now we are good to use JQuery in any of the Pages in any site collection.
1. Add the script link in html head section of the page

<script type ='text/javascript' src='/_layouts/jquery-1.4.4.min.js' ></script >
Once you added the Script link tag you co


2. Add the script link in html head section of themaster page

<script type ='text/javascript' src='/_layouts/jquery-1.4.4.min.js' ></script >

Sunday, December 12, 2010

Creating Custom Timer Job

Timer Job is something which comes into mind when you are looking for batch process in sharepoint.In most of the realtime sharepoint site requires Pulling data from some other application and update the data in sharepoint.In some other scenario we need to synchronize information or Updata date in every day, or give the admin a flexibility execute some batch processing.Its realy good idea to create a Custom Scheduled Job.Let see a Basic skelton code.



using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;


//Class should inherit from  SPJobDefinition

Public class SampleJob : SPJobDefinition


{
       //You could Define Custom properties

        [Persisted()]
        public string MyCustomProperty;

///Implement Following three constructors

public SampleJob (): base(){  }
public SampleJob (string jobName, SPService service, SPServer server, SPJobLockType targetType): base (jobName, service, server, targetType) { }
public SampleJob (string jobName, SPWebApplication webApplication): base (jobName, webApplication, null, SPJobLockType.Job) { }

//You should Override Execute Method

public override void Execute (Guid JobbId) {
//Your Code Execution
//In my case i will be calling a exeternal webservice and synchronize the Data
  }

}


Here basically you will be inheriting  from SPJobDefinition class and then implementing three of the constructors.Then comes main function Execute method , where all of your real excution code goes.You should Override this function to customize the job execution.Another good point you have to watch for the lock type you  specifies in the constructor.


SPJobLockType:

ContentDatabase – this options locks the content database associated with the web application, but the job will be run for each content database associated with the web application.
Job – Ensures that the job will be run only on a single server.
None – Ensures that the Job will be run on all servers.


Next thing how we are going to deploy the Job.Create a feature and and implement FeatureActivated Event and  FeatureDeActivating Event


public class SchedualedJobsFeature : SPFeatureReceiver
    {
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            SPServer myServer = SPServer.Local;
         
            SPWebApplication myApplication = site.WebApplication;
            SPJobDefinitionCollection myJobsColl = myApplication.JobDefinitions;
            Type sPJobDefinitionType = typeof ( SPJobDefinition);
            
            Type[] types =  typeof  (SchedualedJobsFeature).Assembly.GetTypes ();


            foreach (Type t in types)
            {
                if (t.IsSubclassOf(sPJobDefinitionType))
                {
                    
                    object[] atts= t.GetCustomAttributes ( typeof ( MyJobDefinitionAttribute) , false );
                    if ( atts== null || atts.Length == 0)
                    {
                        continue;
                    }
                    MyJobDefinitionAttribute jobAttribute  = (MyJobDefinitionAttribute) atts[0];


                    SPJobDefinition job = (SPJobDefinition)Activator.CreateInstance(t,
                        jobAttribute  .Title, myApplication, myServer, jobAttribute .LockType );
                    job.Schedule = (SPSchedule) Activator.CreateInstance(jobAtt.ScheduleType);
                    
                    try
                    {
                        SPJobDefinition oldJob = myJobsColl[jobAttribute .Title ];
                        if (oldJob != null)
                        {
                            myJobsColl.Remove(oldJob.Id);
                        }
                        else
                        {
                            
                        }
                    }
                    catch {}


                    try
                    {
                        job.Status = SPObjectStatus.Disabled;
                        myJobsColl.Add(job);


                    }
                    catch (Exception ex)
                    {
                        //Handle Exception
                    }
                    
                }
            }


          }
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            SPServer myServer = SPServer.Local;
            SPWebApplication myApplication = site.WebApplication;
            SPJobDefinitionCollection myJobsColl = myApplication.JobDefinitions;


            Type sPJobDefinitionType = typeof(SPJobDefinition);


            Type[] types = typeof(SchedualedJobsFeature).Assembly.GetTypes();




            foreach (Type t in types)
            {
                if (t.IsSubclassOf(sPJobDefinitionType))
                {
                    object[] atts = t.GetCustomAttributes(typeof(MyJobDefinitionAttribute), false);
                    if (atts == null || atts.Length == 0)
                    {
                        continue;
                    }
                    
                    MyJobDefinitionAttribute jobAtt = (MyJobDefinitionAttribute)atts[0];
                    try
                    {
                        SPJobDefinition job = SalesCatalogListItemSync)myApplication.JobDefinitions[jobAtt.Title];
                        myApplication.JobDefinitions.Remove(job.Id);
                    }
                    catch (Exception ex)
                    {
                        //Handle Exeception 
                    }


                }
            }




        }




public class MyJobDefinitionAttribute: Attribute
    {
        public string Title
        {
            get;
            set;
        }
        public Type  ScheduleType
        {
            get;
            set;
        }
        public SPJobLockType LockType
        {
            get;
            set;
        }
    }


Looks simple rite.

System.PlatformNotSupportedException in Sharepoint 2010

All the sharepoint developer must be exited to see the .Net Framework 4.0 , unfortunately its not supported.Once you VS2010 and start playing around as sharepoint devleloper you just jump into start writing few lines of code.

May be something like following


using (SPSite objSiteColl = new SPSite("http://Localhost"))
{
   Console.WriteLine("Found My Girl  : {0}", objSiteColl.RootWeb.Title);
}



 Exception  :

Exception of type 'System.PlatformNotSupportedException' was thrown.


   at Microsoft.SharePoint.Administration.SPConfigurationDatabase.get_Farm()


   at Microsoft.SharePoint.Administration.SPFarm.FindLocal(SPFarm& farm, Boolean& isJoined)


   at Microsoft.SharePoint.Administration.SPFarm.get_Local()


   at Microsoft.SharePoint.SPSite..ctor(String requestUrl)


No need to scratch your head , .Net Framework 4.0 is not supported in Sharepoint.