Pages

Saturday, October 6, 2012

SharePoint 2013: App Concept

Introduction

SharePoint 2013 has added a bunch of new concepts for apps. You can think of a SharePoint app just like iPhone app or Android app for time being. If you have not already setup the on-premises development environment for SharePoint 2013 apps development, please follow the link Set up an on-premises development environment for apps for SharePoint to setup your development environment.

 

Install/Host an App

You can install the app in a SharePoint web (called host web for the app). When you install an app in the SharePoint web (called host site), the app needs a place to exist  where app’s css, javascripts, pages etc will be placed. The app resources (like pages, css, javascript etc) are not stored/kept inside host web. Where the app’s resources are stored/kept basically depends on app’s hosting type. The app can be hosted in any of the followings:

  • inside SharePoint (called SharePoint hosted)
  • You can host app in Cloud. You have two options for cloud-hosting apps
    • Windows Azure (called AutoHosted)
    • Third-party solution providers can provide setup for apps (called Provider-hosted)

You can get more details on this hosting options at MSD link.

 

The app can add some links/actions (like ribbon, ECB menu etc) in the host web. But the app itself doesn’t live inside host site.  When you use SharePoint hosted option for an app and as soon as you install the app in a host web another web (usually subsite to host site) is created (called app web) for the app components to be installed. The relation to host and app web for SharePoint hosted app, is shown below:

image

Figure 1: SharePoint hosted Apps are usually installed under subsite of Host web

For other options (like provider hosted and windows azure hosted app), app web is optional and the actual app web resources are stored in windows azure or third party servers.

Though app webs are installed under subsite of host web usually, for SharePoint hosted app, it doesn’t mean you can access the app web directly with url. Rather the apps are only accessible from different url. The App web is accessible from different url (not like host-web url). This is to keep the app webs isolated from host web. Usually these two types of webs urls (host and app web) belongs to two different domains. You can find more details on this host web url and app web url from this MSDN link.

 

App Types (From users’ points of view)

Now question comes what types of apps we can develop and how they will look like from user’s point of view. You can do the following types of things with apps:

UI Custom Actions

An app can add links like ribbon, custom actions or ECB menu to the host web. When user will click on the link, user will be redirected to the app web. Let’s consider a scenario which will explain this UI custom actions in details:

  1. You installed an app (let’s call it SharePoint PDF Converter) in a SharePoint site http://mysite.mydomain.com/businessdocs (called host web). The app will add a ribbon button in the site to convert any word document to pdf. When you will install  the app ‘SharePoint PDF Converter’, a subsite will be created under host web (http://mysite.mydomain.com/businessdocs) and the app contents (like javascript, css, aspx pages etc) will be deployed in the subsite. As mentioned already app webs are not accessible by url (like http://mysite.mydomain.com/businessdocs/appwebname) directly, rather they have different url for isolation. The idea of adding ribbon button in host web shown below:image Figure 2: An app can add ribbon to the host web.
  2. Now what will happen on user will click the ribbon button? Usually user will be redirected to the app web and app developers have the option to pass the current selected item details (like id, url etc) to the app web. The concept of redirecting from host web to app web and having the app web taking control of the full browser page is called ‘Immersive Full Page’ user experience.

You can get more details on custom action app types on MSDN link Create custom actions to deploy with apps for SharePoint.

 
App Part

Apps can also add web-part like stuffs in the host web called Part (or app part). You can think of an ‘app part’ as like web part but it’s provided by app web. You can think of it as just like web part but instead of Farm WSP solution this app part comes from app deployment to your host web. You can find more details on this app part on MSDN link Create app parts to deploy with apps for SharePoint. The following image shows an app part that is available to be added in the host site:

image

Figure 3: Add an app-part (just like adding webpart)

Once you add the app-part the page will look like below which kind of resembles the webpart concept:

image

Figure 4: App part added to the page

 
Immersive Full Page

