Monday, December 16, 2013

Unknown server tag 'SharePoint:ScriptBlock'.

Error: Unknown server tag 'SharePoint:ScriptBlock'.

Issue: You will get above error when you use the application page in SharePoint 2013 using <SharePoint:ScriptBlock> and try to use that in SharePoint 2010.

Cause: ScriptBlock class is not available in SharePoint 2010 & 2007.

Resolution: Replace the block with <script type="text/javascript">

Sunday, December 15, 2013

This operation can be performed only on a computer that is joined to a server farm by users who have permissions in SQL Server to read from the configuration database. To connect this server to the server farm, use the SharePoint Products Configuration Wizard, located on the Start menu in Microsoft SharePoint 2010 Products.

Error: This operation can be performed only on a computer that is joined to a server farm by users who have permissions in SQL Server to read from the configuration database. To connect this server to the server farm, use the SharePoint Products Configuration Wizard, located on the Start menu in Microsoft SharePoint 2010 Products.

Cause: Got above error when I tried to access my SharePoint site and Central administration. The error says that current user is not able to access the database. Everything was working fine until I've crashed my VMWare and restarted.

Resolution:
1. Open Services.msc
2. Restarted SQL Server (SHAREPOINT) service
3. Noticed that the following services was disabled. Enabled both the service.
SQL Server Agent (SHAREPOINT)
SQL Server Browser

Friday, December 6, 2013

Close modal dialog after page validation passes

Requirement:
To open the default Create Group (newgrp.aspx) page as a dialog box from our custom page on a button click. Close the modal dialog box after page submits.
We created a copy of newgrp.aspx page and used that page to achieve this.

Issues we had:
1. Default “create group” page redirects to the people.aspx page after successful page submission.
2. Closing the dialog on Window.unload worked fine, but the dialog got closed even when the validation fails as validation refresh the page.

Solution:
Create an HTTPModule to check the current page and previous page details though HTTP events. Below is the HttpModule code we used to achieve this.

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DSPModule
{
    public class DynamicModule : IHttpModule
    {

        string strParentPageURL = string.Empty;
        string strCurrentPageURL = string.Empty;

        public DynamicModule()
        {
        }

        public String ModuleName
        {
            get { return "DSPDynamicModule"; }
        }

        // In the Init function, register for HttpApplication events by adding your handlers.
        public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
        }
        void context_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            HttpContext currentContext = HttpContext.Current;
            Page page = currentContext.CurrentHandler as Page;
            if (page != null)
            {
                page.LoadComplete += new EventHandler(page_LoadComplete);
            }
        }
        void page_LoadComplete(object sender, EventArgs e)
        {        
             HttpContext currentContext = HttpContext.Current;
             if(currentContext.Request.UrlReferrer != null)
                strParentPageURL = currentContext.Request.UrlReferrer.ToString().Trim().ToUpper();

             strCurrentPageURL = currentContext.Request.Url.AbsolutePath.ToString().Trim().ToUpper();
             if (strParentPageURL.Contains("/_LAYOUTS/DSPHANDLER/DSPNEWGRP.ASPX") && strCurrentPageURL.Contains("/_LAYOUTS/PEOPLE.ASPX") && strParentPageURL.Contains("?ISDLG=1"))
             {
                 HttpContext.Current.Response.Write("<script type='text/javascript'>window.frameElement.commitPopup();</script>");
                 HttpContext.Current.Response.Flush();
                 HttpContext.Current.Response.End();
             }
        }
        public void Dispose()
        {

        }
    }
}

Make sure that you add the following entry in the web.config file of the web application at path "configuration/system.webServer/modules"
<add name="DSPDynamicModule" type=" DSPModule.DynamicModule, DSPModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=fa63464975c1a198" />

Feel free to discuss if you have better way of doing this.


Thursday, October 17, 2013

Move dll to Gac using powershell

Developers during debugging their code, move their dll to gac and reset IIS. To automate this and save time, we can create a powershell script.


