Showing posts with label CSharp. Show all posts
Showing posts with label CSharp. Show all posts

Thursday, May 29, 2014

Sharepoint 2010 - Strange blog URL issue with site using Variations(Multilingual site). - REALLY WEIRD ISSUE!

Scenario/Symptoms

  • We have a site with variations. English/Spanish
  • Structure
    • Main Site > en > English Blog(Add 1 or 2 sample blogs)
    • Main Site > es > Spanish Blog(Add 1 or 2 sample blogs)
  • On the "Main Site" we added a "Content Query Web Part". Apply the below given setting.
  • Click on the link of any English blog. IT WORKS FINE!!!
  • Now click on the Spanish blog link. IT SAYS "PAGE NOT FOUND"!!!
  • Another way to get this is.
    • Go to the URL of Spanish blog site.
    • You can find the blogs on the page.
    • Click on the blog link IT SAYS "PAGE NOT FOUND"!!!.
    • Or navigate to "Administrar entradas de blog"(AllPosts.aspx). This page will show all the blogs in the list. Click on the blog link IT SAYS "PAGE NOT FOUND"!!!


Cause

We added a column to the list "Post". Now this small thing was causing the whole havoc.


Solution

There are 3 ways to
  1. Either don't add any column to list "Post". => BAD ONE
  2. Copy SharePoint Designer > Lists > Estrada De Blog and paste it there with name "Post". Don't delete the folder. Just need to duplicate and rename the folder.
  3. Read the blog => Sharepoint 2010 - Solution to blog URL issue with site using Variations(Multilingual site) to see the feature stapler solution for this issue.


Hope this helps. If you have any questions or a better solution, I am all open for it. Thanks for reading the blog.

Sharepoint 2010 - Solution to blog URL issue with site using Variations(Multilingual site).

Issue

Read this blog -> Sharepoint 2010 - Strange blog URL issue with site using Variations(Multilingual site). - REALLY WEIRD ISSUE!

Solution

  • Create a Feature Stapler.
  • Set the event scope as Scope="Site" as the feature.
  • Stapler > Element.xml.
    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
        <FeatureSiteTemplateAssociation Id="edf698b1-30db-4d19-b46b-5efbb5dae9a5" TemplateName="Blog" />
    </Elements>
  • Please use the below given code as a solution for the problem.
#region System
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.Administration;
using System.IO;
using System.Linq;
#endregion

namespace FeatureStapler.VariationBlogSiteEvent
{
    /// <summary>
    /// Web Events
    /// </summary>
    public class VariationBlogSiteEvent : SPWebEventReceiver
    {
        #region Properties

        /// <summary>
        /// The site templates
        /// </summary>
        enum EnmSiteTemplate
        {
            BLOG,    //Blog Site
        }

        /// <summary>
        /// English Language
        /// </summary>
        enum EnmLangugeCode
        {
            English = 1033
        }

        #endregion

        #region Events

        /// <summary>
        /// A site was provisioned.
        /// </summary>
        public override void WebProvisioned(SPWebEventProperties properties)
        {
            base.WebProvisioned(properties);

            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    //Create a web object
                    SPWeb _web = properties.Web;

                    //Check and apply the settings
                    if (_web.WebTemplate == EnmSiteTemplate.BLOG.ToString() // If the site is a blog site
                        && _web.Language != (int)EnmLangugeCode.English) // Language Selected is not english
                    {
                        // Get the Library with correct folder
                        SPFolderCollection _folderInList = _web.Folders["Lists"].SubFolders;

                        //Find a folder with "post.aspx" & "newpost.aspx"
                        SPFolder _folderBlogNonEnglish = (from _folderX in _folderInList.Cast<SPFolder>()
                                                          let _fName = _folderX.Name
                                                          let _fCount = (from _fileX in _folderX.Files.Cast<SPFile>()
                                                                 where string.Compare( _fileX.Name , "post.aspx" , true ) == 0
                                                                select _fileX).Count()
                                                          where _fCount > 0
                                                          select _folderX).FirstOrDefault();

                        //So if any folder this properties exists
                        if (_folderBlogNonEnglish != null)
                        {
                            //The folder where file is going to come
                            SPFolder _folderBlogInEnglish = _folderBlogNonEnglish.ParentFolder.SubFolders.Add("Posts");
                            _folderBlogInEnglish.SubFolders.Add("Attachments");
                            _folderBlogInEnglish.SubFolders.Add("Post");

                            //Copy the files to new folder
                            foreach (SPFile _file in _folderBlogNonEnglish.Files)
                            {
                                _file.CopyTo(string.Format("{0}/{1}/{2}", _web.Url, _folderBlogInEnglish.Url, _file.Name), true);
                                ////Add a file
                                //_folderBlogInEnglish.Files.Add(_file.Name, File.OpenRead(_file), true);

                                // Commit 
                                _folderBlogInEnglish.Update();
                            }
                        }                       
                    }

                });
            }
            catch (Exception Exc)
            {
                SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("VariationBlogSiteEvent", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, Exc.Message, Exc.StackTrace);
            }
        }

        #endregion

    }
}



Hope this helps. If you have any questions or a better solution, I am all open for it. Thanks for reading the blog.

Thursday, September 20, 2012

Override Content Query Webpart to do on the run filteration.

Problem

In one of my recent project I had a challenge of filtering the data with localization.
The project contained 2 languages, English and Spanish. I was trying to find out the out of the box way to get this done, but no help was available.


Solution

  1. Create a new empty project in Visual Studio 2010.
  2. Add a webpart to the project. "Webpart" not "Visual Web Part".
  3. Replace the Webpart class inherited and make it "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart".
  4. Please have a look at the code below. It will have on the fly list settings and field settings applied to the webpart.
  5. Build your code and deploy it. It should work.



Source Code


#region System
using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
#endregion

// Create the Toolbar
namespace ToolBar.ToolBar
{
    [ToolboxItemAttribute(false)]
    public class ToolBar : Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart
    {
        #region Properties

        /// <summary>
        /// Root Site Name
        /// </summary>
        private string SiteUrl { get { return SPContext.Current.Site.RootWeb.Url; } }

        /// <summary>
        /// List Name
        /// </summary>
        private string ListName { get { return "ToolBar"; } }