All apps have a default page which might take the full page. Apps show custom action or app part in the host web. The app might take the full page by redirecting user from host web url to app web. For example, the host web url is http://www.hostweb.com and an app is installed in the host web which adds a custom action. When user clicks the custom action, the user will be navigated to a new url (say, http://www.appweb.com). So the app takes the full page (so it’s called Immersive Full page). However user will not notice the url changes as the new app site will have the same UI look and feel. The idea of having the app web to have similar look and feel like host web is achieve thorough a new concept in SharePoint 2013 – called Chrome Control. Basically Chrome control is kind of adding few components (js,div element etc) in App web so that when user redirect from host web to app web, the chrome control retrieves css, js from host web and apply it in the app web on the fly. Also the chrome control create a SharePoint 2013 ribbon bar in the app site, so that user can navigate back to the hot web.You can get clear idea of chrome control watching this video.

Sunday, August 12, 2012

SharePoint: Too much customization is not good for health

SharePoint allows developer/architect to customize it’s power in numerous ways. You can write event receivers, timer jobs, webparts, application pages and so on. But what I’ve found with my years of experience in working with SharePoint is that sometimes developers/architects make too much customization which is not good from maintenance point of view.

If you are senior SharePoint developer or architect or you have the responsibility to design a solution for SharePoint, first focus on out-of-the-box way to solve the problems. If possible, try to compromise features talking to clients.

Real world Example

Let’s consider a simple example. You have a database which is used by other LOB systems. SharePoint reads and writes data to the database and then other LOB systems (like SAP or some custom applications) use (only read) the data in the database for it’s own use.

image

Now client requirement is to show the data in the database as SharePoint list so that clients get the feelings that the tables in the database are kind of List in the SharePoint. Now what options do you have? I think we have two options:

  • Option 1: Use Business Connectivity Service to show Database tables as SharePoint list
  • Option 2: Create custom SharePoint list and then write event receivers to synchronize data between database and List.

Different architect/developer under different circumstances, may use first option or second. But the first option is more out-of-the-box way of implementing the requirements. However some situations demand the second option where you need to  write custom code and need to sync data between SharePoint list and table in database manually. So as an architect/developer I would prefer the first option using Business Connectivity Service. If I need to choose second option then I should have explanation why I need to use second option. The explanation might be Business Connectivity Service has some limitations that we need to overcome with second option, or the requirements are too complex to implement with Business Connectivity Service.

 

But Why?

Now you may ask why it’s matter if I do more customization (I would prefer to say unnecessary customization). I bet it’s matter. The more customization you do, the more difficult to manage codebase, more time to develop, more possible to generate more bugs, more difficult to upgrade to newer version of SharePoint and many more. SharePoint is a rich application framework and we need to utilize it in best possible ways.

 

conclusion

The idea I wanted to share here not to say that you should not do any customization rather make sure your customization really needed. If you do unnecessary customization then you might paving the way for more customizations (maybe for error fixing or features related to customizations). As I read somewhere, “A single bad developer creates job for more developers”. Let’s not create more customizations by an unnecessary customizations.

Saturday, June 16, 2012

SharePoint: Package your external dependencies to another solution

Sometimes we use some third party tools that create external dependencies to our SharePoint projects. For example if you use Pattern and Practice SharePoint Guidance Library in your SharePoint project in visual studio and build WSP, then  WSP package will include these SharePoint Guidance libraries also. However, this might create problems related to deployment. To explain the issue, let’s consider how SharePoint solution retraction/removal might affects other WSP package deployed in the same SharePoint environment.

 

Scenario: Two WSPs sharing Common Dependency

Let’s consider you have two Visual studio SharePoint project: SharePoint Project 1 and SharePoint Project 2. Both projects are using (i.e., referencing) a third party dll (i.e., thirdparty.dll). Now if you generate WSP from two different Visual Studio projects, both WSP will include the thirdparty.dll in their WSP package.

image

Figure 1: A single thirdparty.dll is shared by two WSP solutions

 

As shown in the image above, a single third party dll is referenced by two Visual studio SharePoint projects. Now when you 'will build two different WSP solutions the same third party dll will be included to two different WSPs. If these two WSPs are deployed in a single SharePoint server/farm with GAC deployment, then both WSP will deploy the same ThirdParty.dll in the GAC. Everything will work fine till now.

 

Problem: retracting/removing one solution will fail other WSP to work