[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
$publish = New-Object System.EnterpriseServices.Internal.Publish $publish.GacInstall("D:\Prasath\Workouts\Lookup\bin\Debug\SP.MyContent.dll")
iisreset

Save the above code as "somefilename.ps1"
To execute, right click the saved file and select "Run with Powershell"

Tuesday, October 15, 2013

Connect application service to a web application programmatically

The following code will connect a custom user profile application service to a web application.
(SharePoint 2010)


           SPSite site = new SPSite("http://current site url");

           //Get all Service Proxies in the farm
           SPServiceProxyCollection farmServices = SPFarm.Local.ServiceProxies;

            // Iterate all the proxies
            foreach (SPServiceProxy service in farmServices)
            {
                SPServiceApplicationProxyCollection serviceApplicationColl = service.ApplicationProxies;
                foreach (SPServiceApplicationProxy serviceApp in serviceApplicationColl.OfType<SPServiceApplicationProxy>())
                {
                    if (serviceApp.DisplayName == "My Custom User Profile" && serviceApp.TypeName.ToLower().Contains("user profile service"))
                    {
                        //Add the service proxy to the web application
                        site.WebApplication.ServiceApplicationProxyGroup.Add(serviceApp);
                       
                         // update the application proxy group
                        site.WebApplication.ServiceApplicationProxyGroup.Update();

                         //update the web application
                        site.WebApplication.Update();
                 
                    }
                }
            }


Thursday, October 3, 2013

Check SharePoint Version and read User Profile Property value programmatically

[SharePoint 2010; SharePoint 2013]


using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.Office.Server.UserProfiles;
using System.Linq;
using System.Collections;

namespace GetProfileProperty
{
    class Program
    {
        //Declare SKU keys of each SharePoint version
        const string SHAREPOINT2010FOUNDATION = "BEED1F75-C398-4447-AEF1-E66E1F0DF91E";
        const string SHAREPOINT2010STANDARD = "3FDFBCC8-B3E4-4482-91FA-122C6432805C";
        const string SHAREPOINT2010ENTERPRISE = "D5595F62-449B-4061-B0B2-0CBAD410BB51";
        const string SHAREPOINT2013STANDARD = "C5D855EE-F32B-4A1C-97A8-F0A28CE02F9C";
        const string SHAREPOINT2013ENTERPRISE = "B7D84C2B-0754-49E4-B7BE-7EE321DCE0A9";
        const string SHAREPOINT2013FOUNDATION = "9FF54EBC-8C12-47D7-854F-3865D4BE8118";
           

        static void Main(string[] args)
        {
            string _skuID = string.Empty;
            string CurrentSPVersion = string.Empty;
            bool IsUserProfileServiceEnabled = false;
            string result = string.Empty;
            string PropertyName = "Unit System"; //User profile property name to get the value
            string siteURL = "http://siteURL";
            SPSite site = new SPSite(siteURL);

            SPFarm farm = site.WebApplication.Farm;

            //Get the SharePoint Products installed in current Farm
            IEnumerable<Guid> _guid = farm.Products;

            //Iterate each product to find the version installed
            foreach (var item in _guid)
            {
                _skuID = item.ToString();
                //Condition true if the version installed is Enterprise/Standard
                if (_skuID.Equals(SHAREPOINT2010ENTERPRISE, StringComparison.CurrentCultureIgnoreCase) || _skuID.Equals(SHAREPOINT2010STANDARD, StringComparison.CurrentCultureIgnoreCase) || _skuID.Equals(SHAREPOINT2013ENTERPRISE, StringComparison.CurrentCultureIgnoreCase) || _skuID.Equals(SHAREPOINT2013STANDARD, StringComparison.CurrentCultureIgnoreCase))
                {
                    CurrentSPVersion = "SPServer";
                    break;
                }
                //Condition true if the version installed is Foundation
                if (_skuID.Equals(SHAREPOINT2010FOUNDATION, StringComparison.CurrentCultureIgnoreCase) || _skuID.Equals(SHAREPOINT2013FOUNDATION, StringComparison.CurrentCultureIgnoreCase))
                {
                    CurrentSPVersion = "SPFoundation";
                }

            }
            if (CurrentSPVersion == "SPServer")
            {
                    //Get the service applications installed in the web application
                    Microsoft.SharePoint.SPServiceContext spServiceContext = Microsoft.SharePoint.SPServiceContext.GetContext(site);
                    IEnumerable<SPServiceApplicationProxy> proxies = site.WebApplication.ServiceApplicationProxyGroup.Proxies;

                    foreach (var services in proxies)
                    {
                        //Check if the User Profile Service is enabled
                        if (services.TypeName == "User Profile Service Application Proxy")
                        {
                            IsUserProfileServiceEnabled = true;
                        }
                    }
                    if (IsUserProfileServiceEnabled)
                    {
                        Console.WriteLine("User profile for this web application is enabled");
                        Console.WriteLine(GetUserProfilePropertyValue(siteURL, PropertyName, true));
                    }
                    else
                    {
                        Console.WriteLine("User profile for this web application is NOT enabled");
                    }
                 
            }
            if (CurrentSPVersion == "SPFoundation")
            {
                Console.WriteLine("You have SP Foundation");
            }
         
        }

        /// <summary>
        /// Get the User Profile Property value
        /// </summary>
        /// <param name="property">User Profile Propery Name</param>
        /// <param name="isUserProfileEnabled">boolean</param>
        /// <returns></returns>
        public static string GetUserProfilePropertyValue(string siteURL, string property, bool isUserProfileEnabled)
        {
            string result = "";
            string CurrentWeb =siteURL;
            try
            {
                //Get the value from My Settings/User Information List if User Profile Service is not enabled
                if (!isUserProfileEnabled)
                {
                    using (SPSite site = new SPSite(CurrentWeb))
                    {
                        using (SPWeb web = site.OpenWeb())
                        {
                            SPList userInfoList = web.SiteUserInfoList;
                            SPUser user = web.EnsureUser(@"domainname\username");
                            SPListItem userItem = userInfoList.Items.GetItemById(user.ID);
                            result = userItem[property].ToString();
                        }
                    }
                }
                else
                {
                    //Read the user profile property value if user profile service application is enabled. Reads the value using User Profile Manager
                    SPSecurity.RunWithElevatedPrivileges(delegate()
                    {
                        using (SPSite site = new SPSite(CurrentWeb))
                        {
                            SPServiceContext context = SPServiceContext.GetContext(site);
                            UserProfileManager profileManager = new UserProfileManager(context);
                            string sAccount = @"domainname\username";
                            UserProfile userProfile = profileManager.GetUserProfile(sAccount);
                            ProfileSubtypePropertyManager psmanager = userProfile.Properties;

                            //Get the internal name from the display name
                            IEnumerable<string> PropertyInternalName = psmanager.Cast<ProfileSubtypeProperty>()
                                                                        .Where(r => r.DisplayName.ToLower() == property.ToLower())
                                                                        .Select(r => r.Name);
                            //Get the value of property
                            if(PropertyInternalName.Count()==1)
                                result = userProfile[PropertyInternalName.First().ToString()].Value.ToString();
                        }

                    });
                 
                }

            }
            catch (Exception)
            {
           
            }
            return result;
        }

    }
}

PS: Above is a console application and some of the values are hard-coded, you need to change the code accordingly to your requirement/environment.

Tags:
- programmatically retrieve user profile property value using property display name
- Check SharePoint version/edition programmatically


Add custom profile property in User Information List

Using SharePoint 2010;

Requirement: To add/read a custom profile property in My Settings page/ User Information List.

To read profile property and values:

            string fieldName = string.Empty;
            using (SPSite site = new SPSite("http://SiteURL"))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList userInfoList = web.SiteUserInfoList;
                    SPUser user = SPContext.Current.Web.EnsureUser(login);
                    SPListItem userItem = userInfoList.Items.GetItemById(user.ID);

                    foreach (SPField field in userInfoList.Fields)
                    {
                        fieldName = field.Title;
                        Console.WriteLine(fieldName + "\t " + userItem[fieldName]);
                    }
                }
            }