        /// <summary>
        /// List of Url
        /// </summary>
        private string ListUrl
        {
            get
            {
                return string.Format("{0}/Lists/{1}/AllItems.aspx", SiteUrl, ListName);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// On Page Load
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            //On Load
            base.OnLoad(e);

            //General Settings
            this.AllowConnect = true;
            this.ShowUntargetedItems = false;
            this.AllowEdit = true;
            
            //this.FrameType = "NONE"; // TODO
            this.ChromeType = PartChromeType.None;
            this.ExportMode = WebPartExportMode.All;
            this.GroupByDirection = SortDirection.Desc;
            this.SortByDirection = SortDirection.Desc;
            
            this.ConnectionID = System.Guid.Empty;
            this.ListId = System.Guid.Empty;

            this.ViewFlag = "0";
            this.GroupingText = "GP Web Parts";
            this.Title = " Tool Bar";
            this.ContentTypeName = "Item";
            this.ItemStyle = "ToolBar";
            this.ServerTemplate = "100";
            this.GroupStyle = "DefaultHeader";
            this.WebUrl = "~sitecollection";
            this.Description = "Displays a dynamic view of content from your site.";
            this.Xsl = "<xsl:stylesheet xmlns:x=\"http://www.w3.org/2001/XMLSchema\" version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:cmswrt=\"http://schemas.microsoft.com/WebPart/v3/Publishing/runtime\" exclude-result-prefixes=\"xsl cmswrt x\" > <xsl:import href=\"/Style Library/XSL Style Sheets/Header.xsl\" /> <xsl:import href=\"/Style Library/XSL Style Sheets/ItemStyle.xsl\" /> <xsl:import href=\"/Style Library/XSL Style Sheets/ContentQueryMain.xsl\" /> </xsl:stylesheet>";
            this.SampleData = "<dsQueryResponse><Rows><Row Title=\"Item 1\" LinkUrl=\"http://Item1\" Group=\"Group Header\" __begincolumn=\"True\" __begingroup=\"True\" /><Row Title=\"Item 2\" LinkUrl=\"http://Item2\" __begincolumn=\"False\" __begingroup=\"False\" /><Row Title=\"Item 3\" LinkUrl=\"http://Item3\" __begincolumn=\"False\" __begingroup=\"False\" /></Rows></dsQueryResponse>";
            this.ParameterBindings = string.Empty;

            //Root Web
            using (SPWeb _web = SPContext.Current.Site.RootWeb)
            {
                //Assign the list to the CQWP
                SPList _listYCLToolBar = _web.GetListFromUrl(ListUrl);

                //Data mapping
                this.DataMappings = string.Format("Description:|LinkUrl:{2},TargetUrl,URL;|Title:{4},Title,Text;|NumComments:|PublishedDate:|PostCategory:|ImageUrlAltText:{0},Title,Text;|Author:|Language:{3},Language,Lookup;|ImageUrl:{1},Icon,URL;|Body:|"
                    , _listYCLToolBar.Fields["Title"].Id.ToString()
                    , "{" + _listYCLToolBar.Fields["Icon"].Id.ToString() + "}"
                    , "{" + _listYCLToolBar.Fields["TargetUrl"].Id.ToString() + "}"
                    , "{" + _listYCLToolBar.Fields["Language"].Id.ToString() + "}"
                    , "{" + _listYCLToolBar.Fields["Title"].Id.ToString() + "}"
                    );

                this.ListGuid = _listYCLToolBar.ID.ToString();

                this.DataMappingViewFields = string.Format("{0},URL;{1},URL;{2},Text;{3},Lookup;"
                    , "{" + _listYCLToolBar.Fields["TargetUrl"].Id.ToString() + "}"
                    , "{" + _listYCLToolBar.Fields["Icon"].Id.ToString() + "}"
                    , "{" + _listYCLToolBar.Fields["Title"].Id.ToString() + "}"
                    , "{" + _listYCLToolBar.Fields["Language"].Id.ToString() + "}"
                    );
                
                //Filter One
                this.FilterField1 = "Language";//Custom Field to get the variation work.
                this.FilterOperator1 = FilterFieldQueryOperator.Eq;
                this.FilterValue1 = System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag;
                this.FilterType1 = "Lookup";
                this.Filter1ChainingOperator = FilterChainingOperator.Or;

                this.Filter2ChainingOperator = FilterChainingOperator.Or;

                //Sorting
                this.SortByFieldType = "DateTime";
                this.SortBy = "Created";
            }            
        }

        /// <summary>
        /// Create Child Controls
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
        }

        #endregion
    }
}



Please let me know if there is any issue with this code or you can also correct me if I am wrong.

Friday, May 18, 2012

Apply "Multiple" column Group By on DataTable in C#

Goal

A few days ago a reader asked for Multiple column group by on DataTable. This blos is in reply of that question. This was my old blog Apply group by clause on Datatable in C#.

Solution

#region System
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
#endregion

namespace SampleApplication
{
    #region Enums

    /// <summary>
    /// The functions which can be used for aggreation
    /// </summary>
    public enum AggregateFunction
    {
        Sum,
        Avg,
        Count,
        Max,
        Min
    }

    #endregion

    #region Entity

    /// <summary>
    /// The class which will have properties of function to be performed and on which field
    /// </summary>
    public class DataTableAggregateFunction
    {
        /// <summary>
        /// The function to be performed
        /// </summary>
        public AggregateFunction enmFunction { get; set; }

        /// <summary>
        /// Performed for which column
        /// </summary>
        public string ColumnName { get; set; }

        /// <summary>
        /// What should be the name after output
        /// </summary>
        public string OutPutColumnName { get; set; }
    }

    #endregion
    