Now consider a scenario. After deploying the two WSPs in the production with GAC deployment, you have found a problem with Project 2 WSP. So you want to remove the Project 2 WSP while you will keep Project 1 WSP. So you will remove the Project 2 WSP. Removing the Project 2 WSP will remove all the assemblies from GAC/BIN related to the WSP. So removing the Project 2 WSP will remove thirdparty.dll from GAC. As soon as you remove the Project 2 WSP from SharePoint server/farm, Project 1 WSP will fail to work as it’ll not find the referenced thirdparty.dll in GAC. So removing Project 1 WSP (or project 2 WSP) will remove the thirdparty.dll from GAC and other WSPs which are using the same dll will fail to work.

 

Solution: Package your external dependency to new WSP

The solution to this problem is to exclude thirdparty.dll from both WSPs and create a new WSP dependency/prerequisite solution for thirdparty.dll. You can do it easily with SharePoint 2010 Package editor. As a result the thridparty.dll will not be included in any of the two WSPs.To package a new WSP for the thirdparty.dll you need to create another new Visual Studio SharePoint projects which will just include the thirdparty.dll (or any other prerequisites). The new architecture is shown below:

image

Figure 2: Shared thirdparty.dll is included in separate WSP

 

As shown in the figure 2, now the shared dll (thirdparty.dll) is excluded from Project 1 and Project 2 WSP. Whether you use WSPBuilder or SharePoint 2010 project template in Visual studio, you can exclude one more dlls from the WSP. Then create a new Visual Studio project (WSPBuilder or SharePoint) which will include the thirdparty.dll and the output WSP package will include the shared/external dll. Now you will have three WSPs and the new WSP will be prerequisite WSP for other two WSPs.

Now with this model, you can remove Project 1 WSP or Project 2 WSP from your server without affecting each other. Even if you remove Project 1 WSP from the Farm/Server, the thirdparty.dll will not be removed from GAC as it’s not deployed as part of Project 1 WSP. Later if you want to redeploy the Project 1 WSP again then you don’t need to redeploy the prerequisite WSP as it’s already deployed in the server. If needed you can package your external dependency in more than one WSP packages.

 

Conclusion

If you are developing a SharePoint custom product that will be deployed in some client’s environment, then you should care about creating one or more dependency WSP packages. If your SharePoint solution is developed for a specific client or as an in-house product then you might not face the problem even if you don’t create a prerequisite WSP package. However if you are developing a SharePoint solution as a custom product and you don’t know the client yet, you should create prerequisite WSP package. And then when you will deploy your product in client server, you can deploy the perquisite or not depending on if the client has the prerequisite dlls install or not. If the client has the dlls/prerequisites installed in the farm, you don’t need to deploy the prerequisite WSP. This will make your SharePoint product more independent and will have less impact on other SharePoint solution deployed in the farm.

Thursday, May 17, 2012

SharePoint Tips: Iterating through All the webs in the site

Sometimes we need to process all webs in a site collection, as you want to do some quick fixes in the web. Few weeks back my manager asked me to do some fixes in the list items exists in all the webs in the site collection. There were about 30,000 webs in the site collection and I was looking for some kind of script that will be efficient. The usual way of looping through all webs might be using some recursive way, as shown below.

//Starting point
public void ProcessAllWeb(SPSite site)
{
    using (var web = site.RootWeb)
    {
        ProcessWebRecursive(web);
    }

}

//Recursive method
private static void ProcessWebRecursive(SPWeb web)
{
    //do some processing
    //web.Lists["listName"].ItemCount

    foreach (SPWeb subWeb in web.Webs)
    {
        using (subWeb)
        {
            ProcessWebRecursive(subWeb);            
        }
    }

}

Code Snippet 1: Recursive way of processing all webs in the site collection (Not optimized)

In the recursive way of processing all webs, there will be more than one SPWeb instance alive in memory. In the above code snippet, when the method ProcessAllWeb is invoked it’ll call the recursive method ProcessWebRecursive. The recursive method will keep calling the subwebs while keeping the parent web alive.

 

