Monday, June 20, 2016

What is the difference between Site Definition and Site Template?

Site Definition

Site Definition can be said to be the foundation for building a site in SharePoint, it contains 
all the artifacts that are needed for the site. A Site Definition can contain multiple site definition 
configuration. It is a collection of XML (using CAML) and ASPX pages. Each site definition consists 
of a combination of files that are placed in the %ProgramFiles%\Common 
Files\Microsoft Shared\web server extensions\14\TEMPLATE\SiteTemplatessub folders of SharePoint 
Foundation servers during installation of SharePoint Foundation. The XML markup in the site definition files
 may include references to files in other sub folders of %ProgramFiles%\
Common Files\Microsoft Shared\web server extensions\14\TEMPLATE, including .xml, .aspx, .ascx and 
.master page files, in addition to document template files (.dot, .html) and content files (.gif, .doc). 
The files related to the Site Definition are stored in the file system of the server and not in the content database.

Advantages of Site Definition
  • The Site Template is deployed to the file system and hence it is much faster
  • A high level of list customization is possible by making changes to the Schema.xml file
  • Certain kinds of customization to sites or lists require use of site definitions, such as introducing new file types, defining view styles, or modifying the Edit menu.
Disadvantages of Site Definition
  • The effort needed is much more than creating a site template
  • Once deployed making changes is difficult
  • Anything other than adding code can break the site definition
  • One cannot make use of the SharePoint Theme
  • Users cannot create two lists of the same time having different content
  • The user needs to have permission to access the file system
The site definitions that can be used to create a new custom site definition are as follows:
  • STS - includes definition for Blank Site, Team Site and Document Workspace
  • MPS - includes definition for Blank Meeting Workspace, Basic Meeting Workspace, Decision Meeting Workspace, Social Meeting Workspace and Multipage Meeting Workspace
  • BLOG - includes definition for Blogs
  • SGS - includes definition for Group Work Site
There are other site definitions but they cannot be used to create a custom site definition, which are as follows:
  • CentralAdmin - this provides the site definition for the central admin site
  • TenantAdmin - this provides the site definition for the site hosting features
  • Wiki - this provides the site definition for the legacy wiki sites
  • Global - this is used to initialize all the other site definitions
The two most important XML files that govern the configuration and structure are as follows:
  • WebTemp*.xml
    Identifies the site definition and configuration and how the UI will look.
    The built-in WebTemp.xml file and any supplemental WebTemp*.xml files that may have been deployed, specify which site definition configurations are available for creating sites. If you are creating a custom site definition and do not edit the original WebTemp.xml file, instead create a custom WebTemp*.xml file then SharePoint Foundation merges the contents of all WebTemp*.xml files when showing available site definition configurations in the UI. This simplifies installing and uninstalling site definitions, because their contents do not have to be merged into one WebTemp.xml file.

    Location: %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\1033\XML
  • Onet.xml
    Onet.xml defines the top navigation and Quick Launch areas, specifies a basic set of list types that are available for creation, specifies document templates and their file types and itemizes the files and "all user" Web Parts that are available for use in site configurations. The global Onet.xml file, from which all other Onet.xml files inherit, defines the base types for lists, which include Generic List, Document Library, Discussion Forum, Vote or Survey, and Issues List. In addition, Onet.xml uses Configuration elements to define the site definition configurations in a site definition (such as STS and BLOG) and Module elements to define the modules in each site definition configuration.

    Location: %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\SiteDefinitions\site_type\XML


Site Template
On the other hand Site Template is a package which contains all the changes made to the site from the base site definition used to create the site. They are stored in a file with the extension of .stp which can be created from within the site. The Site Template package are stored in a CAB based file which can be uploaded or downloaded from a site.

Advantages of Site Template
  • Site Template is easy to create
  • Almost every changes made to the site can be preserved in the template
  • Site Templates can be modified without affecting the other sites created using the template
  • It is easy to deploy
Disadvantages of Site Template
  • It is not created in a development environment
  • If the Site Definition on which the Site Template has been created does not exist in the server the site template will fail
  • It is less efficient in large environments

User Information List in SharePoint 2013