    public class Helper
    {
        /// <summary>
        /// Demo for Group By
        /// </summary>
        public void DemoGroupBy()
        { 
            //Gets the mock data table
            DataTable _dt = GetDataTable();

            //Add columns which you want to group by
            IList<string> _groupByColumnNames = new List<string>();
            _groupByColumnNames.Add("State");
            _groupByColumnNames.Add("City");

            //Functions you want to perform on which fields
            IList<DataTableAggregateFunction> _fieldsForCalculation = new List<DataTableAggregateFunction>();
            _fieldsForCalculation.Add(new DataTableAggregateFunction() { enmFunction = AggregateFunction.Avg, ColumnName = "Population", OutPutColumnName = "PopulationAvg" });
            _fieldsForCalculation.Add(new DataTableAggregateFunction() { enmFunction = AggregateFunction.Sum, ColumnName = "Population", OutPutColumnName = "PopulationSum" });
            _fieldsForCalculation.Add(new DataTableAggregateFunction() { enmFunction = AggregateFunction.Count, ColumnName = "Population", OutPutColumnName = "PopulationCount" });
            _fieldsForCalculation.Add(new DataTableAggregateFunction() { enmFunction = AggregateFunction.Max, ColumnName = "Year", OutPutColumnName = "YearMax" });
            _fieldsForCalculation.Add(new DataTableAggregateFunction() { enmFunction = AggregateFunction.Min, ColumnName = "Year", OutPutColumnName = "YearMin" });

            //Gets the result after grouping by
            DataTable dtGroupedBy = GetGroupedBy(_dt, _groupByColumnNames, _fieldsForCalculation);
        }


        /// <summary>
        /// Returns a mock data table
        /// </summary>
        /// <returns></returns>
        private DataTable GetDataTable()
        {
            //Declarations
            DataTable _dt = new DataTable();
            DataRow _dr;
            
            //Create columns
            _dt.Columns.Add(new DataColumn() { ColumnName = "State" });
            _dt.Columns.Add(new DataColumn() { ColumnName = "City" });
            _dt.Columns.Add(new DataColumn() { ColumnName = "Year", DataType = typeof(System.Int32) });
            _dt.Columns.Add(new DataColumn() { ColumnName = "Population", DataType = typeof(System.Int32) });

            //Add mock data
            _dr = _dt.NewRow(); _dr["State"] = "Gujarat"; _dr["City"] = "Ahmedabad"; _dr["Year"] = 2009; _dr["Population"] = 6000000; _dt.Rows.Add(_dr);
            _dr = _dt.NewRow(); _dr["State"] = "Gujarat"; _dr["City"] = "Surat"; _dr["Year"] = 2009; _dr["Population"] = 2000000; _dt.Rows.Add(_dr);
            _dr = _dt.NewRow(); _dr["State"] = "Gujarat"; _dr["City"] = "Rajkot"; _dr["Year"] = 2009; _dr["Population"] = 1000000; _dt.Rows.Add(_dr);
            _dr = _dt.NewRow(); _dr["State"] = "Maharastra"; _dr["City"] = "Mumbai"; _dr["Year"] = 2009; _dr["Population"] = 3000000; _dt.Rows.Add(_dr);
            _dr = _dt.NewRow(); _dr["State"] = "Maharastra"; _dr["City"] = "Pune"; _dr["Year"] = 2009; _dr["Population"] = 3000000; _dt.Rows.Add(_dr);

            _dr = _dt.NewRow(); _dr["State"] = "Gujarat"; _dr["City"] = "Ahmedabad"; _dr["Year"] = 2010; _dr["Population"] = 8000000; _dt.Rows.Add(_dr);
            _dr = _dt.NewRow(); _dr["State"] = "Maharastra"; _dr["City"] = "Mumbai"; _dr["Year"] = 2010; _dr["Population"] = 8000000; _dt.Rows.Add(_dr);

            _dr = _dt.NewRow(); _dr["State"] = "Gujarat"; _dr["City"] = "Ahmedabad"; _dr["Year"] = 2011; _dr["Population"] = 6000000; _dt.Rows.Add(_dr);
            _dr = _dt.NewRow(); _dr["State"] = "Gujarat"; _dr["City"] = "Surat"; _dr["Year"] = 2011; _dr["Population"] = 2000000; _dt.Rows.Add(_dr);
            _dr = _dt.NewRow(); _dr["State"] = "Gujarat"; _dr["City"] = "Rajkot"; _dr["Year"] = 2011; _dr["Population"] = 1000000; _dt.Rows.Add(_dr);
            _dr = _dt.NewRow(); _dr["State"] = "Maharastra"; _dr["City"] = "Mumbai"; _dr["Year"] = 2011; _dr["Population"] = 3000000; _dt.Rows.Add(_dr);
            _dr = _dt.NewRow(); _dr["State"] = "Maharastra"; _dr["City"] = "Pune"; _dr["Year"] = 2011; _dr["Population"] = 3000000; _dt.Rows.Add(_dr);

            //Return table
            return _dt;
        }

        /// <summary>
        /// Group by DataTable
        /// </summary>
        /// <param name="_dtSource"></param>
        /// <param name="_groupByColumnNames"></param>
        /// <param name="_fieldsForCalculation"></param>
        /// <returns></returns>
        private DataTable GetGroupedBy(DataTable _dtSource, IList<string> _groupByColumnNames, IList<DataTableAggregateFunction> _fieldsForCalculation)
        {
            
            //Once the columns are added find the distinct rows and group it bu the numbet
            DataTable _dtReturn = _dtSource.DefaultView.ToTable(true, _groupByColumnNames.ToArray());

            //The column names in data table
            foreach (DataTableAggregateFunction _calculatedField in _fieldsForCalculation)
            {
                _dtReturn.Columns.Add(_calculatedField.OutPutColumnName);
            }

            //Gets the collection and send it back
            for (int i = 0; i < _dtReturn.Rows.Count; i = i + 1)
            {
                #region Gets the filter string
                string _filterString = string.Empty;
                for (int j = 0; j < _groupByColumnNames.Count; j = j + 1)
                {
                    if (j > 0)
                    {
                        _filterString += " AND ";
                    }
                    if (_dtReturn.Columns[_groupByColumnNames[j]].DataType == typeof(System.Int32))
                    {
                        _filterString += _groupByColumnNames[j] + " = " + _dtReturn.Rows[i][_groupByColumnNames[j]].ToString() + "";
                    }
                    else
                    {
                        _filterString += _groupByColumnNames[j] + " = '" + _dtReturn.Rows[i][_groupByColumnNames[j]].ToString() + "'";
                    }
                }
                #endregion

                #region Compute the aggregate command

                foreach (DataTableAggregateFunction _calculatedField in _fieldsForCalculation)
                {
                    _dtReturn.Rows[i][_calculatedField.OutPutColumnName] = _dtSource.Compute(_calculatedField.enmFunction.ToString() + "(" + _calculatedField.ColumnName + ")", _filterString);
                }
                
                #endregion
            }

            return _dtReturn;
        }
    }
}


