Tuesday, January 6, 2015

How to copy items from a CSV file into SharePoint List through C# Code.

One of the requirement we frequently get from end user is to upload the contents of an excel or CSV file into SharePoint List. Here is the code for doing it from a CSV file and update it into SharePoint List.

We can also suggest end user to save their excel file as CSV. It will provide all the features of excel and can be read more easily pro-grammatically.

First of all we need to add these two classes in our solution :

Class String Converter is an standard class for dealing with string inputs :

public static class StringConverter
    {
        public static Type ConvertString(string value, out object convertedValue)
        {
            // First check the whole number types, because floating point types will always parse whole numbers
            // Start with the smallest types
            byte byteResult;
            if (byte.TryParse(value, out byteResult))
            {
                convertedValue = byteResult;
                return typeof(byte);
            }

            short shortResult;
            if (short.TryParse(value, out shortResult))
            {
                convertedValue = shortResult;
                return typeof(short);
            }

            int intResult;
            if (int.TryParse(value, out intResult))
            {
                convertedValue = intResult;
                return typeof(int);
            }

            long longResult;
            if (long.TryParse(value, out longResult))
            {
                convertedValue = longResult;
                return typeof(long);
            }

            ulong ulongResult;
            if (ulong.TryParse(value, out ulongResult))
            {
                convertedValue = ulongResult;
                return typeof(ulong);
            }

            // No need to check the rest of the unsigned types, which will fit into the signed whole number types

            // Next check the floating point types
            float floatResult;
            if (float.TryParse(value, out floatResult))
            {
                convertedValue = floatResult;
                return typeof(float);
            }


            // It's not clear that there's anything that double.TryParse() and decimal.TryParse() will parse 
            // but which float.TryParse() won't
            double doubleResult;
            if (double.TryParse(value, out doubleResult))
            {
                convertedValue = doubleResult;
                return typeof(double);
            }

            decimal decimalResult;
            if (decimal.TryParse(value, out decimalResult))
            {
                convertedValue = decimalResult;
                return typeof(decimal);
            }

            // It's not a number, so it's either a bool, char or string
            bool boolResult;
            if (bool.TryParse(value, out boolResult))
            {
                convertedValue = boolResult;
                return typeof(bool);
            }

            char charResult;
            if (char.TryParse(value, out charResult))
            {
                convertedValue = charResult;
                return typeof(char);
            }

            convertedValue = value;
            return typeof(string);
        }

        /// <summary>
        /// Compare two types and find a type that can fit both of them
        /// </summary>
        /// <param name="typeA">First type to compare</param>
        /// <param name="typeB">Second type to compare</param>
        /// <returns>The type that can fit both types, or string if they're incompatible</returns>
        public static Type FindCommonType(Type typeA, Type typeB)
        {
            // Build the singleton type map (which will rebuild it in a typesafe manner
            // if it's not already built).
            BuildTypeMap();

            if (!typeMap.ContainsKey(typeA))
                return typeof(string);

            if (!typeMap[typeA].ContainsKey(typeB))
                return typeof(string);

            return typeMap[typeA][typeB];
        }


        // Dictionary to map two types to a common type that can hold both of them
        private static Dictionary<Type, Dictionary<Type, Type>> typeMap = null;

        // Locker object to build the singleton typeMap in a typesafe manner
        private static object locker = new object();

        /// <summary>
        /// Build the singleton type map in a typesafe manner.
        /// This map is a dictionary that maps a pair of types to a common type.
        /// So typeMap[typeof(float)][typeof(uint)] will return float, while
        /// typemap[typeof(char)][typeof(bool)] will return string.
        /// </summary>
        private static void BuildTypeMap()
        {
            lock (locker)
            {
                if (typeMap == null)
                {
                    typeMap = new Dictionary<Type, Dictionary<Type, Type>>()
                    {
                        // Comparing byte
                        {typeof(byte), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(byte) },
                            { typeof(short), typeof(short) },
                            { typeof(int), typeof(int) },
                            { typeof(long), typeof(long) },
                            { typeof(ulong), typeof(ulong) },
                            { typeof(float), typeof(float) },
                            { typeof(double), typeof(double) },
                            { typeof(decimal), typeof(decimal) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing short
                        {typeof(short), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(short) },
                            { typeof(short), typeof(short) },
                            { typeof(int), typeof(int) },
                            { typeof(long), typeof(long) },
                            { typeof(ulong), typeof(ulong) },
                            { typeof(float), typeof(float) },
                            { typeof(double), typeof(double) },
                            { typeof(decimal), typeof(decimal) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing int
                        {typeof(int), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(int) },
                            { typeof(short), typeof(int) },
                            { typeof(int), typeof(int) },
                            { typeof(long), typeof(long) },
                            { typeof(ulong), typeof(ulong) },
                            { typeof(float), typeof(float) },
                            { typeof(double), typeof(double) },
                            { typeof(decimal), typeof(decimal) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing long
                        {typeof(long), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(long) },
                            { typeof(short), typeof(long) },
                            { typeof(int), typeof(long) },
                            { typeof(long), typeof(long) },
                            { typeof(ulong), typeof(ulong) },
                            { typeof(float), typeof(float) },
                            { typeof(double), typeof(double) },
                            { typeof(decimal), typeof(decimal) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing ulong
                        {typeof(ulong), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(ulong) },
                            { typeof(short), typeof(ulong) },
                            { typeof(int), typeof(ulong) },
                            { typeof(long), typeof(ulong) },
                            { typeof(ulong), typeof(ulong) },
                            { typeof(float), typeof(float) },
                            { typeof(double), typeof(double) },
                            { typeof(decimal), typeof(decimal) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing float
                        {typeof(float), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(float) },
                            { typeof(short), typeof(float) },
                            { typeof(int), typeof(float) },
                            { typeof(long), typeof(float) },
                            { typeof(ulong), typeof(float) },
                            { typeof(float), typeof(float) },
                            { typeof(double), typeof(double) },
                            { typeof(decimal), typeof(decimal) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing double
                        {typeof(double), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(double) },
                            { typeof(short), typeof(double) },
                            { typeof(int), typeof(double) },
                            { typeof(long), typeof(double) },
                            { typeof(ulong), typeof(double) },
                            { typeof(float), typeof(double) },
                            { typeof(double), typeof(double) },
                            { typeof(decimal), typeof(decimal) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing decimal
                        {typeof(decimal), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(decimal) },
                            { typeof(short), typeof(decimal) },
                            { typeof(int), typeof(decimal) },
                            { typeof(long), typeof(decimal) },
                            { typeof(ulong), typeof(decimal) },
                            { typeof(float), typeof(decimal) },
                            { typeof(double), typeof(decimal) },
                            { typeof(decimal), typeof(decimal) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing bool
                        {typeof(bool), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(string) },
                            { typeof(short), typeof(string) },
                            { typeof(int), typeof(string) },
                            { typeof(long), typeof(string) },
                            { typeof(ulong), typeof(string) },
                            { typeof(float), typeof(string) },
                            { typeof(double), typeof(string) },
                            { typeof(decimal), typeof(string) },
                            { typeof(bool), typeof(bool) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing char
                        {typeof(char), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(string) },
                            { typeof(short), typeof(string) },
                            { typeof(int), typeof(string) },
                            { typeof(long), typeof(string) },
                            { typeof(ulong), typeof(string) },
                            { typeof(float), typeof(string) },
                            { typeof(double), typeof(string) },
                            { typeof(decimal), typeof(string) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(char) },
                            { typeof(string), typeof(string) },
                        }},

                        // Comparing string
                        {typeof(string), new Dictionary<Type, Type>() {
                            { typeof(byte), typeof(string) },
                            { typeof(short), typeof(string) },
                            { typeof(int), typeof(string) },
                            { typeof(long), typeof(string) },
                            { typeof(ulong), typeof(string) },
                            { typeof(float), typeof(string) },
                            { typeof(double), typeof(string) },
                            { typeof(decimal), typeof(string) },
                            { typeof(bool), typeof(string) },
                            { typeof(char), typeof(string) },
                            { typeof(string), typeof(string) },
                        }},

                    };
                }
            }
        }
    }

Class CSVReader is also an standard class and can be used as is in most of the cases. It has no. of constructors which can be used for multiple inputs as per your needs.

public class CSVReader : IDisposable
    {
        public const string NEWLINE = "\r\n";

        /// <summary>
        /// This reader will read all of the CSV data
        /// </summary>
        private BinaryReader reader;

        /// <summary>
        /// The number of rows to scan for types when building a DataTable (0 to scan the whole file)
        /// </summary>
        public int ScanRows = 0;

        #region Constructors

        /// <summary>
        /// Read CSV-formatted data from a file
        /// </summary>
        /// <param name="filename">Name of the CSV file</param>
        public CSVReader(FileInfo csvFileInfo, UserControl obj)
        {
            if (csvFileInfo == null)
                throw new ArgumentNullException("Null FileInfo passed to CSVReader");
            try
            {
                this.reader = new BinaryReader(File.OpenRead(csvFileInfo.FullName), Encoding.ASCII);
            }
            catch(Exception ex)
            {
                LoggingService.LogErrorInULS("IA & IC SharePoint Application Informational exception at " + System.DateTime.Now + "Exception Message : " + ex.Message.ToString() + " Exception Stacktrace : " + ex.StackTrace.ToString());
                ScriptManager.RegisterStartupScript(obj, GetType(), "showalert", "alert('This file is already opened. Please close and then upload data to IAIC site.');", true);
            }
        }


        /// <summary>
        /// Read CSV Form Binaries
        /// </summary>
        /// <param name="objSPFile"></param>
        public CSVReader(Stream fileStream)
        {
            if (fileStream == null)
                throw new ArgumentNullException("Null File passed to CSVReader");

            this.reader = new BinaryReader(fileStream, Encoding.ASCII);

        }

        /// <summary>
        /// Read CSV-formatted data from a string
        /// </summary>
        /// <param name="csvData">String containing CSV data</param>
        public CSVReader(string csvData)
        {
            if (csvData == null)
                throw new ArgumentNullException("Null string passed to CSVReader");


            this.reader = new BinaryReader(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(csvData)), Encoding.ASCII);
        }

        /// <summary>
        /// Read CSV-formatted data from a TextReader
        /// </summary>
        /// <param name="reader">TextReader that's reading CSV-formatted data</param>
        public CSVReader(TextReader reader)
        {
            if (reader == null)
                throw new ArgumentNullException("Null TextReader passed to CSVReader");

            this.reader = new BinaryReader(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd())));
        }

        #endregion



        string currentLine = "";
        /// <summary>
        /// Read the next row from the CSV data
        /// </summary>
        /// <returns>A list of objects read from the row, or null if there is no next row</returns>
        public List<object> ReadRow()
        {
            // ReadLine() will return null if there's no next line
            if (reader.BaseStream.Position >= reader.BaseStream.Length)
                return null;

            StringBuilder builder = new StringBuilder();

            // Read the next line
            while ((reader.BaseStream.Position < reader.BaseStream.Length) && (!builder.ToString().EndsWith(NEWLINE)))
            {
                char c = reader.ReadChar();
                builder.Append(c);
            }

            currentLine = builder.ToString();
            if (currentLine.EndsWith(NEWLINE))
                currentLine = currentLine.Remove(currentLine.IndexOf(NEWLINE), NEWLINE.Length);

            // Build the list of objects in the line
            List<object> objects = new List<object>();
            while (currentLine != "")
                objects.Add(ReadNextObject());
            return objects;
        }

        /// <summary>
        /// Read the next object from the currentLine string
        /// </summary>
        /// <returns>The next object in the currentLine string</returns>
        private object ReadNextObject()
        {
            currentLine = currentLine.Trim();
            if (currentLine == null)
                return null;

            // Check to see if the next value is quoted
            bool quoted = false;
            if (currentLine.StartsWith("\""))
                quoted = true;

            // Find the end of the next value
            string nextObjectString = "";
            int i = 0;
            int len = currentLine.Length;
            bool foundEnd = false;
            while (!foundEnd && i <= len)
            {
                // Check if we've hit the end of the string
                try
                {
                    if ((!quoted && i == len) // non-quoted strings end with a comma or end of line
                        || (!quoted && currentLine.Substring(i, 1) == ",")
                        // quoted strings end with a quote followed by a comma or end of line
                        || (quoted && i == len - 1 && currentLine.EndsWith("\""))
                        || (quoted && currentLine.Substring(i, 2) == "\","))
                        foundEnd = true;
                    else
                        i++;
                }
                catch(Exception ex)
                {
                    //ScriptManager.RegisterStartupScript( ,GetType(), "showalert", "alert('This file is already opened. Please close and then upload data to IAIC site.');", true);
                    i++;
                }
            }
            if (quoted)
            {
                if (i > len || !currentLine.Substring(i, 1).StartsWith("\""))
                    throw new FormatException("Invalid CSV format: " + currentLine.Substring(0, i));
                i++;
            }
            nextObjectString = currentLine.Substring(0, i).Replace("\"\"", "\"");

            if (i < len)
                currentLine = currentLine.Substring(i + 1);
            else
                currentLine = "";

            if (quoted)
            {
                if (nextObjectString.StartsWith("\""))
                    nextObjectString = nextObjectString.Substring(1);
                if (nextObjectString.EndsWith("\""))
                    nextObjectString = nextObjectString.Substring(0, nextObjectString.Length - 1);
                return nextObjectString;
            }
            else
            {
                object convertedValue;
                StringConverter.ConvertString(nextObjectString, out convertedValue);
                return convertedValue;
            }
        }

        /// <summary>
        /// Read the row data read using repeated ReadRow() calls and build a DataColumnCollection with types and column names
        /// </summary>
        /// <param name="headerRow">True if the first row contains headers</param>
        /// <returns>System.Data.DataTable object populated with the row data</returns>
        public DataTable CreateDataTable(bool headerRow)
        {
            // Read the CSV data into rows
            List<List<object>> rows = new List<List<object>>();
            List<object> readRow = null;
            while ((readRow = ReadRow()) != null)
                rows.Add(readRow);

            // The types and names (if headerRow is true) will be stored in these lists
            List<Type> columnTypes = new List<Type>();
            List<string> columnNames = new List<string>();

            // Read the column names from the header row (if there is one)
            if (headerRow)
                foreach (object name in rows[0])
                    columnNames.Add(name.ToString());

            // Read the column types from each row in the list of rows
            bool headerRead = false;
            foreach (List<object> row in rows)
                if (headerRead || !headerRow)
                    for (int i = 0; i < row.Count; i++)
                        // If we're adding a new column to the columnTypes list, use its type.
                        // Otherwise, find the common type between the one that's there and the new row.
                        if (columnTypes.Count < i + 1)
                            columnTypes.Add(row[i].GetType());
                        else
                            columnTypes[i] = StringConverter.FindCommonType(columnTypes[i], row[i].GetType());
                else
                    headerRead = true;

            // Create the table and add the columns
            DataTable table = new DataTable();
            for (int i = 0; i < columnTypes.Count; i++)
            {
                table.Columns.Add();
                table.Columns[i].DataType = columnTypes[i];
                if (i < columnNames.Count)
                    table.Columns[i].ColumnName = columnNames[i];
            }

            // Add the data from the rows
            headerRead = false;
            foreach (List<object> row in rows)
                if (headerRead || !headerRow)
                {
                    DataRow dataRow = table.NewRow();
                    for (int i = 0; i < row.Count; i++)
                        dataRow[i] = row[i];
                    table.Rows.Add(dataRow);
                }
                else
                    headerRead = true;

            return table;
        }

        /// <summary>
        /// Read a CSV file into a table
        /// </summary>
        /// <param name="filename">Filename of CSV file</param>
        /// <param name="headerRow">True if the first row contains column names</param>
        /// <param name="scanRows">The number of rows to scan for types when building a DataTable (0 to scan the whole file)</param>
        /// <returns>System.Data.DataTable object that contains the CSV data</returns>
        public static DataTable ReadCSVFile(string filename, bool headerRow, UserControl objControl, int scanRows)
        {
            using (CSVReader reader = new CSVReader(new FileInfo(filename), objControl))
            {
                reader.ScanRows = scanRows;
                return reader.CreateDataTable(headerRow);
            }
        }

        /// <summary>
        /// Read a CSV file into a table
        /// </summary>
        /// <param name="filename">Filename of CSV file</param>
        /// <param name="headerRow">True if the first row contains column names</param>
        /// <returns>System.Data.DataTable object that contains the CSV data</returns>
        public static DataTable ReadCSVFile(string filename, bool headerRow, UserControl objControl)
        {
            using (CSVReader reader = new CSVReader(new FileInfo(filename), objControl))
                return reader.CreateDataTable(headerRow);
        }


        public static DataTable ReadCSVSteram(Stream fileStream, bool headerRow, UserControl objControl)
        {
            using (CSVReader reader = new CSVReader(fileStream))
                return reader.CreateDataTable(headerRow);
        }


        #region IDisposable Members

        public void Dispose()
        {
            if (reader != null)
            {
                try
                {
                    // Can't call BinaryReader.Dispose due to its protection level
                    reader.Close();
                }
                catch { }
            }
        }

        #endregion
    }

Now for reading the contents from CSV and getting it into an asp.net data table use this set of code.Here I have put it inside a Button Click event and also wrote code to insert data from these tables to SharePoint List

protected void btnUploadData_Click(object sender, EventArgs e)
        {
            try
            {
                string selectedText = ddlIntroducerAgent.SelectedItem.Text;
                string selectedValue = ddlIntroducerAgent.SelectedItem.Value;
                SPFieldLookupValue objSPFieldLookupValue = new SPFieldLookupValue(Convert.ToInt32(selectedValue), selectedText);

                //string fileName = Path.GetFileName(FileUploadControl.FileName); //If you are using other constructors.
                //if you are using file upload control in sharepoint get the full path as follows assuming fileUpload1 is control instance
                string fileName = FileUploadControl.PostedFile.FileName;
                Stream fStream = FileUploadControl.PostedFile.InputStream;
                //byte[] contents = new byte[fStream.Length];
                //fStream.Read(contents, 0, (int)fStream.Length);
                //fStream.Close();
                if (string.IsNullOrEmpty(fileName))
                {
                    ScriptManager.RegisterStartupScript(this, GetType(), "showalert", "alert('Please select a file to upload.');", true);
                }

                string fileExtension = Path.GetExtension(fileName).ToUpper();

                string strClientDataListTitle = "Client Data";

                if (fileExtension == ".CSV")
                {
                   
                   DataTable dt = CSVReader.ReadCSVSteram(fileStream, true, this);

                   SPWeb mySite = SPContext.Current.Web; //create web object if context is null
                   mySite.AllowUnsafeUpdates = true;

                   SPList ClientDataList = mySite.Lists["strListName"];
                   SPListItem newItem = ClientDataList.Items.Add();


                   SettingValuesInColumns(listTable, newItem);
                   newItem.Update();
                }
                else
                {
                    ScriptManager.RegisterStartupScript(this, GetType(), "showalert", "alert('Please use CSV file');", true);
                }

            }
            catch (Exception ex)
            {
                LoggingService.LogErrorInULS("See my other blog for logging click here " + System.DateTime.Now + "Exception Message : " + ex.Message.ToString() + " Exception Stacktrace : " + ex.StackTrace.ToString());

            }
        }:

protected static void SettingValuesInColumns(DataTable listTable, SPListItem newItem)
        {
           newItem["ListColName1"] = Convert.ToString(listTable.Rows[iRow]["CSVCol1"]);
           newItem["ListColName2"] = Convert.ToString(listTable.Rows[iRow]["CSVCol2"]);
           newItem["ListColName3"] = Convert.ToString(listTable.Rows[iRow]["CSVCol3"]);
           newItem["ListColName4"] = Convert.ToString(listTable.Rows[iRow]["CSVCol4"]);
           newItem["ListColName5"] = Convert.ToString(listTable.Rows[iRow]["CSVCol5"]);    
}

So by using above code you can upload content from a CSV file to SharePoint List on a button click.

Hope will help someone...!!


Wednesday, December 17, 2014

How to remove language filter and Searh tip from an Advance Search Webpart of SharePoint 2010.

By default UI of a SharePoint Advance search Webpart is as follows :

However in so many scenarios we are not using other criteria except our Custom Manged Metadata properties. So in order to hide all these unwanted criteria, just add a content editor Webpart into this page and add below scripts :

<style type="text/css">

.ms-advsrchtips{
display:none;
}
TD.ms-advsrchText-v2 > SELECT[title='Result Type'] {
DISPLAY: none
}
TD.ms-advsrchText-v1 > LABEL[for*='_ASB_SS_rtlb'] {
DISPLAY: none
}
.bottom {
BORDER-BOTTOM: gray 2px solid; BORDER-LEFT: gray 2px solid; BORDER-TOP: gray 2px solid; BORDER-RIGHT: gray 2px solid
}
.box {
BORDER-BOTTOM: medium none; BORDER-LEFT: gray 2px solid; BORDER-TOP: gray 2px solid; BORDER-RIGHT: gray 2px solid
}
.box H2 {
PADDING-BOTTOM: 10px; BACKGROUND-COLOR: gray; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; COLOR: white; PADDING-TOP: 10px
}
.box DIV {
COLOR: #333
}
.box {
-moz-border-radius-topright: 5px; -moz-border-radius-topleft: 5px; -webkit-border-top-right-radius: 5px; -webkit-border-top-left-radius: 5px
}</style><script language="javascript" src="/sites/IAIC/Style%20Library/CPA/jquery-1.8.1.min.js"></script><script language="javascript" type="text/javascript">

ExecuteOrDelayUntilScriptLoaded(function () {

$(".srch-advancedtable").wrap("<div class='content'></div>");$(".content").wrap("<div class='box'></div>").before($('content'), "<h2>Search Client Data Here</h2>");;$(".content").after('<div class="bottom"></div>'); 
    }, 'sp.js');</script>

After adding above script. Advance Search Webpart will look like below :



Thursday, November 27, 2014

Linq to filter items based on different conditions from your own custom class in C#

This is a demo that how can we store and process a set of records using Linq and our custom class. Here I have created a class for storing information. Then processed it using Linq. Here is the code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LinqLearning
{
    class Program
    {
        static void Main(string[] args)
        {

            IANameAndID obj1 = new IANameAndID("Maah", 1, "exit");
            IANameAndID obj2 = new IANameAndID("Krishna", 2, "exit");
            IANameAndID obj3 = new IANameAndID("Krishna", 3, "reduced");
            IANameAndID obj4 = new IANameAndID("Pawan", 4, "exit");
            IANameAndID obj5 = new IANameAndID("Pawan", 5, "exit");
            List<IANameAndID> col = new List<IANameAndID>();
            col.Add(obj1);
            col.Add(obj2);
            col.Add(obj3);
            col.Add(obj4);
            col.Add(obj5);

            Console.WriteLine(GetAgentDetailsFromCollection("Karan"," ", col));
            Console.WriteLine(GetAgentDetailsFromCollection("Krishna", "exit", col));
            Console.WriteLine(GetAgentDetailsFromCollection("Krishna", "ghbfjsevbjh", col));

            Console.ReadLine();
        }
        
        

        private static string GetAgentDetailsFromCollection(string strIAName, string strDataResponsibility, List<IANameAndID> objCol)
        {
            string objAgentLookup = null;

            IEnumerable<IANameAndID> selectedCollection = new List<IANameAndID>();

            if (objCol != null && objCol.Count > 0)
            {
                
                if (strIAName.Equals("Karan"))
                {
                    selectedCollection = from item in objCol
                                         where item.IAName.Equals("Maah")
                                         select item;
                    if (selectedCollection.Count() == 1)
                    {
                        objAgentLookup = selectedCollection.FirstOrDefault().ID + selectedCollection.FirstOrDefault().IAName;
                    }

                }
                else
                {

                    selectedCollection = from item in objCol
                                         where item.IAName.Equals(strIAName)
                                         select item;
                    int Count = selectedCollection.Count();
                    if (selectedCollection.Count() == 1)
                    {
                       objAgentLookup  = selectedCollection.FirstOrDefault().ID + selectedCollection.FirstOrDefault().IAName;
                    }
                    else if (selectedCollection.Count() == 2)
                    {
                        var subselectedCollection = from item in selectedCollection
                                                    where item.TypeofProject.ToLower().Contains("exit") && strDataResponsibility.ToLower().Contains("exit")
                                                    select item;
                        if (subselectedCollection.Count() == 1)
                        {
                            objAgentLookup = subselectedCollection.FirstOrDefault().ID + subselectedCollection.FirstOrDefault().IAName;
                        }
                        else
                        {
                            objAgentLookup = selectedCollection.LastOrDefault().ID + selectedCollection.LastOrDefault().IAName;
                        }
                    }
                    else
                    {
                        var innerselectedCollection = from item in objCol
                                                      where item.IAName.Equals("No Agent Assinged")
                                                      select item;
                        if (innerselectedCollection.Count() == 1)
                        {
                            objAgentLookup = innerselectedCollection.FirstOrDefault().ID + innerselectedCollection.FirstOrDefault().IAName;
                        }
                    }
                }

                
            }

            return objAgentLookup;

        }

        public class IANameAndID
        {
            public string IAName { get; set; }

            public int ID { get; set; }

            public string TypeofProject { get; set; }

            public IANameAndID(string strName, int intID, string strTypeofProject)
            {
                IAName = strName;
                ID = intID;
                TypeofProject = strTypeofProject;

            }
        }
    
    }
}

Friday, November 14, 2014

How to programmatically change value of a People Picker field or any other field through C# code in Infopath Form Library.

For Simple we can do it without using any namespace just with filed names :

private static void WithoutNameSpace(SPListItem objSPListItem)
        {
                            XmlDocument xml = new XmlDocument();

                            //Open XML file and load it into XML document
                            using (Stream s = objSPListItem.File.OpenBinaryStream())
                            {
                                xml.Load(s);
                            }

                            //Do your stuff with xml here. This is just an example of setting a field
                            Console.WriteLine(xml.InnerXml);

                            
                            XmlNodeList nodes = xml.GetElementsByTagName("my:IPCountry");
                            foreach (XmlNode node in nodes)
                            {
                                Console.WriteLine("Got value.." + node.InnerText);
                                node.InnerText = "Ireland";
                            }
                                
                            //Get binary data for new XML
                            byte[] xmlData = System.Text.Encoding.UTF8.GetBytes(xml.OuterXml);

                            using (MemoryStream ms = new MemoryStream(xmlData))
                            {
                                //Write data to SharePoint XML file
                                objSPListItem.File.SaveBinary(ms);
                            }
                            Console.WriteLine("Changes Saved");
                            Console.Read();
        }

For special type of fields like people picker first get the namespace that field and then set each attribute inside that field.

private static void WithNameSpaceApproach(SPList objSPListParent)
        {
            SPFile spf;
            XmlDocument doc;
            XmlNamespaceManager nsm;
            SPListItem itm = objSPListParent.GetItemById(6);
            spf = itm.File;
            try
            {

                doc = new XmlDocument();
                doc.Load(spf.OpenBinaryStream());
                nsm = new XmlNamespaceManager(doc.NameTable);
                foreach (XmlAttribute att in doc.DocumentElement.Attributes)
                {
                    if (att.Prefix == "xmlns")
                    {
                        nsm.AddNamespace(att.LocalName, att.Value);
                    }
                }
//Print all the old values..
                Console.WriteLine(doc.SelectSingleNode("//my:ResponsiblePerson" + "/pc:Person/pc:AccountId", nsm).InnerText.ToString());
                Console.WriteLine(doc.SelectSingleNode("//my:ResponsiblePerson" + "/pc:Person/pc:DisplayName", nsm).InnerText.ToString());
                Console.WriteLine(doc.SelectSingleNode("//my:ResponsiblePerson" + "/pc:Person/pc:AccountType", nsm).InnerText.ToString());
                spf.CheckOut();
                doc.SelectSingleNode("//my:ResponsiblePerson" + "/pc:Person/pc:AccountId", nsm).InnerText = @"INT\IJohnson";
                doc.SelectSingleNode("//my:ResponsiblePerson" + "/pc:Person/pc:DisplayName", nsm).InnerText = "Ian Johnson";
                doc.SelectSingleNode("//my:ResponsiblePerson" + "/pc:Person/pc:AccountType", nsm).InnerText = "User";
                spf.SaveBinary(new MemoryStream(Encoding.UTF8.GetBytes(doc.OuterXml)));
                spf.CheckIn("Updated by the UpdateInfoPathItems utility!");
                Console.WriteLine("Updated...");
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message.ToString());
                spf.CheckIn("Updated by the UpdateInfoPathItems utility!");

            }
        }

Wednesday, November 5, 2014

Breaking Item level Permission on ItemAdded and Add a Specific Group (Permission) for item

Here is the code for breaking permission for an item, whenever Items get added. And you can also add any group or permission as per your need. It can be very useful at times :

using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;

namespace DemoByKrishna.BreakItemLevelPermisiion
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class DocReadAccessEventReceiver : SPItemEventReceiver
    {
        /// <summary>
        /// An item was added.
        /// </summary>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            this.EventFiringEnabled = false;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                try
                {
                    using (SPSite site = new SPSite(properties.SiteId))
                    {
                        using (SPWeb web = site.OpenWeb(properties.RelativeWebUrl))
                        {
                            //SPList list = properties.List;
                            //SPListItem item = properties.ListItem;
                            SPListItem item = web.Lists[properties.ListId].GetItemById(properties.ListItem.ID);


                            web.AllowUnsafeUpdates = true;

                            item.BreakRoleInheritance(false);
                            string Group = "Viewers";
                            SPPrincipal cxosGroupUserGroup = FindUserOrSiteGroup(site, Group);
                            SPRoleDefinitionCollection GroupRole = web.RoleDefinitions;
                            SPRoleAssignment GroupRoleAssign = new SPRoleAssignment(cxosGroupUserGroup); 
                            cxosGroupRoleAssign.RoleDefinitionBindings.Add(cxosGroupRole["Read"]);
                            item.RoleAssignments.Add(GroupRoleAssign);

                            item.Update();
                        }
                    }
                }
                catch (Exception ex)
                {
                    properties.Status = SPEventReceiverStatus.CancelWithError;
                    properties.ErrorMessage = ex.Message;
                    properties.Cancel = true;
                }
            });
            this.EventFiringEnabled = true;

        }

        private static SPPrincipal FindUserOrSiteGroup(SPSite site, string userOrGroup)
        {
            SPPrincipal myUser = null;


            if (SPUtility.IsLoginValid(site, userOrGroup))
            {
                myUser = site.RootWeb.EnsureUser(userOrGroup);
            }
            else
            {
                foreach (SPGroup g in site.RootWeb.SiteGroups)
                {
                    if (g.Name.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == userOrGroup.ToUpper(System.Globalization.CultureInfo.InvariantCulture))
                    {
                        myUser = g;
                        break;
                    }
                }
            }
            return myUser;


        }

    }
}