While I was writing the code, I was wonder if there’s any way of processing only one web non-recursively. So my intention was to open only one web in memory at once. And then I found it. You can get all web Url(including all subwebs at all level) using SPSite.AllWebs.Names. The following code snippet shows the efficient way of processing all webs in the site collection:

public void ProcessAllWeb(SPSite site)
{
    string[] allWebUrls = site.AllWebs.Names;
    foreach (string webUrl in allWebUrls)
    {
        using (SPWeb web = site.OpenWeb(webUrl))
        {
            //process web
        }
    }
}

Code Snippet 2: Process all webs one by one (Optimized for large number of webs)

Using the code snippet shown in figure 2, you just open one web at a time in memory for processing. The trick here is ‘SPSite.AllWebs.Names’ which will return all the (I mean it!) subwebs (including children and their children and so on) as a result. If you have thousands of webs under a site collection (and if it’s production), you should care about performance issue.

Thursday, May 3, 2012

SharePoint Tips: List.ItemCount vs List.Items.Count

If you need to know the total items in the list, how do you write code? The usual way to write code is shown below:
var itemCount = list.Items.Count;
Code Snippet 1: Usual (not suggested) way to get items count
However this will fetch all the records from database and apply the count in memory.

SharePoint object model provides an easiest way to find the items count without fetching all records and you can use the following code snippet to do so:
var itemCount = list.ItemCount;
Code Snippet 2: Suggested way to get items count

Saturday, April 21, 2012

SharePoint Tips: Object Mode provides Built-in Field and Content type Ids

Sometimes we need to access SharePoint built-in fields from list. You may find code to access list item value as shown below:

listItem["Title"] = "value";

Code Snippet 1: Usual approach

 

The title field is SharePoint built-in field and you don’t need to hard-code the field name . SharePoint Object Model provides a class ‘SPBuiltInFieldId'’ where you can find most of the SharePoint built-in field’s IDs. So you can write the above code snippet as shown below:

listItem[SPBuiltInFieldId.Title] = "value";

Code snippet 2: Suggested approach to access built-in fields

 

The class ‘SPBuiltInFieldId’ also provides many built-in fields Ids like ‘created by’ (known as owner), modified by etc.

Similarly you can get built-in content type Ids using the class ‘SPBuiltInContentTypeId’. I would recommend you to use these classes to access built-in fields and content types.

Friday, March 9, 2012

Managing a single codebase for both SharePoint 2007 and 2010

Sometimes we need to work on source code that needs to be maintained for both SharePoint 2007 and 2010. There’s no built-in support from Microsoft to manage two versions of same Visual Studio solution for multiple versions of SharePoint. The problem is more complicated as the SharePoint assembly details are hard-coded in markup (ascx, aspx).

Anyway, I worked on a project where my team was developing a SharePoint custom product and some of our clients are still using SharePoint 2007 while some others are already moved to SharePoint 2010. So we had a challenge to support all clients (both SharePoint 2007 and 2010) but maintaining a single codebase. I am not demanding that the solution I’ll provide in this post is the best but the approach might be helpful to minimize code duplication. The sample Visual studio project can be download from skydrive.

 

Introduction

I’ve used Model View Presenter (MVP) to separate the presenter logic from view. Also, code that not dependent on SharePoint assembly directly are put in presenter layer. If for any reason, presenter is dependent on SharePoint assembly (for example SPGridView is used in code-behind) then the SharePoint assembly dependent code is implemented in individual (2007 or 2010) SharePoint project where common non-SharePoint presenter logic is kept in Presenter layer. For explaining the solution, I would like to introduce you to the Visual Studio projects (can be downloaded from here)I’ve been used.

  • Sohel.Blogging.Common: This is common project where interfaces, data contracts, common utilities etc are declared.
  • Sohel.Blogging.Presenter: This is the presenter layer where all non-SharePoint related presenter logic is kept. Since there’s no SharePoint-dependent logic is places, no reference to SharePoint dll is needed. As a result this project (or more specifically, presenter logic) can be reused by both SharePoint 2007 and 2010.
  • Sohel.Blogging.Wss: This is SharePoint 2007 (wss) project from where we’ll generate WSP file. Only SharePoint 2007 project structure, Views (aspx, ascx etc.) and Site artifacts (site definition, columns etc.) are placed in this project. As code-behind is replaced by presenter (which resides in Presenter layer), only views are need to duplicated between SharePoint 2007 and 2010.
  • Sohel.Blogging.Foundation: This is SharePoint 2010 project from which we’ll generate WSP solution file. Only views (aspx, ascx), site structure and site artifacts (site definitions, site columns etc.) are maintained in this project