How to Use?

Call the function from somewhere.
(new SampleApplication.Helper()).DemoGroupBy();


Screenshot

Before Group By :
After Group By :


Please let me know if this helped.

Thursday, May 17, 2012

SharePoint 2010 : Call server side function from XSL.

Goal

To use a server side function from a XSL used in a web part.

Solution

It is simple to use a server side function. Just need to make sure the dll should be deployed in GAC. In this example I created a class with name "ClassName", the project name is "SampleApplication". Deployed the dll in GAC. Modify the XSL head and add xmlns:helper="SampleApplication.ClassName" on the head. "helper" is like an tag which will point to the class.

XSL
<xsl:stylesheet 
  version="1.0" 
  exclude-result-prefixes="x d xsl msxsl cmswrt helper"
  xmlns:x="http://www.w3.org/2001/XMLSchema" 
  xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" 
  xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
  xmlns:cmswrt="http://schemas.microsoft.com/WebParts/v3/Publishing/runtime"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:helper="SampleApplication.ClassName">


SampleApplication.ClassName
#region System
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#endregion

namespace SampleApplication
{
    public class ClassName
    {
        #region Properties
        
        /// <summary>
        /// Name 
        /// </summary>
        private static string Name = "Maulik Dhorajia";
        
        /// <summary>
        /// Today Date
        /// </summary>
        private static string TodayDate = System.DateTime.Now.ToString();

        #endregion

        /// <summary>
        /// Gets the property
        /// </summary>
        /// <param name="propertyKey"></param>
        /// <returns></returns>
        public static string GetProperty(string propertyKey)
        {
            if (propertyKey == "Name")
            {
                return Name;
            }
            else if (propertyKey == "TodayDate")
            {
                return TodayDate;
            }
            else 
            {
                return "";
            }
        }
    }
}


Calling the function from XSL
<xsl:value-of select="helper:GetLabel('Name')"/>
<xsl:value-of select="helper:GetLabel('TodayDate')"/>


This should be all to show the stuff on the page. Let me know if this helped.

Friday, April 6, 2012

SharePoint 2010 : Use Resouce(resx) file in a Multilingual site.

Goal

Our site is created using variations in both English and Spanish. Create a Visual Web Part which can use the resource file(.resx) to show different texts for different language.

Steps to achieve goal

  • Create a SharePoint project with name "Sample".
  • Add a web part with name "SampleWebPart".
  • Add a "Mapped Folder" to "Resources". 2 files needs to be added.
    1. SampleWebPart.en-US.resx - English version resource file. Add some text to the resource.
    2. SampleWebPart.es-ES.resx - Spanish version resource file. Add some text to the resource.
  • At this point the project "Solution Explorer" will look like
  • For applying the resource, Open the Feature1 properties. And make the 2 changes shown in the below given image.
  • Use the HTML and C# Code below.
  • Once the above given steps are done, deploy the web part and They will display as below given image.


HTML - SampleWebPartUserControl.ascx

<h1><asp:Literal ID="ltrlTitle" runat="server" /></h1>
<hr />
<h3>
    <asp:Literal ID="ltrlDescription" runat="server" />
</h3>


C# - SampleWebPartUserControl.ascx.cs

#region System
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
#endregion

namespace Sample.SampleWebPart
{
    /// <summary>
    /// Simple example to use Resouce file with English/Spanish language.
    /// </summary>
    public partial class SampleWebPartUserControl : UserControl
    {
        #region Events

        /// <summary>
        /// Page Load
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            ltrlTitle.Text = LoadResource( ResourceName.Title );
            ltrlDescription.Text = LoadResource(ResourceName.Description);
        }

        #endregion

        #region Resource Reader

        /// <summary>
        /// Name for the Version to be considered.
        /// NOTE :- Use exactly same "Name" as used in Resource(resx) file.
        /// </summary>
        public enum ResourceName
        { 
            Title,
            Description
        }

        /// <summary>
        /// Gets the text on the basis of "Name" in Resource(resx).
        /// </summary>
        private string LoadResource(ResourceName _resName)
        {
            return Microsoft.SharePoint.Utilities.SPUtility.GetLocalizedString("$Resources:" + _resName.ToString(),
                "SampleWebPart"
            , (uint)System.Globalization.CultureInfo.CurrentUICulture.LCID); 
        }

        #endregion
    }
}


Happy Coding

Saturday, March 3, 2012

SharePoint 2010 Error Solution : A Web Part or Web Form Control on this Page cannot be displayed or imported. The type could not be found or it is not registered as safe.

Introduction

An occours when a user tries to add a webpart on the page. The description of the error is "A Web Part or Web Form Control on this Page cannot be displayed or imported. The type could not be found or it is not registered as safe.".


Test Cases

Here, I am creating a small solution to show why I got this issue.
  1. Open Visual Studio 2010. Create a project with name "Sample".
  2. Add a WebPart to the project with name "SomeWebPart"(Note : Mind it WebPart not VisualWebPart).
  3. Add a class library to the solution with name "Helper".
  4. Add a "Helper.snk" to the project by Right Clicking "Helper" > Properties > Signing > Choose a strong name...
  5. Once that is done the structure will look like image given below
  6. Helper.Enums Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Helper
    {
        public class Enums
        {
            public enum SomeType
            {
                A = 0,
                B = 1,
                C = 2
            }
        }
    }
    
  7. SomeWebPart.cs Code
    using System;
    using System.ComponentModel;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    
    namespace Sample.SomeWebPart
    {
        [ToolboxItemAttribute(false)]
        public class SomeWebPart : WebPart
        {
            /// <summary>
            /// The enum which resides in enum
            /// </summary>
            public Helper.Enums.SomeType SomeTypeEnum { get; set; }
    
            /// <summary>
            /// Create child control
            /// </summary>
            protected override void CreateChildControls()
            {
    
            }       
            
        }
    }
  8. Deploy to the site. Try adding the WebPart and it will give the above mentioned error.