What is User Information List?
As per the Name SharePoint User Information List stores information about a user by having some metadata set up for the user. Some examples are User Picture, Email, DisplayName, LoginName etc. For a complete list of fields, see further down this blogpost under "User Information List Fields".
When a user get added in User Information List?
When we grant any user permissions to a user, they are added automatically to the hidden User Information list a new item will be created in the User Information List storing some information about the user.
Even though if we grant access to any active directory group the group gets added to the hidden User Information list as well but the user does not get added until they access the site. (As an example, I granted an AD group permissions to my site & only the AD group showed up in the hidden User Information list not the users
It has been changed little bit in SharePoint 2013. As it shows user in list as soon as I give them permission to site regardless of they logon or not
Where the User Information details are used in SharePoint
When a user add/create or edit an item, documents or pages SharePoint will display the Created By or Last modified by details for the users and these all comes from the SharePoint User Information List
URL for User Information List SP 2010 ?
http://siteurl/_catalogs/users/detail.aspx - If you want to see the detail view of only Users in the list.
http://siteurl/_catalogs/users/simple.aspx - The blow URL will show the simple view of only Users in the List
http://siteurl/_catalogs/users/allgroups.aspx - This will provide all the groups without users available in Site.
URL for User Information List SharePoint 2013?
http://siteurl/_catalogs/users/detail.aspx - If you want to see the detail view of only Users in the list.
http://siteurl/_catalogs/users/simple.aspx - The blow URL will show the simple view of only Users in the List
http://siteurl/_catalogs/users/allgroups.aspx - This will provide all the groups without users available in
http://siteurl/_layouts/15/people.aspx?MembershipGroupId=0
URL for User Information List SharePoint online, O365

Or
http://siteurl/_layouts/15/people.aspx?MembershipGroupId=0
Note : /_catalogs folder is not mapped as virtual folder in IIS, like /_layouts, /settings.aspx or other application pages that we have in SharePoint site etc, i.e. it will work only on the root site.
Here the important thing is that these endless Users, AllUsers, SiteUsers, etc properties of SPWeb and SPSite, which may return different results depending on the context site, should not mislead you: users are created on site collection level.   
User Information List is a special one but still is a list and is bound to the web scope. So it is stored only in the root web of each site collection and you wouldn't find it in any subweb
In theory this list should be updated with user profile synchronization as well, but at first SharePoint may be used without user profiles, and second because of a lot of bugs in this process, on practice the most reliable way to force synchronization between user profiles and user information list is to delete user from the list explicitly and call SPWeb.EnsureUser(). We had similar situation and it was the only method which really worked (in our case it was more tricky: samAccountName of the user account in AD was changed, but as SID remained the same, Sharepoint still showed old account name).
If there is some users who’s details are showing differently in SharePoint than its AD value
You can try to sync the user profile with user Information List by below given Power shell script.
To fix the issue run the PowerShell as below. abcDomainName\pqrUserLoginId ---> abc is the domain and pqr is the user login.
$web=Get-SPWeb ...web URL...
$web|Set-SPUser -identity "abcDomainName\pqrUserLoginId" -SyncFromAD

The problem is the UserInformationList is stored in AllUserData table. This is not the UserInfo table. It is absolutely different portion of data. You can see its data by navigating to http://<SiteCollectionUrl>/_catalogs/users/detail.aspx. It is the site (Web scope) level data and the UserInformationList (hidden list) is created for the Root Web of each site collection. While UserInfo stores data of the site collection level. Information in UserInfo table can be different fromUserInformationList. So if i get the user from PowerShel I get the right display name.

$web = Get-SPWeb -Identity 'WebUrl'
$user = $web | Get-SPUser -Identity 'login'
$user.DisplayName

If I Remove users from User Information List


We can remove a user from the User Information List (UIL) in a site collection from SharePoint 2010 and 2013. SharePoint stores user information in the UIL to extract data when this user is being searched by the people picker, the people picker extracts information from multiple locations:
– The User Information List
– Active Directory

The people picker does not extract information from the User Profile Service Application (UPSA). The UPSA syncs information from the AD and updates the UIL but it does not delete the user from it.

For example if I will delete myself from the Active Directory and navigate back to SharePoint to see what happened.
– I can no longer log on with “myLogInName”
– I can still find “myLogInName” with the people picker.
– The permissions are still visible
I want to delete myLogInName user from the Site Collection so this user won’t be found by the people picker and the permissions will be deleted.

Solution
I can’t just click on the user and delete him because I’ll be redirected to the My Site (the My Site will be scheduled for deletion in 14 days by the My Site Cleanup Timer Job).
You will have to add the following right behind the URL
SharePoint 2010
<URL>/_layouts/people.aspx?MembershipGroupId=0

and click on “Actions –> Delete Users from Site Collection
After that
I can now
– no longer log on with “myLogInName”
– no longer find him using the people picker
– no longer find his permissions because they have been deleted
Downside is that you’ll receive the following error while clicking on this user at documents

With the following information from the ULS Viewer
System.ArgumentException: User cannot be found.
at Microsoft.SharePoint.SPList.GetItemById(String strId, Int32 id, String strRootFolder, Boolean cacheRowsetAndId, String strViewFields, Boolean bDatesInUtc)
at Microsoft.SharePoint.SPContext.get_Item()

Deleting users from UIL’s in bulk and across Site Collections
Please read the following blog from Nico Martens if you would like to delete users in bulk with PowerShell.
http://sharepointrelated.com/2012/10/11/remove-bulk-users-from-user-information-list-people-picker/

Timer Job that is working behind the User Information List?
To synchronize the User Profile user Data with user Information List there are two timer jobs that are responsible
  1. 1.      User Profile to SharePoint Quick Sync and
  2. 2.      User Profile to SharePoint Full Sync,
Can I set Alert on SharePoint User information list? Or Can I Track changes to the SharePoint User Information list.
How do you track the changes in "User Information List" without using any custom code? One way is to enable auditing under site collection administration for "Editing users and permissions". However this add an extra load to the database and may result in performance issues. Moreover his requirement was to track only when a user is added or removed from site collection. 
Another approached is to setup alerts. However, the User Information List does not have any option to setup alerts or go to setting etc as normal lists. So how can we configure alerts on the list?
1. Our first requirement was to get the GUID. To get this we queried dbo.Lists table in the content database holding this site collection.

2. The query should be: Select tp_ID From Lists with(NoLock)where tp_Title = 'User Information List'

3. Make a note of this ID, Now go to any other list in the top site in your site collection and click on Alert Me under Actions.

4. In the next page in URL remove the contents after ?List= and add the GUID noted in step 3.

5. Press enter and now you will find that the fields are populated with User Information List and you can create the alerts.
It is not possible to add event handlers to the user info list ?
 No, we cannot attach any event handler to User Information List. Please check the MS details on that on this article (http://msdn.microsoft.com/en-us/library/aa979520.aspx), we know that  “Lists:List events do not fire on the UserInfo list.”
       Another asynchronous was discussed in this post below:       we can think to create a service to monitor the change inUserInfo list, or get the modification logs from audit information is also a solid alternative.

Please see this following thread:

How user Information list is linked with SharePoint User Profile Service?
To keep all the information in the user information lists up to data with User profile and user Information list is a task that is handled by the Profile Synchronization and the Quick Profile Synchronization timer jobs. By default the first job runs once every hour, the second one runs every couple of minutes and is incremental. The first time user data is replicated from the user profile to the user information list of a site a full update is needed. So the Profile Synchronization job needs to run in order to get the data replicated to the site and this may take up to an hour. If information about a user is already stored in the user information list and the information changes in the user profile it will be synchronized with the data in the site collection by the  Quick Profile Synchronization job.
You can also kick off the profile synchronization jobs by running the stsadm sync command.
  stsadm -o sync

If you believe that information is not synced between the user profiles and the user information lists in one or more sites you can request a list of content databases that have not been synchronized for x number of days by using the following stsadm sync command.
 stsadm -o sync -listolddatabases <x number of days>
 If one or more content databases show up in this list you can clean up the sync list so they can be added to the list again.
 stsadm -o sync -deleteolddatabases <x number of days>
 You can also use the sync command to change the schedule for the synchronization job.
For more information on the stsadm sync command have a look here http://technet.microsoft.com/en-us/library/cc263196.aspx.
To synchronize the User Profile user Data with user Information List there are two timer jobs that are responsible
  1. 3.      User Profile to SharePoint Quick Sync and
  2. 4.      User Profile to SharePoint Full Sync,
That synchronize the User Profile database information with the UIL. Sometimes this stops working (properly) and in that case you need to run:
stsadm -o sync -listolddatabases 0
stsadm -o sync -deleteolddatabases 0
The first command will list Content Databases that haven't had the UPA -> UIL sync occur in 0 or more days. The second command will delete the records corresponding to those databases (it doesn't delete databases/end user data).
If still the issue is there you can delete the user from user Information list and run the user profile sync again to fix the issue.
How to access User information list using Server Object model?
// Get the List Object for User Information List
SPList userInformationList = SPContext.Current.Web.SiteUserInfoList;
// Get the Object of current logged in user
SPUser user = SPContext.Current.Web.EnsureUser(@"web");
// Here is actual User Information is within this SPListItem
SPListItem userItem = userInformationList.Items.GetItemById(user.ID);
The above code will give you the SPListItem object which links to the currently logged in user (the one executing the request) and you have almost all the details about the user you can play around it and user it further.
You can then work with the SPListItem object like normal to get or set the properties like this:
string userPictureURL = userItem["Picture"].ToString();


How to access User Information list using Client object model?
Here is the example of to get current log in user Id and show user Information by fetching from user Information list.
var contextObj = new SP.ClientContext.get_current();
    var webObj = contextObj.get_web();

    var userInfoListObj = webObj.get_siteUserInfoList();

    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml('<View><Query><Where><Eq><FieldRef Name=\'ID\' />' +
                                '<Value Type=\'Number\'>' + userId + '</Value></Eq>' +
                                '</Where></Query><RowLimit>1</RowLimit></View>');

    this.userInfoListObj= userInfoListObj.getItems(camlQuery);

    contextObj.load(this.userListItem);

    contextObj.executeQueryAsync(
            Function.createDelegate(this, onSucceeded),
            Function.createDelegate(this, onFailed));

The onSucceeded function is called when the query runs successfully, otherwise the onFailed function will be executed.
function onSuceeded(sender, eventArgs)
{
        var item = this.userListItem.itemAt(0);
        var name = item.get_item('Name');
        var userName = "Name";

        if (name) {
            userName = name;
        }

        alert(userName);
}

We need to execute the code after SP.js is loaded SP.SOD.executeOrDelayUntilScriptLoaded(LoadUserInfo, 'SP.js');
How to access User information list for SharePoint online Site?
/_catalogs/users/detail.aspx is work in both Onpremise and SharePoint Online
How to access User Information list using powershell scripts.
You can write a PowerShell script(named ListWebUserInformationListItems.ps1) as following:
 # Run with SharePoint 2010 Management Shell
$webUrl = Read-Host "Enter the web url"
$web = Get-SPWeb $webUrl
$list = $web.Lists["User Information List"]
$query = New-Object Microsoft.SharePoint.SPQuery
$queryCamlString = '<Query><OrderBy><FieldRef Name="Title" Ascending="True" /></OrderBy></Query>'
$query.Query = $queryCamlString
$userInformationListItems = $list.GetItems($query)
foreach($userInformationListItem in $userInformationListItems)
{
    echo $userInformationListItem.Title
}



****************************************************************************************************************

update user information list

SPWeb web = properties.OpenWeb();
           web.AllowUnsafeUpdates = true;

           SPList list = web.Lists["Távollétek"];
           SPListItem item = properties.ListItem;

           SPSite site = new SPSite("http://sp2010/sites/demo");
           SPWeb kezdo = site.OpenWeb();
           SPList felhasznalok = kezdo.Lists["User Information list"];
           
           
           string userReszleg = string.Empty;
           string nev = item["Name"].ToString();
           foreach (SPListItem felList in felhasznalok.Items)
           {
               if (nev == felList["Name"].ToString())
               {
                   userReszleg = felList["Department"].ToString();
               }
           }
           item["Department"] = userReszleg.ToString();
           item.Update();
           this.EventFiringEnabled = true;
 
 

SharePoint User Profiles - Internal Names

Two types of User Profiles:
1. WSS Profile - can be accessed from Welcome User > My Settings page (_layouts/userdisp.aspx?.......)


User Information List
Display Name
Internal Name
AccountName
First nameFirstName
Last nameLastName
NameTitle
Work phoneWorkPhone
OfficeOffice
DepartmentDepartment
TitleJobTitle
Work e-mailEMail
User nameUserName


2. MOSS profile - can be accessed from My Site (../Person.aspx?....). The MOSS profiles are created when users are imported into the system from AD or LDAP.


SSP User Profile
Display Name
Internal Name
Account nameAccountName
First nameFirstName
Last nameLastName
NamePreferredName
Work phoneWorkPhone
OfficeOffice
DepartmentDepartment
TitleTitle
Work e-mailWorkEmail


Basically, there are two MOSS Timer jobs that control the replication of the user profiles per web application. These jobs can be found from Central Administration -> Operations -> Timer Job definitions.

1. Profile Synchronization - updates the WSS profiles.
2. Quick Profile Synchronization - updates the MOSS profiles.

******************************************************************************************************************
How to Access and Update User Information List Programmatically.

To acces the hidden User Information List list of a SharePoint site (only accessible by administrators), the best way is to use the SiteUserInfoList property of the SPWeb object as in the following example:



// Button1- title and Internal name of User Information list



protected void Button1_Click(object sender, EventArgs e)

        {



            DataTable dtt = new DataTable();

            dtt.Columns.Add("Title ", typeof(string));

            dtt.Columns.Add("InternalName", typeof(string));





            SPSecurity.RunWithElevatedPrivileges(delegate()

            {

                using (SPSite site = new SPSite("http://abc/"))

                {

                    using (SPWeb web = site.OpenWeb())

                    {

                        SPList listUserInfo = web.SiteUserInfoList;

                        SPFieldCollection fieldColl = listUserInfo.Fields;

                        foreach (SPField field in fieldColl)

                        {

                            Console.WriteLine("Name:{0} - Type:{1}", field.Title, field.TypeAsString);



                            dtt.NewRow();

                            //dtt.Rows.Add(words[i], words2[i], words3[i]);

                            //dtt.Rows.Add(a, b, c, txt4,txt5,txt6,txt7,txt8,txt9,txt10);

                            dtt.Rows.Add(field.Title, field.InternalName);

                        }



                        GridView1.DataSource = dtt;

                        GridView1.DataBind();

                    }

                }

            });

        }



// Button2 – fetch record from user information list





        protected void Button2_Click(object sender, EventArgs e)

        {



            DataTable dt = new DataTable();

            dt.Columns.Add("ID", typeof(string));

            dt.Columns.Add("Title", typeof(string));

            dt.Columns.Add("User Name", typeof(string));

            dt.Columns.Add("Email", typeof(string));





            using (SPSite mySiteCollection = new SPSite("http://abc/"))

                {

                    using (SPWeb mySite = mySiteCollection.OpenWeb(mySiteCollection.RootWeb.ID))

                    {

                        SPList usersList = mySite.SiteUserInfoList;



                        SPListItemCollection oSpListCln = usersList.Items;



                        //iterate through all the items in itemcollection object

                        foreach (SPListItem item in oSpListCln)

                        {

                            dt.NewRow();

                           

     dt.Rows.Add(item["ID"], item["Title"], item["UserName"], item["EMail"]);

                        }



                        GridView2.DataSource = dt;

                        GridView2.DataBind();

                    }

                }

        }





// Button3 – update record from user information list


        protected void Button3_Click(object sender, EventArgs e)
        {



            using (SPSite mySiteCollection = new SPSite("http://abc/"))

            {

                using (SPWeb mySite = mySiteCollection.OpenWeb(mySiteCollection.RootWeb.ID))

                {

                    mySite.AllowUnsafeUpdates = true;

                    SPList usersList = mySite.SiteUserInfoList;



//in ID(column) have record which contain 5(value) number                   



SPListItem item = usersList.GetItemById(Convert.ToInt32("5"));



                    item["EMail"] = "abc@hotmail.com";



                    item.Update();

                }

            }

  }