To plug presenter/view to each other, Dependency Injection is used and for that purpose, Microsoft Patterns & Practices SharePoint Guidance is used. The Guidance Library for both SharePoint 2007 and 2010 can be downloaded from CodePlex (http://spg.codeplex.com/). For more information on how to use the Guidance Library for Dependency Injection please follow another post SharePoint Service Locator in my blog.

The overall architecture of the Visual Studio solution is presented below:

image

Figure 1: Visual Studio Project Dependency

The overall goal of the architecture is to move aspx/ascx code behind to presenter layer. As a result the code-behind logic is reused in two different views (SharePoint 2007 and 2010).

 

Views

The view (aspx, ascx) files are slimmed by removing code to presenter. View files (aspx,ascx etc) are placed in Sohel.Blogging.Foundation or Sohel.BLogging.Wss project. An interface is extracted from view to make Controls (like TextBox, Dropdown etc) available to Presenter. This is done by exposing View’s controls as the interface properties of the view. Though this is not the real Model View Presenter (MVP) but it works and faster to develop. The only problem is that the view interface/presenter is tightly coupled to asp.net controls.

public interface IProductListview
{
    Panel CreateListPanel { get; }
    Panel AddItemListPanel { get; }
    HtmlGenericControl MessageDiv { get; }
    HyperLink ViewAllProductLink { get; }
    Product GetProduct();
    string GetProductListUrl();
}

However if you use SharePoint controls (like SPGridView), then instead of exposing them in View interface, keep the logic related to the control in View and use a method in view. For example if you use SharePoint DateTime control, a method in view/code-behind can be used to put the logic related to SharePoint control. The following view interface declares SetDate method that set the date value of SharePoint DateTime control.

public interface IProductListview
{
    //Panel CreateListPanel { get; }
    //Panel AddItemListPanel { get; }
    //HtmlGenericControl MessageDiv { get; }
    //HyperLink ViewAllProductLink { get; }
    //Product GetProduct();
    //string GetProductListUrl();
    void SetDate(DateTime dateTime);
}

The view (say UserControl) below implement the SetDate method.

public partial class ProductList : UserControl, IProductListview
{
    public void SetDate(DateTime dateTime)
    {
        uiSpDateTimePicker.SelectedDate = dateTime;
    }
..............
..............
}

 

Presenter

All Presenters are kept in Sohel.Blogging.Prensenter project. Presenter access View controls through view interface. As I’ve mentioned already, this is not the right for MVP pattern to use web control directly inside view interface. SharePoint Service Locator is used as shown below:

public class CurrentSharePointServiceLocator : IBloggingServiceLocator
{
    public T ResolveInstance<T>()
    {
        return SharePointServiceLocator.Current.GetInstance<T>();
    }
}

The interface to the service locator (IBloggingServiceLocator) is passed to the Presenter constructor inside view, as shown below:

public partial class ProductList : UserControl, IProductListview
{
    private ProductListPresenter _presenter;
    public ProductListPresenter Presenter
    {
        get
        {
            if (_presenter == null)
            {
                _presenter = new ProductListPresenter(this, CurrentSharePointServiceLocator.GetInstance<IBloggingServiceLocator>());
            }
            return _presenter;
        }
    }
.....
.....
}

As presenter get access to the IBloggingServiceLocator, presenter can access any object that is registered through service locator. The presenter gets access to the view and service locator through constructor as shown below:

public class ProductListPresenter:APresenter
{
    public IProductListview View { get; set; }

    public ProductListPresenter(IProductListview view,IBloggingServiceLocator serviceLocator):base(serviceLocator)
    {
        View = view;
    }
.....
.....
}

 

New development Consideration

Once the project architecture is in place and if you need to develop new control, application pages etc, you should develop new control for any version of SharePoint first. For example if I need to develop a new application page, I would go and develop the page for SharePoint 2010. Then I would refactor the code to move the code-behind logic to Presenter class. Then I’ll create a new page in SharePoint 2007 copying the similar file from SharePoint 2010 (but surely with modifications). Now while you’ll create new page for SharePoint 2007, you may fine more refactoring needed to generalize code more for both SharePoint 2007 and 2010. The only duplication needs to be made in this approach is resources like markup/xml/css/jss etc. need to be duplication. But I think its possible to minimize the duplication by putting most of the resources in separate web project and on post-build event, you can copy the resources in individual SharePoint projects.

 

Conclusion

As more and more clients are adopting SharePoint and more and more Independent Software Vendor (ISV) are developing custom SharePoint products, ISVs need to support more than one version of their product. Since Microsoft doesn’t provide any out-of-the box solution for this multiple-version support for Visual Studio Solution, it takes extra efforts for developers to use the same codebase for different version of SharePoint and increase the possible of code duplication which in turn make maintenance difficult. You can download the sample code from skydrive.

Disclaimer: The solution provided in this post is not the best solution but a workaround. If anybody has any better idea, you are welcome to share.

Sunday, November 20, 2011

SharePoint 2010: Configure Kerberos Authentication

SharePoint 2010 supports two authentication mode: Classic mode and Claims based. Today I’m going to explain how to configure Kerberos authentication for an web application with classic mode Authentication. I’ll try to explain how to configure Kerberos for an web application with Claims based authentication later.

 

Step 1:  Create/Configure Web Application

In this step you need to create an web application with required configurations. However, you can convert an existing web application to use Kerberos authentication if the web application app pool user is a domain user. But as mentioned already, the configuration explained in this post applies for an web application with Classic Mode Authentication.

Create a new web application

In creating new web application for using Kerberos Authentication you need to consider the following options:

  • Use classic mode Authentication as shown below (You can use Claims Based Authentication but then the steps described in this post might not work. For Claims Based Authentication you need different sets of configuration):

    image
    Figure 1: Create site with ‘Classic Mode Authentication’

  • Use Negotiate (Kerberos) as Authentication Provider in ‘Create Web Application’ page as shown below:

    image
    Figure 2: Create site with Negotiate (Kerberos) Authentication provider selected.

  • Use domain username for app-pool account. Don’t use Predefined (like Network Service, Local System etc) user account. This is important to use domain user name as you will configure Kerberos against this app-pool username.

    image
    Figure 3: User domain user name for App-pool account.

  • One recommendation. Make the site url to be Fully Qualified Domain Name. For example, my server name was sohel-server and domain name was sohel.com. I’ve modified my full site name from default http://sohel-server:5000 to http://sohel-server.sohel.com:5000. This will help you identifying if the Only Kerberos is used for authentication instead of NTLM.

 

Configure an existing web application

If you have an existing web application that you want to move to Kerberos from NTLM you need to make sure your site meets the following criterion:

  • The web application uses a domain user in application pool account instead of predefined account like Network Service, Local System. If your web application doesn’t use domain user then you can create a new web application with domain user name as application pool account. Changing the application pool account might make your web application malfunctioning.
  • If you existing web application uses Classic Mode Authentication then configuration in this post should work. However, if you are using Claims based Authentication then you need to configure Security Token Service (STS) which in not mentioned in this post. If you are using Classic Mode, then you can continue this post as this post describes Kerberos for an web application with Classic Mode Authentication.

If you meet the above mentioned criterion, then you can change the authentication of the site to Kerberos. To change the Authentication Provider to Kerberos, navigate to Central Admin site then click “Application Management” => Manage Web Applications => Select your web application => Click Authentication Provider from ribbon button as shown below:

image

Figure 4: Change Authentication Provider

In the Authentication provider windows click on the zone you want to configure the Kerberos Authentication. Then you will be shown ‘Edit Authentication’ window. If your web application is using NTLM you can change the Authentication to Kerberos as shown below:


image

Figure 5: Change NTLM to Kerberos

When you change the authentication type from NTLM to Kerberos you will be prompted with message saying “” as shown below. You don’t need to worry, we’ll configure other settings to use Kerberos. So just click ok button when the message appears and then save the settings.

image

Figure 6: Warning appears during Authentication changes from NTLM to Kerberos

 

Step 2: Configure Service Principal Name (SPN) in Active Directory

So your web application is configured for Kerberos Authentication but you need to configure Service Principal Name (SPN). Simply SPN is an unique identifier for each service (HTTP, SQL, AD etc) running in the server. An SPN is a combination of service name, host name and port name. The original format for SPN is

<Service Name>/<DNS Host>:Port

To know more about SPN, you can follow the link: http://technet.microsoft.com/en-us/library/cc961723.aspx. For our web application we need to create SPN. The SPN format for our web application is as shown below:

  • HTTP/<DNS Host Name>:Port
  • HTTP/<DNS FQDN>:Port

In my case the SPN are:

  • HTTP/sohel-server:5000
  • HTTP/sohel-server.sohel.com/5000

However, if you are using any port other than 80, you need to add four SPNs (two for 80 port and two for your non-80 web application port). Whether you use Kerberos for 80 port, you need to add SPNs for default port. So though I’m configuring Kerberos for HTTP port 5000, I need to configure Kerberos for 80 port also. The following SPNs are need to configured for my example.

  • HTTP/sohel-server
  • HTTP/sohel-server.sohel.com
  • HTTP/sohel-server:5000
  • HTTP/sohel-server.sohel.com:5000

How to set SPN?

  1. Make sure you installed ‘Active Directory Lightweight Directory Services’ from Server Role to get the ADSI Edit UI for editing SPN values. You can add the  ‘Active Directory Lightweight Directory Services’ from Server Manager => Add Roles  as shown below:

    image
    Figure 7: Install ‘Active Directory Lightweight Directory Services’ from ‘Add Server Role’

  2. To setup SPN, Run the command “adsiedit.msc” in either command prompt or from Run. You will get the ADSI Edit window.
  3. In ADSI Edit window, expand the ‘Default naming context’ and expand CN=Users and find the user you used for application pool in web application.
  4. Right click on the user entry CN=UserName and select properties window. Then find the property ‘servicePrincipalName’ and click edit as shown below:

    image
    Figure 8: Set SPN through servicePrincipalName

  5. Finally add the SPNs in the edit window as shown below:

    image
    Figure 9: Add SPN values as value of attribute ‘servicePrincipalName’.

  6. Press OK and then apply to close the dialog.

 

Step 3: Enable delegation

In some cases you may need to enable delegation of credentials. To enable delegation, open the Active Directory users and Computers from ‘Administrative Tools’ menu. Find the user used in Application pool under ‘Users’ node. Right click on the user and click Properties to get the properties window. Then in the properties window go to ‘Delegation’ tab and select ‘Trust this user for…’ as shown below:

image

Figure 10: Enable delegation

 

Step 4: Configure Internet Explorer

Finally you need to configure Internet Explorer (IE) to use current windows user to access the SharePoint site.

  1. Go to Tool => Internet Options. Then select ‘Local Intranet’ and click Sites as shown below:

    image
    Figure 11: Setup IE for adding the SharePoint site to local Intranet

  2. After ‘Local Intranet’ dialog select ‘Advanced’ and then you’ll find the way to add sites to local intranet. Add ‘*.yourdomain’ in the local intranet zone as shown below:
    image
    Figure 12: Adding my domain (sohel.com) to local intranet.

  3. Now close the Internet Options dialog. Then open the ‘Internet Options’ dialog from Tools => Internet Options. Then go to Security tab and select ‘Local Intranet’ and select ‘Custom Level’. Then At the end of the ‘Security settings’ window, select ‘Automatic login only in Intranet zone’ as shown below:
    image
    Figure 13: Enable automatic login for Intranet zone

 

Conclusion

Configuring Kerberos authentication may depends on many factors. So I can’t guarantee than each and every steps described here will work for everybody. But the overall sets of configurations are same. You need to configure SharePoint site, You need to configure SPN, You need to enable delegation (if required), you n need to configure Internet Explorer.  You can get elaborate description of configuring Kerberos Authentication with SharePoint 2010 from the link: http://www.microsoft.com/download/en/details.aspx?id=23176.

Sunday, October 9, 2011

SharePoint 2010: Get Full or Relative Url of web using EcmaScript

Sometimes from client side, you need to know the current web url. And for this little information you don’t want to call EcmaScript’s load function to get information from server side. Actually the information can be found without any server call. You can access the information from ClientContext as shown below.

var context = new SP.ClientContext();
var relativeWebUrl = context.get_url();

Remember the get_url method will only return relative url of the site. As shown in the following table:

Site Collection Url Site Url context.get_url() response
http://mysite.com http://mysite.com /
http://mysite.com http://mysite.com/site1 /site1
http://mysite.com/sites http://mysite.com/sites/site1 /sites/site

 

So if you need to know the full url of the site you can do so easily with the following script:

function getFullWebUrl() {
var context = new SP.ClientContext();
var relativeWebUrl = context.get_url();
var fullWebUrl = window.location.protocol + '//' + window.location.host + relativeWebUrl ;
alert(fullWebUrl);
}

Saturday, September 17, 2011

SharePoint 2010: Access WCF Service with jQuery

In one of my earlier post I described how to develop a custom WCF service. Today I’ll cover how you can invoke the SharePoint WCF Service from jQuery. In my last post I described to develop a SOAP web service but for using WCF service from jQuery I’m going to use REST web service. For the list of service types and factories supported in SharePoint you can visit the link in MSDN. You can download source code from the link given at the end of the post.

Prepare the service to call from jQuery

Consider developing a service as described in my earlier post with the following changes:

  • For  using json I’ve used REST service factory ‘Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory’ as shown below. You can use SOAP factory but you then need to parse data in different way.
    <%@ ServiceHost Language="C#" Debug="true"
    Service="AccessSPServiceFromJQuery.MyService, $SharePoint.Project.AssemblyFullName$"
    CodeBehind="MyService.svc.cs"
    Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0,
    Culture=neutral, PublicKeyToken=71e9bce111e9429c"
    %>


  • Next you need to specify the return type to json in the service interface as shown below. I’ve specified both request and response type to json in WebInvoke attribute:

    [ServiceContract]
    public interface IMyService
    {
    [OperationContract]
    [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    List<Product> SearchProduct(string productName);


    [OperationContract]
    [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    bool Save(Product product);
    }

One thing to notice here is that you can’t access the service in browser with mex endpoint. For example if you service is http://myserver/myservice.svc, then the url http://myserver/myservice.svc/mex will not work for service created with MultipleBaseAddressWebServiceHostFactory.
 

Call Service with jQuery

The next step is to call the service with jQuery. The url of the service to be used in jQuery will be service url and method name. For example if you service url is ‘/_vti_bin/AccessSPServiceFromJQuery/MyService.svc’ and the method name you want to invoke is ‘Search’ then the full url will be ‘/_vti_bin/AccessSPServiceFromJQuery/MyService.svc/Search’. As shown in the code below, you can invoke the service Search by passing the parameter in data field of ajax call of jquery

function getProductFromService(searchText) {
try {
$.ajax({
type: "GET",
url: '/_vti_bin/AccessSPServiceFromJQuery/MyService.svc/SearchProduct',
contentType: "application/json; charset=utf-8",
data: { "productName": searchText },
dataType: 'json',
success: function (msg) {
WCFServiceGetSucceeded(msg);
},
error: WCFServiceGetFailed
});
}
catch (e) {

alert('error invoking service.get()' + e);
}
}
function WCFServiceGetSucceeded(result) {
alert('success');
}
function WCFServiceGetFailed(error) {
alert('Service Failed.');
}

Download and use code

I’ve uploaded the code for this post in my skydrive. You can download the code from the link below. To use the code please ensure you have internet connection as I’ve used jqery from Microsoft CDN. The search functionality get all products matching name. You can try to search just by typing a single character. You can debug and test the code. In save I’ve just shown you can pass value from browser to service using POST method.