Problem

The problem is "Sample.dll" created for the WebPart gets added to the wsp and gets added to GAC automatically but the "Helper.dll" is not considered as a safe one and it stays out of GAC and so while adding the WebPart, it blows and the error shows on the alert window.

Solution

  1. Sample > Package > Open "Package.package"
  2. At the bottom you will find an option title "Advanced".
  3. As shown in the image select "Add Assembly from Project Output...".
  4. In the dialog select "Helper" will auto populate the Helper details.
  5. Safe Controls section add a new item.
  6. Fill the Namespace and Assembly with name "Helper".
  7. Click "OK" and exit the dialog. You can see the settings of Helper added on the Advanced screen.
  8. Deploy the WebPart and try adding it again. It should work.


Hope this helped!

SharePoint 2010 : Remove a WebPart from Page programmatically using C#.

Goal

To remove webparts from a page programmatically using C#.

Code

/// <summary>
/// This function will remove web parts with title passed
/// </summary>
/// <param name="_web">Web object</param>
/// <param name="_pageUrl">The url of the page on which the web part exists.</param>
/// <param name="_title">The title of the Web part</param>
private void RemoveWebPart(SPWeb _web, string _pageUrl, string _webPartTitle)
{
    //Remove the control once the page is copied
    Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager _webPartCollection = _web.GetLimitedWebPartManager(_pageUrl, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);

    //Retrive the webpart and remove
    IList<Microsoft.SharePoint.WebPartPages.WebPart> _listFormWebParts = (from _wp in _webPartCollection.WebParts.Cast<Microsoft.SharePoint.WebPartPages.WebPart>()
                                                                            where string.Compare( _wp.Title , _webPartTitle  , true ) == 0
                                                                            select _wp).ToList();

    //Check if there are any web parts found
    if (_listFormWebParts != null)
    {
        foreach (Microsoft.SharePoint.WebPartPages.WebPart _listFormWebPart in _listFormWebParts)
        {
            //Remove the webpart
            _webPartCollection.DeleteWebPart(_listFormWebPart);

            //Update
            _web.Update();
        }
    }
}


Tip

Suppose we dont want to remove the webpart using "Title" we want to remove the webpart with type.
//Retrive the webpart and remove
IList<Microsoft.SharePoint.WebPartPages.WebPart> _listFormWebParts = (from _wp in _webPartCollection.WebParts.Cast<Microsoft.SharePoint.WebPartPages.WebPart>()
                                                                        where _wp.GetType() == typeof(Microsoft.SharePoint.WebPartPages.ListFormWebPart)
                                                                        select _wp).ToList();

Thursday, January 19, 2012

SharePoint 2010 - Update user's infomation using UserProfileManager programmatically.

Goal

To update a user's information using C#. In the below given sample i am changing the Email(WorkEmail) of a user.

Important facts

  • User trying to update a profile should be updating own record or should be an "Admin in User Profile Service". If the user is not an Admin in User Profile Service the error will come "You must have manage user profiles administrator rights to use administrator mode.".
  • In below given code I am using true for IgnoreUserPrivacy. Default it should be false but i also wanted to make this work.
    UserProfileManager(SPServiceContext.Current , true)
  • Most Important : The user i am using to run this is an Admin in User Profile Service. So the code is working fine.

Code

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite _site = new SPSite(SPContext.Current.Site.Url))
    {
        using (SPWeb _web = _site.OpenWeb())
        {
            //Gets the profile manager object
            UserProfileManager _profileManager = new UserProfileManager(SPServiceContext.Current , true);
                           
            //UserName
            string _userName = @"MyMachine\User";

            //Gets the profile of a User
            UserProfile _userProfile = _profileManager.GetUserProfile(_userName);
            if (_userProfile != null)
            {
                //Change the Email value
                ((UserProfileValueCollection)_userProfile["WorkEmail"]).Value = "sample@someDomain.com";
                               
                //Save the record
                _userProfile.Commit();
                               
            }
        }
    }
});

This code works absolutely fine. For the developers who are getting issue like "You must have manage user profiles administrator rights to use administrator mode." please click the error to visit the solution.

Friday, January 13, 2012

SharePoint 2010 - Custom Toolpart properties for CQWP.

Goal

Adding custom fields in the tool pane of Content Query Web Part and using them. A few days ago I was working on a project with a similar requirement. I figured out that we can extend ToolPane and add custom controls to it.