Monday, July 14, 2014

Logging in SharePoint 2010 Custom Applications using SharePoint SPDiagnosticsServiceBase Class.

In SharePoint 2010 we have a very easy way to log errors in default SharePoint Log at "14\Log" folder by default. However if you are not able to view it here you can check Central Administrator --> Monitoring -->
Configure Diagonistic Logging -->Trace Log. Here is the code for :

Add  a class file into your project and then paste below code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Runtime.InteropServices;


namespace LoggingServiceExample
{
    public class LoggingService : SPDiagnosticsServiceBase
    {
        public static string vsDiagnosticAreaName = "SharePoint Logging Service";
        public static string CategoryName = "SharePointProject";
        public static uint uintEventID = 700; // Event ID
        private static LoggingService _Current;
        public static LoggingService Current
        {
            get
            {
                if (_Current == null)
                {
                    _Current = new LoggingService();
                }
                return _Current;
            }
        }
        private LoggingService()
            : base("SharePoint Logging Service", SPFarm.Local)
        { }
        protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
        {
            List<SPDiagnosticsArea> areas = new List<SPDiagnosticsArea>
                 {
                  new SPDiagnosticsArea(vsDiagnosticAreaName, new List<SPDiagnosticsCategory>
                   {
                    new SPDiagnosticsCategory(CategoryName, TraceSeverity.Medium, EventSeverity.Error)
                   })
                  };
            return areas;
        }
        public static string LogErrorInULS(string errorMessage)
        {
            string strExecutionResult = "Message Not Logged in ULS. ";
            try
            {
                SPDiagnosticsCategory category = LoggingService.Current.Areas[vsDiagnosticAreaName].Categories[CategoryName];
                LoggingService.Current.WriteTrace(uintEventID, category, TraceSeverity.Unexpected, errorMessage);
                strExecutionResult = "Message Logged";
            }
            catch (Exception ex)
            {
                strExecutionResult += ex.Message;
            }
            return strExecutionResult;
        }
        public static string LogErrorInULS(string errorMessage, TraceSeverity tsSeverity)
        {
            string strExecutionResult = "Message Not Logged in ULS. ";
            try
            {
                SPDiagnosticsCategory category = LoggingService.Current.Areas[vsDiagnosticAreaName].Categories[CategoryName];
                LoggingService.Current.WriteTrace(uintEventID, category, tsSeverity, errorMessage);
                strExecutionResult = "Message Logged";
            }
            catch (Exception ex)
            {
                strExecutionResult += ex.Message;
            }
            return strExecutionResult;
        }
    }
}

