Saturday, August 25, 2012

Ensure User SharePoint 2010 using web service


SharePoint is a product from Microsoft that is being used in many of the organization today to improve the business efficiency. The product provides capability to business like Sites, Communities, Content, Composites, Insights and Search.
Also it offer three different ways of accessing the SharePoint data as follows
1.       SharePoint site web user interface
2.       Server Object Model
3.       Client Object Model
The security is well handled in SharePoint itself. If user accesses the data using any of the way that mentioned above, first it applies the security rule then SharePoint will decide whether the request can be processed further or not. But there are some security rule applied against Client Object Model since this concept can be used from a client computer where the SharePoint is not installed or via web service. See all the web services here.
Now we discuss about Ensure User: Checks whether the specified logon name belongs to a valid user of the website, and if the logon name does not already exist, adds it to the website.  Server and Client object models directly exposes a method (Web.EnsureUser) to add or verify the user in the Website. Also this is to let you all know that a user (AD DS/LDAP/Membership Provider) can be added in the SharePoint userinfo list which is hidden using SharePoint web service(Web service reference: http://Site/_vti_bin/People.asmx).

People Web Service: Provides classes that can be used to associate user identifiers (IDs) with security groups for SharePoint Foundation Web site permissions. User IDs are validated against Active Directory Domain Services (AD°DS) as well as various role or membership providers. SPGroup security information may also be stored in a collection of cross-site groups for the site collection.
Class: People  Structures: PrincipalInfo Enumerations: SPPrincipalType
Class People that exposes member are here

Method People.ResolvePrincipals is used for adding user in to SharePoint userinfo list. User verification is performed against a directory or user list, such as Active Directory Domain Services (AD DS), a Lightweight Directory Access Protocol (LDAP) directory, some other role or membership providers, or another form of user list.

Parameters

principalKeys
Type: System.String[]
Logon name of the principal.
principalType
Type: [People Web service].SPPrincipalType
SPPrincipalType object that specifies user scope and other information.
addToUserInfoList
Type: System.Boolean
Indicates whether to add the principal to a SPUserCollection that is associated with the Web site.

Return Value

Type: [People Web service].PrincipalInfo[]
A list of PrincipalInfo objects that is indexed and accessed by the logon name in the AccountName() field.


        static string WS_EnsureUser(string domain, string loginName)
        {
            string[] userLogin = new string[] { domain + "\\" + loginName };
            string userInfo = string.Empty;
            try
            {
                WSPeople.People ppl = new WSPeople.People();
                ppl.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
                ppl.Url = "http://kmsnet:5050/_vti_bin/people.asmx";

                //Get user info if already added in the site
                WSPeople.PrincipalInfo[] principalInfoUser = ppl.ResolvePrincipals(userLogin, WSPeople.SPPrincipalType.User, false);
                if (principalInfoUser[0].UserInfoID == (-1))
                {
                    //Add and Get user info if user is not added in the site
                    principalInfoUser = ppl.ResolvePrincipals(userLogin, WSPeople.SPPrincipalType.User, true);
                }
                //get SharePoint user id(unique) and user account name
                userInfo = principalInfoUser[0].UserInfoID + ";#" + principalInfoUser[0].AccountName;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in Web Service  : " + ex.Message);
            }

            return userInfo;
        }


Complete Source Code:


using System;
//Server Object Model
using Microsoft.SharePoint;
//Client Object Model
using Microsoft.SharePoint.Client;

namespace KMSNET.EnsureUser
{
    class Program
    {
        static void Main(string[] args)
        {
            string domain = "KMSNET";
            string loginName = "Senthilrajan";
            string userInfo = string.Empty;

            //Call web service to Ensure user in SharePoint site
            userInfo = WS_EnsureUser(domain, loginName);
            Console.WriteLine("\nWeb Service Returned :" + userInfo);

            //Call Client Object Model to Ensure user in SharePoint site
            userInfo = COB_EnsureUser(domain, loginName);
            Console.WriteLine("\nClient Object Model Returned :" + userInfo);

            //Call Server Object Model to Ensure user in SharePoint site
            userInfo = SOB_EnsureUser(domain, loginName);
            Console.WriteLine("\nServer Object Model Returned :" + userInfo);

            Console.ReadKey(true);            Console.WriteLine("Press any key to close....");
        }

        /// <summary>
        /// Server Object Model : Returns user ID and logon account. If user is not registered the add in to userinfor list and return the user ID and logon account
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="loginName"></param>
        /// <returns></returns>
        static string SOB_EnsureUser(string domain, string loginName)
        {
            string userLogin = (domain + "\\" + loginName);
            string userInfo = string.Empty;
            try
            {
                using (SPSite siteColl = new SPSite("http://kmsnet:5050/"))
                {
                    using (SPWeb rootWeb = siteColl.RootWeb)
                    {
                        // Allow unsafe updates required, throws exception without, if not administrator.
                        rootWeb.AllowUnsafeUpdates = true;

                        SPUser usr = rootWeb.EnsureUser(loginName);
                        userInfo = usr.ID + ";#" + usr.LoginName;

                        rootWeb.AllowUnsafeUpdates = false;
                    }
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in Server Object Model  : " + ex.Message);
            }
            return userInfo;

        }

        /// <summary>
        /// Client Object Model : Returns user ID and logon account. If user is not registered the add in to userinfor list and return the user ID and logon account
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="loginName"></param>
        /// <returns></returns>
        static string COB_EnsureUser(string domain, string loginName)
        {
            string userLogin = (domain + "\\" + loginName);
            string userInfo = string.Empty;
            try
            {
                using (ClientContext context = new ClientContext("http://kmsnet:5050/"))
                {
                    context.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
                    Web web = context.Web;

                    User usr = web.EnsureUser(userLogin);
                    context.Load(usr);
                    context.ExecuteQuery();
                    userInfo = usr.Id + ";#" + usr.LoginName;
                    context.ExecuteQuery();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in Client Object Model  : " + ex.Message);
            }
            return userInfo;
        }

        /// <summary>
        /// Web Service : Returns user ID and logon account. If user is not registered the add in to userinfor list and return the user ID and logon account
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="loginName"></param>
        /// <returns></returns>
        static string WS_EnsureUser(string domain, string loginName)
        {
            string[] userLogin = new string[] { domain + "\\" + loginName };
            string userInfo = string.Empty;
            try
            {
                WSPeople.People ppl = new WSPeople.People();
                ppl.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
                ppl.Url = "http://kmsnet:5050/vti_bin/People.asmx";

                //Get user info if already added in the site
                WSPeople.PrincipalInfo[] principalInfoUser = ppl.ResolvePrincipals(userLogin, WSPeople.SPPrincipalType.User, false);
                if (principalInfoUser[0].UserInfoID == (-1))
                {
                    //Add and Get user info if user is not added in the site
                    principalInfoUser = ppl.ResolvePrincipals(userLogin, WSPeople.SPPrincipalType.User, true);
                }
                //get SharePoint user id(unique) and user account name
                userInfo = principalInfoUser[0].UserInfoID + ";#" + principalInfoUser[0].AccountName;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in Web Service  : " + ex.Message);
            }

            return userInfo;
        }
    }
}

Monday, October 17, 2011

Alternate accessing mapping issue over internet

SharePoint is quite interesting in terms of its own features, Customization, deployment and disaster recovery. It provides good feature to add different URLs for different zones and allows extending the web application. These feature ultimately reduces the work effort of System/SharePoint Administrators and time as well. At the same time SharePoint needs some basic security configuration to perform all operation successfully. Here I would like to explain the issue and how it was resolved.

I have created a web application and added a custom managed path. The managed path type is explicit(Don’t allow to create more than a instance under this path). Then created a top level site collection under this managed path. The SharePoint portal has been published in the location network and it was working fine. After few day our customer wants to publish the SharePoint portal over internet. For public URL I have taken help from our network/IIS team to create and register the public URL. Finally I got the URL for our SharePoint portal(eg. http://spportal.mycomp.com.). I have added the public url in the custom zone and done below settings/configuration.
1. Update the host file(:\WINDOWS\system32\drivers\etc) with new host header
2. Updated the virtual directory bindings with new URL and points the default port i.e. 80.
After completing the Alternate access map settings the portal was accessible in the server. Over internet only the portal landing page(Home page) accessible but not any other Site objects (sub sites, document library..) for following reason (1. Custom managed path, 2. Site Redirection). The site objects url not been transferred as expected. Those urls points to the server IP address and port instead public url. Then I realized that the problem in the firewall setting since the Portal is working in the server but not over internet.

Error e.g.
Over internet:

Sub site URL: http://000.000.000.001:22760/en/testsite/
Folder URL : http:// 000.000.000.001:22760/en/Lists/testtbd/AllItems.aspx?RootFolder=%2fen%2fLists%2ftesttbd%2ftest&FolderCTID=&View=%7b36BC9C38%2d409D%2d469D%2d87E8%2d98F96E3A50B3%7d

In SharePoint server:
Sub site URL: http://spportal.mycomp.com/en/testsite/default.aspx
Folder URL : http://spportal.mycomp.com/en/Lists/testtbd/AllItems.aspx?RootFolder=%2fen%2fLists%2ftesttbd%2ftest&FolderCTID=&View=%7b36BC9C38%2d409D%2d469D%2d87E8%2d98F96E3A50B3%7d
Solution :
To rectify this issue I asked ISA expert to verify the ISA setting in the server. Our ISA expert diverted the request from “000.000.000.001:22760” to “spportal.mycomp.com/”. This solved our first issue.
Then we came across another problems
Issue 1:
Some of the url special characters as encoded twice in the URL. So the SharePoint object were not able access over internet.
Solution:
I have searched for solution over internet then got that “verify normalization” has to be disabled in the server. Our ISA responsible did the changes as requires.
Actually, in this case 'verify normalization' has to be disabling in the server. When the option verifies normalization is enabled, the ISA firewall will escape the URL, then escape it once more. If the second escape attempt results in a string that is different from the first string, the ISA firewall will object and deny the traffic.
Issue 2:
Finally we got another issue that “List operation(Create, Update, delete) not able to perform”. Therefore during the data modulation in the list user gets 500 server internal error and the operation goes incomplete.
Error description:
Page: 500 Server internal error. The space character in the URL has encoded twice. For e.g. (http://sitecoll/lists/test%2520/displayform.aspx?ID=10). The Space(%20) has encoded twice there the url has %2520
Solution2 :
There was some issue with WebResource.axd. It was not allowed from external. Then ISA responsible did the settings to allow WebResource.axd from external.
Now our site works as expected.
Happy working with SharePoint issues.