How to achieve?

  1. Create a blank SharePoint project in Microsoft Visual Studio 2010 with name "CustomContentQueryWebPart".
  2. Add a "Web Part" to the project with name "ExtendedCQWP" and not to be mistaken with "Visual Web Part".

  3. Added a class "ExtendedCQWPToolPart" for the ToolPane in a folder name "CustomToolPart". Once the classes are added the structure of the project will look like the picture given below.

  4. Use the code for "ExtendedCQWPToolPart".
    #region System
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web.UI.WebControls;
    
    #endregion
    
    namespace CustomContentQueryWebPart.CustomToolPart
    {
        /// <summary>
        /// The extended tool part of Extended Content Query Web Part.
        /// Will have a DropdownList, RadioButtonList and TextBox
        /// Will use the values added in the controls as applied.
        /// </summary>
        public class ExtendedCQWPToolPart : Microsoft.SharePoint.WebPartPages.ToolPart
        {
            #region Properties
    
            /// <summary>
            /// Literal
            /// </summary>
            protected Literal Ltrl { get; set; }
    
            /// <summary>
            /// Text Box
            /// </summary>
            protected TextBox Txt { get; set; }
    
            /// <summary>
            /// Dropdownlist
            /// </summary>
            protected DropDownList Ddl { get; set; }
    
            /// <summary>
            /// Radiobutton
            /// </summary>
            protected RadioButtonList Rbtnl { get; set; }
    
            #endregion
    
            #region Methods
    
            /// <summary>
            /// Constructor
            /// Applies the settings
            /// </summary>
            public ExtendedCQWPToolPart(string _ddlValue, string _rbtnValue, string _txtValue)
            {
                //Bind the ddl
                Ddl = new DropDownList();
                Ddl.Items.Insert(0, new ListItem("--- Select ---", ""));
                Ddl.Items.Insert(1, new ListItem("DDL 1"));
                Ddl.Items.Insert(2, new ListItem("DDL 2"));
                Ddl.Items.Insert(3, new ListItem("DDL 3"));
               
                //Radio Button the ddl
                Rbtnl = new RadioButtonList();
                Rbtnl.Items.Insert(0, new ListItem("RBTN 1"));
                Rbtnl.Items.Insert(1, new ListItem("RBTN 2"));
                Rbtnl.Items.Insert(2, new ListItem("RBTN 3"));
                Rbtnl.SelectedIndex = 0;
                
                //Text box
                Txt = new TextBox();
    
                //Refill the settings
                if (!string.IsNullOrEmpty(_ddlValue))
                {
                    Ddl.SelectedValue = _ddlValue;
                }
                if (!string.IsNullOrEmpty(_rbtnValue))
                {
                    Rbtnl.SelectedValue = _rbtnValue;
                }
                if (!string.IsNullOrEmpty(_txtValue))
                {
                    Txt.Text = _txtValue;
                }            
            }
    
            /// <summary>
            /// Applies the child controls
            /// </summary>
            protected override void CreateChildControls()
            {
                base.CreateChildControls();
    
                #region Add the controls to the section
    
                //Title to the web part
                this.Title = "Extended Settings";
    
                //Add the contorls so that they show up on the screen
                Ltrl = new Literal();
                Ltrl.Text = "<b>Dropdown Selection</b><br /><br />";
                this.Controls.Add(Ltrl);
                this.Controls.Add(Ddl);
    
                Ltrl = new Literal();
                Ltrl.Text = "<br /><br /><b>Radiobutton Selection</b><br /><br />";
                this.Controls.Add(Ltrl);
                this.Controls.Add(Rbtnl);
    
                Ltrl = new Literal();
                Ltrl.Text = "<br /><br /><b>Textbox</b><br /><br />";
                this.Controls.Add(Ltrl);
                this.Controls.Add(Txt);
    
                Ltrl = new Literal();
                Ltrl.Text = "<br /><br />";
                this.Controls.Add(Ltrl);
    
                #endregion
            }
    
            /// <summary>
            /// Fires on the OK/Save is clicked in the tool part pane
            /// </summary>
            public override void ApplyChanges()
            {
                base.ApplyChanges();
    
                //Applies the custom settings to the content query web part
                ExtendedCQWP.ExtendedCQWP _parentWebPart = (ExtendedCQWP.ExtendedCQWP)this.ParentToolPane.SelectedWebPart;
                if (_parentWebPart != null)
                {
                    //Applies the control settings
                    _parentWebPart.DdlValue = Ddl.SelectedValue;
                    _parentWebPart.RbtnlValue = Rbtnl.SelectedValue;
                    _parentWebPart.TxtValue = Txt.Text;
    
                    //Applies the settings
                    _parentWebPart.ApplyChanges();
                }
                
            }
    
            #endregion
            
        }
    }
    
  5. For "ExtendedCQWP" add a reference of Microsoft.Sharepoint.Publishing and the code is given below.

    #region System
    
    using System;
    using System.ComponentModel;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    using System.Collections.Generic;
    using Microsoft.SharePoint.WebPartPages;
    
    #endregion
    
    namespace CustomContentQueryWebPart.ExtendedCQWP
    {
        /// <summary>
        /// Sample extended Content Query Web Part
        /// </summary>
        [ToolboxItemAttribute(false)]
        public class ExtendedCQWP : Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart
        {
            #region Properties
    
            /// <summary>
            /// Txt Value
            /// </summary>
            public string TxtValue { get; set; }
    
            /// <summary>
            /// Radio button Value
            /// </summary>
            public string RbtnlValue { get; set; }
    
            /// <summary>
            /// Txt Value
            /// </summary>
            public string DdlValue { get; set; }
    
            #endregion
    
            #region Methods
    
            /// <summary>
            /// Create Child Controls
            /// </summary>
            protected override void CreateChildControls()
            {
                base.CreateChildControls();
            }
    
            /// <summary>
            /// Override the get tool part
            /// </summary>
            /// <returns></returns>
            public override ToolPart[] GetToolParts()
            {
                List<ToolPart> _toolParts = new List<ToolPart>(base.GetToolParts());
                _toolParts.Insert(0, new CustomToolPart.ExtendedCQWPToolPart(DdlValue, RbtnlValue, TxtValue));
                return _toolParts.ToArray();
            }
    
            /// <summary>
            /// Applies the changes
            /// </summary>
            public void ApplyChanges()
            {
                this.Title = string.Format("DDL : {0}, Rbtn : {1}, Txt : {2}", DdlValue, RbtnlValue, TxtValue);
            }
    
            #endregion
        }
    }
    
  6. I renamed the title in element.xml so the web part show with title "Custom Content Query Web Part".
  7. Edit the newly added webpart.

    /li>
  8. The right side of the tool pane will show like the below given picture. Make the modification as you want.



  9. On applying or saving the settings my code will set the title concatenating all the 3 values.


This was the simplest way of showing how to add the custom parameters in the tool pane. We can do many more things with it not just setting the title. You can also go through one of my old blog Override Content Query Webpart to do on the run filteration to get an idea of what else can be done with extending the classes.
Hope the blog helped you, please comment if you have any queries. I will be very much happy to answer them.

Friday, November 4, 2011

SharePoint 2010 - Get My Personal Site URL and all other settings programmatically.

Summary

Guys, I found out a good way to retrieve the My Site > My Content(Personal Site) url using C#.

Solution

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    //Trying to get the Personal Site link or Url
    //SPContext.Current.Site = http://sp2010/
    //_url = http://sp2010:50000/personal/administrator/
                
    //The main site.
    SPSite _site = SPContext.Current.Site;
                
    //Gets the service context of the site.
    SPServiceContext _serviceContext = SPServiceContext.GetContext(_site);
                
    //On the basis of Service Manager 
    UserProfileManager _userProfileManager = new UserProfileManager(_serviceContext);
               
    //Get the User profile from User Profile Manager
    //True is passed in the constructor to create a My Site User Profile if it doesnot exists.
    UserProfile _userProfile = _userProfileManager.GetUserProfile(true);

    //Check if the Personal Site exists
    if (_userProfile.PersonalSite != null)
    {
        //This should give the link in the my site                   
        string _url = _userProfile.PersonalUrl.OriginalString;
    }
    else
    {
        //My Content(Personal Site) Does Exists
    }
});