To add a custom profile property:

//Create custom profile property
   SPField newTextfield = userInfoList.Fields.CreateNewField(SPFieldType.Text.ToString(), "Personal Web Site");                  
  userInfoList.Fields.Add(newTextfield);
  userInfoList.Update();

Few facts about My Settings Page:

1. Keep in mind that “My Profile” and “My Settings” are two completely different things.  My Profile is looking at information directly from the Profile Database.  My Settings is site specific, and is looking at information at the current site.

2. If the User Profile service application is not enabled when you visit the site initially, your data is retrieved from the Active directory and stored in the content database "User Information List"

3. User Information List is a hidden list. You can access it programmatically or using PowerShell.

4. In People and Group page (http://<sitecollection>/_layouts/people.aspx), it appears as a SharePoint list. Fields can be added or removed to suit the business needs.

5. List events are not raised on the User Information list type. There is no resolution as of now as per Microsoft. Refer: http://msdn.microsoft.com/en-us/library/aa979520.aspx

6. My Settings is the local site collection profile. The UserInfo table (DB instance of ‘User Information List’) is a table stored in the Content Database for each Site Collection.

7. If User Profile is not configured and there are no My sites, then we can use User Information List available per each Site Collection where minimal data is available, such as AD account, SID, Email, First name, last name.

8. Custom properties in User Information List can be added from ‘People and Groups’ site collection page by Site Collection Administrators.