You just need to call following code on each entry points for any custom component :

try
{
            
}
catch(Exception ex)
 {
LoggingService.LogErrorInULS("Custom SharePoint Application exception at " + System.DateTime.Now + "Exception Message : "+ ex.Message.ToString() +" Exception Stacktrace : "+ ex.StackTrace.ToString());
}

Hope it helps..!!

Wednesday, July 9, 2014

How to create cascaded drop down using Client Side Object Model in SharePoint 2010 or above.

When we are trying to cascade drop-downs usually we use server side cascading which causes Post back and reload of controls View-state. Which leads to reset of fields to avoid it we used to use update panel. So instead of doing it we can use client side ECMA Script to get these values. It will make it more user friendly.

Here I am considering we have drop-down list bound from a list which works as a Parent List for second drop-down with a look-up column. We will call these methods on the first  drop-down change event :

function getDocumentType(index, sourceColumn, listName) {
        // get the list by it's name from the root site level
        var Query = '<View><Query><Where><Eq><FieldRef Name="' + sourceColumn + '" LookupId="TRUE"/><Value Type="Lookup">' + index + '</Value></Eq></Where></Query></View>';
        // Get the current client context to start. Most things run from the client context.
        clientContext = new SP.ClientContext.get_current();
        var myList = clientContext.get_site().get_rootWeb().get_lists().getByTitle(listName);
        // use a standard syntax CAML query to filter your results and the fields returned if required, by adding the following, or passing parameters to the load command below
        var query = new SP.CamlQuery();
        // You can leave out this line if you just want to return the entire list.
        query.set_viewXml(Query);
        // add your query to the getItems command for your list
        this.collListItems = myList.getItems(query);
        // issue the load command, these can be batched for multiple operations
        clientContext.load(collListItems);
        // execute the actual query against the server, and pass the objects we have created to either a success or failure function
        clientContext.executeQueryAsync(Function.createDelegate(this, this.mySuccessFunction), Function.createDelegate(this, this.myFailFunction));
    }


    function mySuccessFunction() {
        var destDropDown= this.document.getElementById('<%=ddChild.ClientID%>');
        destDropDown.options.length = 0;
        var listItemEnumerator = this.collListItems.getEnumerator();
        var count = this.collListItems.get_count();
        destDropDown.options[destDropDown.options.length] = new Option("-Select-", "0");
        if (count != 0) {
            while (listItemEnumerator.moveNext()) {
                var currentItem = listItemEnumerator.get_current();
                destDropDown.options[destDropDown.options.length] = new Option(currentItem.get_item(destColumn).get_lookupValue(), currentItem.get_item(destColumn).get_lookupId());

            }
        }
    }

    function myFailFunction() {
        alert("Error: Failed to fetch items. Please contact your Administrator.");
        // do something to alert the user as to the error here.
    } 

We can make these function generic for multiple level of cascading.