Hope this helps someone facing issue to find a piece of code to get the url. The same way we can use _userProfile to get all the many other My Site Settings.

Thursday, October 13, 2011

SharePoint 2010 - SharePoint Page unable to save the "Publishing Content" changes in Version History.

Problem
I was facing a strange issue with custom "Page". Each and every page layout i was using having a "Page Content" control to enter some text. Here is visual as well as HTML of the control I am talking about.

HTML
<PublishingWebControls:RichHtmlField FieldName="PublishingPageContent" runat="server"/>
Visual
  • I added a new page to my SharePoint Site.
  • Assigned a custom "Page Layout".
  • My Page Layout contains the "Page Content" control. I made some changes to the text "Test".
  • Check In the page.
  • I want to edit the page again, changed the text to "Test - This is a change".
  • Check In the page.
  • Now in the "Page" tab on the top click "Page History".
  • You can find out the versions on the left side. 0.1 and 0.2. Please have a look at the image below.
  • There is no history shown. If you try the same thing with a "Out Of the Box" Page Layouts like Article Page, Enterprise wiki page it will work.


Catch
The publishing content type "Page" was missing column "Page Content". Because if you see in the properties above FieldName="PublishingPageContent"(This is a static name of "Page Content" column) was there in the HTML, but was not as columns in "Page", so history was not getting saved.


Manual Solution
  • Site Actions
  • Site Settings
  • Site Content Types
  • Publishing Content Types
  • Click "Page"
  • Add from existing site columns
  • Select and Add a "Page Content"
  • Save
Programmatic Solution
Create a Visual Studio Project. Create a "Site level Feature". Add a feature receiver. Use below given code. Call the function from Feature_Activation. It will add the "Page Content" if missing.
/// <summary>
/// Add Page Content To Content Type Page for a Publishing Site.
/// </summary>
/// <param name="_properties"></param>
private void AddPageContentToContentTypPage(SPFeatureReceiverProperties _properties)
{
    using (SPWeb _web = ((SPSite)_properties.Feature.Parent).RootWeb)
    {

        //Retrieve the content type
        SPContentType _contentType = _web.ContentTypes["Page"];

        if (_contentType != null)
        {
            if (!_contentType.Fields.ContainsFieldWithStaticName("PublishingPageContent"))
            {
                SPField _field = _web.AvailableFields["Page Content"];
                SPFieldLink _fieldText = new SPFieldLink(_field);

                if (_contentType.FieldLinks[_fieldText.Id] == null)
                {
                    _contentType.FieldLinks.Add(_fieldText);
                }
                _contentType.Update(true);
            }
        }
    }
}

Final Result
Once you are done with this. Please follow the steps mentioned above and you can see the result below.



Hope this helps.

Saturday, October 8, 2011

SharePoint 2010 - Set the default Page Layout programmatically.

Goal - To set "CustomDefaultPageLayout.aspx" as the default page layout, so the next time when some one creates a "New Page" our custom page layout is applied to the page and not system's.


Follow the below given steps to achieve the goal.

  • First of all make sure that the site we have to apply the page layout is a "Publishing Site."
  • Create a Visual Studio Empty Project.
  • Add a Feature Receiver
  • Add new reference of "Microsoft.SharePoint.Publishing".
  • Apply this on the top of the class.
    using Microsoft.SharePoint.Publishing;
    using System.Linq;
  • On feature activation use the below given code.
    private void SetDefaultPageLayout(SPWeb _web)
    {
        PublishingWeb _pubWeb = PublishingWeb.GetPublishingWeb(_web);
        if (_pubWeb != null)
        {
            PageLayout _pageLayout = (from _pl in _pubWeb.GetAvailablePageLayouts()
                                        where _pl.Name == "CustomDefaultPageLayout.aspx"
                                        select _pl).FirstOrDefault();
            _pubWeb.SetDefaultPageLayout(_pageLayout, true);
            _pubWeb.Update();
        }
    }
  • Call the function "SetDefaultPageLayout" from the Feature Activation event.

Tuesday, September 27, 2011

Sharepoint 2010 Adding a "Publishing Image" to a Sharepoint List programmatically.

What is "Publishing Image" content type?

"Publishing Image" is a content type which will bind the image with all its properties and will show it on the screen with those properties applied. The properties like height width etc.


What my task was?

My task was to add a "Publishing Image" content type with Display Name as "Rollup Image" in the content type list "Post". This was a site level feature, once i activate this feature all the blog type site with SharePoint List "Post" will have an extra field "Rollup Image". Please have a look at the 2 pictures which can give you a clear idea.


The 1st from the above one is new post screen. and the 2nd one comes when you click to add a new image reference.


Solution

  1. Open a visual studio 2010
  2. Add new project
  3. Empty Sharepoint Project > Deploy as Farm Solution > Finish.
  4. In the visual studio solution project select "Features > Feature1 > Feature1.feature".
  5. Right click "Add event receiver".
  6. I used this code to achieve it.

    /// <summary>
    /// Add a field name "Rollup Image" to a content type "Post".
    /// "Post" is the content type used in the Site Template blog.
    /// </summary>
    /// <param name="properties"></param>
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        SPSecurity.RunWithElevatedPrivileges(delegate
        {
            using (SPWeb _web = ((SPSite)properties.Feature.Parent).RootWeb)
            {
                //Post is the content type list which is on the blogs.
                SPContentType _contentType = _web.ContentTypes["Post"];
    
                if (_contentType != null)
                {
                    //PublishingRollupImage is the static name for the "Publishing Image "
                    if (!_contentType.Fields.ContainsFieldWithStaticName("PublishingRollupImage"))
                    {
                        //Name of the column to be added to the list content type post
                        SPField _field = _web.AvailableFields["Rollup Image"];
                        SPFieldLink _fieldText = new SPFieldLink(_field);
    
                        if (_contentType.FieldLinks[_fieldText.Id] == null)
                        {
                            _contentType.FieldLinks.Add(_fieldText);
                        }
                        _contentType.Update(true);
                    }
                }
            }
        });
    }
  7. Deploy the solution.




How to verify this?

  1. Open the Sharepoint Site.
  2. Site Actions > Site Settings > Site Content Types
  3. Click "Post" in "List Content Type".
  4. You can see the newly added column in the image below. For checking the above 2 images you should go to the "Post" sharepoint list in the blog site.



Please feel free to ask question, I will be more glad to answer your question.

Sharepoint 2010 Enabling "Target Audience" programmatically for Sharepoint List

In this blog i have tried and explained how enable the "Target Audience" using C# for a list. But first I will show you how to enable manually.


Why do we have to enable "Target Audience" field?

To filter the data using audience in Content Query Web Part we have to enable this feature.



Manually

  1. Go to Sharepoint Site
  2. Site Actions > View All Site Content
  3. Select the SharePoint List you want to enable target audience.
  4. List Settings > Audience targeting settings
  5. Select the check box and save.
  6. This will add a field name "Target Audience" in the list.
  7. You can now give Item level target audience.

Programmatically

  1. In the event receiver where you are creating a Sharepoint List.
  2. Just use the code given below.
    #region Enable Target Audience
    
    XmlElement _fldElement = new XmlDocument().CreateElement("Field");
    _fldElement.SetAttribute("ID", "{61cbb965-1e04-4273-b658-eedaa662f48d}");
    _fldElement.SetAttribute("Type", "TargetTo");
    _fldElement.SetAttribute("Name", "Target_x0020_Audiences");
    _fldElement.SetAttribute("StaticName", "Target_x0020_Audiences");
    _fldElement.SetAttribute("DisplayName", "Target Audiences");
    _fldElement.SetAttribute("Required", "FALSE");
    _list.Fields.AddFieldAsXml(_fldElement.OuterXml);
    
    _list.Update();
    
    #endregion
  3. That should be it. See to the list if that column is there!

Thank you and hoping the blog helped you.

Monday, September 26, 2011

Sharepoint 2010 Master page issue with re-deployment with new changes from Visual Studio solution

PROBLEM :- There is a problem with the current process. For the first time this will work but if you make any changes to the master page and re-deploy the same solution will not deploy this new master page with the changes on the server.


In my last post "SharePoint 2010 Deploy Master Page using Visual Studio Solution Project and Set it as Default Master Page.", i explained how to add a master page and set it as a default. I suggest to read the last blog first.


What causes the issue?

Answer: When a file is deployed to the server using a Visual Studio Solution, the file gets deleted first and than added back to server. But when we assign a file as a Default Master Page it "CANNOT" be deleted. So just follow the below given steps to make it a fix.

Solution

Just write a deactivating event in the feature receiver setting V4.master as a master page. Please checkout the code below.


/// <summary>
/// Set the v4.master as default master for site.
/// </summary>
/// <param name="properties"></param>
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
    SPSecurity.RunWithElevatedPrivileges(delegate
    {
        using (SPWeb _web = ((SPSite)properties.Feature.Parent).RootWeb)
        {
            Uri _siteMaster = new Uri(string.Format("{0}/_catalogs/masterpage/v4.master", _web.Url));
            _web.MasterUrl = _siteMaster.AbsolutePath;
            _web.CustomMasterUrl = _siteMaster.AbsolutePath;
            _web.Update();
        }
    });
}
Hope this was helpful to you. Thanks for reading the blog.

SharePoint 2010 Deploy Master Page using Visual Studio Solution Project and Set it as Default Master Page.

This blog will give an understanding of how to add a master page using a Visual Studio solution project. Also setting the same master as a default for site.


STEP 1 : Adding a Master Page using Module

  1. Open a visual studio 2010
  2. Add new project
  3. Empty Sharepoint Project > Deploy as Farm Solution > Finish.
  4. Add New Item > Select "Module" > I named it as "MasterPage".
  5. Delete the "Sample.txt" which gets added in the module by default.
  6. Add new MainMasterPage.master. Do whatever change you want to it.
  7. Open the elements.xml file of "MasterPage" module. You will have to make some modification shown below.


    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
        <Module Name="MasterPage" List="116" Url="_catalogs/masterpage">
            <File Path="MasterPage\MainMasterPage.master" Url="MainMasterPage.master" Type="GhostableInLibrary">
                <Property Type="string" Name="Title" Value="My Main Master Page"/>
            </File>
      </Module>
    </Elements>
  8. Please verify the below given text i made change in the original one. This is MOST IMPORTANT!!!.
    List="116" Url="_catalogs/masterpage"
    Url="MainMasterPage.master" Type="GhostableInLibrary"
  9. Once this is set just deploy the project.

STEP 1.1 : Verify the file got uploaded

  1. Open the site in SharePoint Designer 2010.
  2. All Files > _catalogs > MasterPage
  3. The file should be at this location because if you see the element.xml above in the url we have given the path of "_catalogs/masterpage". That's it we now achieved the first step of adding a master file to the site.


STEP 2 : Apply the page as a default master page

  1. In the visual studio solution project select "Features > Feature1 > Feature1.feature".
  2. Right click "Add event receiver".
  3. Put this code.

    /// <summary>
    /// Set the MainMasterPage.master as default master for site.
    /// </summary>
    /// <param name="properties"></param>
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        SPSecurity.RunWithElevatedPrivileges(delegate
        {
            using (SPWeb _web = ((SPSite)properties.Feature.Parent).RootWeb)
            {
                Uri _siteMaster = new Uri(string.Format("{0}/_catalogs/masterpage/MainMasterPage.master", _web.Url));
                _web.MasterUrl = _siteMaster.AbsolutePath;
                _web.CustomMasterUrl = _siteMaster.AbsolutePath;
                _web.Update();                   
            }
        });
    }
  4. Right click the project and deploy the solution.

I hope this helps you with the deployment of master page and setting it as a default.

PROBLEM :- There is a problem with the current process. For the first time this will work but if you make any changes to the master page and re-deploy the same solution will not deploy this new master page with the changes on the server. Please read my next blog "Sharepoint 2010 Master page issue with re-deployment with new changes from Visual Studio solution" for the solution.