Tuesday, December 22, 2015

Easiest way to add Auto complete lookup to SharePoint 2013 or Online Form Fields using SPServices.

Today we will see how can we add an auto complete function to a SharePoint field in SharePoint 2013 or Online using SPServices. It will provide an easier way to provide user lookup functionality as a help instead of mandatory way and also add below code to on NewForm.aspx of your destination List by adding a Script Editor Webpart:

<script language="javascript" src="//code.jquery.com/jquery-1.6.2.min.js"
type="text/javascript"></script>
<script language="javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2014.02/jquery.SPServices-2014.02.min.js"
type="text/javascript"></script>
<script type="text/javascript">
    $(document).ready(function () {
        $().SPServices.SPAutocomplete({
            sourceList: "SourceList", // Source List Name
            sourceColumn: "Title", // Source List Column from where you want to fetch it.
            columnName: "DestinationListColumn", // Destination List Column where you wan to add it.
            ignoreCase: true,
            numChars: 2,
            slideDownSpeed: 'fast'
        });
    });</script>

Wednesday, August 19, 2015

Best way to validate a SharePoint Enhanced Rich text field using JQuery.

Recently I got a requirement to create a new Enhanced Rich text field in my existing application. We also need to validate that its not blank. So at first I know, it will be bit complex due to any obvious selector unavailability for Enhanced Rich Text Field in SharePoint. I searched a lot and found no. of suggestion but nothing seems very logical to me and also did not work for me. Then I have written below script to deal with it.

//Rich Text Field Validation Code

var RichtTxtContent = $('nobr:contains("Rich Text Field Title")').closest('tr').find('div[id$="TextField_inplacerte"]').text();
if( RichtTxtContent.length === 1 ||  RichtTxtContent.length === 0)
{
alert("Please enter  Richt Text Content .");
SetRemoveStyleOnFocus($('nobr:contains("Rich Text Field Title")').closest('tr').find('div[id$="TextField_inplacerte"]'));
return false;

I have just selected whole Row with the Rich Text Field Title, then found out a div with the text its always append it into this div client Id. Refer below screen shot to see the ID.


Then we need to check length as by default its set to 1. We need to compare with both 1 and 0.


Here is a function which will make sure that field is highlighted with focus whenever its blank. You can write your own classes to highlight it.

function SetRemoveStyleOnFocus(inputField)
{
$(inputField).focus(function() {
    $(this).addClass("focus");
});
$(inputField).blur(function() {
    $(this).removeClass("focus");
    });

    $(inputField).focus();
}

We just need to call this piece of code on Pre Save event of a SharePoint OOB New\Edit form or any other event as per need.


Validate no. of characters and their type entered into any input field using Java Script.

Here are I am writing an example how can we make sure that entered input in a filed should be only a 6 Digit number. You can modify it to according to your requirements:

var InputFieldValue = $("#InputFiledID").val();//Bit Jquery :) You can use java script too.

if( InputFieldValue!= '')
    {
var digits = "0123456789";
        var temp;
        if (InputFieldValue.length > 6){
        alert("Entered value cannot be more than 6 Digit Numbers ");
        return false;
        }
        else if(InputFieldValue.length < 6){
        alert("Entered value cannot be less than 6 Digit Numbers ");
        return false;
        }
        else {
for (var i = 0; i < InputFieldValue.length ; i++) {
        temp = InputFieldValue.substring(i, i + 1);
        if (digits.indexOf(temp) == -1) {
        alert("Entered value cannot contain any Character.");
        return false;
        }
        }
        }
     }

On the above code we have provided a string of characters which we want to permit as inputs. In this case we want to validate against numerals.  Then we select each character of input field value and try to find it into our format string, if it does not contain we return vale as false.

This can be extend for checking against any format.

Here is an example how can we extend it. For an input in this format "xx-xx-xx" where 'x' needs to be a number:

if( InputFieldValue != '')
{
var digits = "0123456789";
        var temp;
        if (InputFieldValue.length > 8){
        alert("Entered Value cannot be more than 6 Digit Numbers ");
                return false;
                }
                else if(InputFieldValue.length < 8)
                {
                alert("Entered Value cannot be less than 6 Digit Numbers ");
                return false;
                }
                else {
for (var i = 0; i < InputFieldValue.length; i++) {
            temp =InputFieldValue.substring(i, i + 1);
            if(i==2|| i==5)
            {
            if(temp!='-')
            {
            alert("Entered Value be in xx-xx-xx format. Does not conation - in current values.");
                   return false;
                   }
            }
            else if (digits.indexOf(temp) == -1) {
                alert("Entered Value cannot contain any Character ");
                return false;
            }
            }
             }
            }

On the above code, we are making sure that on 3rd and 5th position its always contain '-'.

Hope it helps someone.


Thursday, July 16, 2015

Creating multiple layer of folders in SharePoint using SPServices and Jquery on any version.

Recently I got a requirement, where user wants to create a set of multiple layer of multiple folders. Creating all those folders one by one with same structure manually is very time consuming work. At the same time we wanted not to deploy any custom C# solution and we need it on SP2007. So I decided to use SPServices.

Below is the code which I have added into a Content Editor Webpart:

<script language="javascript" type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script language="javascript" type="text/javascript" src="http://www.sympraxisconsulting.com/Demos/jQuery%20Libraries/jquery.SPServices-0.6.0.min.js"></script>
<script language="javascript" type="text/javascript">
  $(document).ready(function() {
  });

function CallOnButtonClick()
{
var librarynaem = "List or Library Title";
var newfolder = document.getElementById("topFolderName").value;
CreateFolder(librarynaem, newfolder);
}  

function CreateFolder(librarynaem, newfolder) {
 jQuery().SPServices({
  operation: "UpdateListItems",
  async: false,
  listName: librarynaem ,
  updates: "<Batch OnError='Continue' PreCalc='TRUE' ListVersion='0' >" +
    "<Method ID='1' Cmd='New'>" +
     "<Field Name='FSObjType'>1</Field>" +
     "<Field Name='BaseName'>" + newfolder + "</Field>" +
    "</Method>" +
    "<Method ID='2' Cmd='New'>" +
     "<Field Name='FSObjType'>1</Field>" +
     "<Field Name='BaseName'>" + newfolder +"/Folder1"+ "</Field>" +
    "</Method>" +
"<Method ID='3' Cmd='New'>" +
     "<Field Name='FSObjType'>1</Field>" +
     "<Field Name='BaseName'>" + newfolder +"/Folder1/Folder11"+ "</Field>" +
    "</Method>" +
"<Method ID='4' Cmd='New'>" +
     "<Field Name='FSObjType'>1</Field>" +
     "<Field Name='BaseName'>" + newfolder +"/Folder1/Folder12"+ "</Field>" +
    "</Method>" +
"<Method ID='5' Cmd='New'>" +
     "<Field Name='FSObjType'>1</Field>" +
     "<Field Name='BaseName'>" + newfolder +"/Folder2"+ "</Field>" +
    "</Method>" +
"<Method ID='6' Cmd='New'>" +
     "<Field Name='FSObjType'>1</Field>" +
     "<Field Name='BaseName'>" + newfolder +"/Folder3"+ "</Field>" +
    "</Method>" +
"<Method ID='7' Cmd='New'>" +
     "<Field Name='FSObjType'>1</Field>" +
     "<Field Name='BaseName'>" + newfolder +"/Folder3/Folder31"+ "</Field>" +
    "</Method>" +
"<Method ID='8' Cmd='New'>" +
     "<Field Name='FSObjType'>1</Field>" +
     "<Field Name='BaseName'>" + newfolder +"/Folder3/Folder32"+ "</Field>" +
    "</Method>" +
   "</Batch>",
  completefunc: function(xData, Status) {
   //alert("Status=" + Status); 
alert("New Service Added. Please refresh.");
 document.getElementById("topFolderName").value = "";
   }
 });
 }
  
</script>
<input type="text" id="topFolderName" />
<input type="button" onclick="CallOnButtonClick()" value="Add New Folder Structure">

Running this code will create folders and sub folders. We can create it any level using "/" for a new level in name parameter.

Friday, July 10, 2015

Find out users from a particular domain and remove them from whole SharePoint web application with checking status in Active Directory.

Recently we have got an requirement to remove users from a particular domain from SharePoint Web-application. In addition to it we also need to check if that user is still active on that Active Directory.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

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

            Console.WriteLine("Started...");

            Console.WriteLine("Please enter any site collection URL to access Web Application and press enter");
            string siteURL = Convert.ToString(Console.ReadLine());

            Console.WriteLine("Please enter domain name and press enter.");
            string DomainName = Convert.ToString(Console.ReadLine());
            string StartedTime = DateTime.Now.ToString();

            Console.WriteLine("Started For... Site URL " + siteURL + " and Doamin Name " + DomainName);
            GetAllUsersFormADomain(siteURL, DomainName);
            Console.WriteLine("Stared Executing at : " + StartedTime);
            Console.WriteLine("Complted Executing at : " + System.DateTime.Now.ToString());
            Console.Read();
        }

        private static bool DoesUserExistsDisabledAndDeletable(string strDomain, string strUserName)
         {
                 bool isUserExistsAndDisabled = false; 
                    using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, strDomain))
                    {
                       isUserExistsAndDisabled =  ForEachUserNameCheckExistsAndDisabled(strDomain, strUserName, pc);
                    }
                 return isUserExistsAndDisabled;

         }

        private static bool ForEachUserNameCheckExistsAndDisabled(string strDomain, string strUserName, PrincipalContext pc)
        {
            bool isUserExistsAndDisabled = false;
            
            UserPrincipal up = UserPrincipal.FindByIdentity(pc, strUserName);

            bool UserExists = (up != null);
            if (UserExists)
            {
                bool isEnabled = (bool)up.Enabled;
                if (isEnabled)
                {
                    isUserExistsAndDisabled = false;
                    Console.WriteLine(strDomain + " " + strUserName + " " + "Account Enabled...!!!");
                    File.AppendAllText("UsersStatus.txt", strDomain + " " + strUserName + " " + "Account Enabled...!!! Can not be Deleted." + "\r\n");
                    //TextWriter tsw = new StreamWriter(@"UsersStatusEnabled.txt", true);
                }
                else
                {
                    isUserExistsAndDisabled = true;
                    Console.WriteLine(strDomain + " " + strUserName + " " + "Account is Disabled...!!!");
                    File.AppendAllText("UsersStatus.txt", strDomain + " " + strUserName + " " + "Account is Disabled...!!! Deleted from SharePoint" + "\r\n");
                                 
                    //TextWriter tsw = new StreamWriter(@"UsersStatusDisabled.txt", true);
                }
            }
            else
            {
                isUserExistsAndDisabled = true;
                Console.WriteLine(strDomain + " " + strUserName + " " + "Account does not exists...!!!");

                File.AppendAllText("UsersStatus.txt", strDomain + " " + strUserName + " " + "Account does not exists...!!! Deleted from SharePoint." + "\r\n");
                //TextWriter tsw = new StreamWriter(@"UsersNotFound.txt", true);
            }
            return isUserExistsAndDisabled;
        }

        private static void GetAllUsersFormADomain(string siteURL, string DomainName)
        {
           
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite objSPSite = new SPSite(siteURL))
                {
                    if (objSPSite!=null)
                    {
                        DeleteUsers(objSPSite, DomainName);
                    }
                }
                
            });
        }

        private static void DeleteUsers(SPSite objSPSite, string DomainName)
        {
            SPWebApplication objSPWebApp = objSPSite.WebApplication;
                    foreach (SPSite siteCollection in objSPWebApp.Sites)
                    {
                        foreach (SPWeb web in siteCollection.AllWebs)
                        {
                            SPUserCollection objSPColl = web.AllUsers;
                            foreach (SPUser user in web.AllUsers)
                            {
                                string[] DomainAndUserName = user.LoginName.ToString().Split('\\');
                                if (DomainAndUserName != null && DomainAndUserName.Length > 0)
                                {
                                    string Domain = DomainAndUserName[0];
                                    string UserName = DomainAndUserName[1];
                                    if (Domain.ToLower().Equals(DomainName.ToLower()))
                                    {
                                        if (DoesUserExistsDisabledAndDeletable(DomainName.ToLower(), user.LoginName))
                                        {
                                            web.SiteUsers.Remove(user.LoginName);
                                        }
                                    }
                                }

                            }
                        }
                   }
        }

        
    }
}





Thursday, July 2, 2015

CRUD Operation in SharePoint List Using REST API in Windows Form with C#

Here is how we can we perform SharePoint List Add, Update and delete operations using REST API.

Structure of Form Solution we need to add a Service Reference with below URL:

http://severname:portname/sites/sitename/_vti_bin/listdata.svc

Add a Data Source using service reference by putting same URL:



Structure of the windows form application will be as below:


Now write below code to perform all operations:

namespace RESTExample
{
    public partial class REST : Form
    {
        BidManagementDataContext context;

        private void InitContext()
        {
            context = new BidManagementDataContext(new Uri("http://jsy-shpwebvt003:19891/sites/BidManagement/_vti_bin/ListData.svc"));
            context.Credentials = CredentialCache.DefaultCredentials;
        }

        public REST()
        {
            
            InitializeComponent();
        }

        private void Add_Click(object sender, EventArgs e)
        {
            InitContext();
            NotesItem objNotes = new NotesItem() { Title = "Insterted through Rest" };
            context.AddToNotes(objNotes);
            context.SaveChanges();
            BindList();
            
        }

        private void Update_Click(object sender, EventArgs e)
        {
            InitContext();
            NotesItem objNotes = context.Notes.FirstOrDefault();
            objNotes.Title = "Updated by Code...";
            context.UpdateObject(objNotes);
            context.SaveChanges();
            BindList();
        }

        private void Delete_Click(object sender, EventArgs e)
        {
            InitContext();
            NotesItem objNotes = context.Notes.FirstOrDefault();
            //objNotes.Title = "Updated by Code...";
            context.DeleteObject(objNotes);
            context.SaveChanges();
            BindList();
        }

        private void REST_Load(object sender, EventArgs e)
        {
            BindList();
        }

        private void BindList()
        {
            InitContext();
            notesBindingSource.DataSource = context.Notes;
        }

        
    }
}

Thursday, June 25, 2015

Redirect a SharePoint Edit form with ID without using any JavaScript using SharePoint Save feature.

To get ID of an item from a OOB SharePoint Custom edit page, we have to add get this from Query String. To pass it into OOB Save functionality. We have to pass it on the below

To redirect without any XSL variable:


<td class="ms-separator">&#160;</td>
                                                                                                                <td class="ms-toolbar" nowrap="">
                                                                                                                <input type="button" class="ms-ButtonHeightWidth" style="width:13em!important" value="Save and Redirect" name="btnSave" onclick="javascript: {ddwrt:GenFireServerEvent('__commit;__redirect={abc.aspx?Type=New}')}" />
                                                                                                </td>

In edit form with ID parameter:

Find this text:
                <xsl:param name="dvt_apos">&apos;</xsl:param>
                <xsl:variable name="dvt_1_automode">0</xsl:variable>

Add below text to store value in an XSL variable:

                <xsl:param name="ListItemId" />
    <xsl:variable name="RedirectLoc">abc.aspx?ItemID=<xsl:value-of select="$ListItemId"/></xsl:variable>


<input type="button" class="ms-ButtonHeightWidth" style="width:16em!important"  value="Save and Redirect" name="btnSave" onclick="javascript: {ddwrt:GenFireServerEvent(concat('__commit;__redirect={',$RedirectLoc,'}'))}"/>

Now if you wan tot fire PreSaveAction in addition to it, here are the important links to understand what is happening. Below I am writing what we need to add on our page:

Add this function to your JS of form:

function PreSaveItem()
 {
       if ("function"==typeof(PreSaveAction))
       {
         return PreSaveAction();
       }
     return true;
 }

Then change your button to below code:

<input type="button" class="ms-ButtonHeightWidth" style="width:16em!important" value="Save and Redirect" name="Save and Redirect" onclick="if (!PreSaveItem()) return false;{ddwrt:GenFireServerEvent(concat('__commit;__redirect={',$RedirectLoc,'}'))}" />

Now PreSaveAction will also be fired before redirecting. Also in case of multiple save button on forms, we can write something Just before PreSaveAction.


Thursday, May 7, 2015

Future for Microsoft SharePoint

What is the Future for Microsoft SharePoint?

Microsoft is facing important pressures from market and technology forces, which will force it to make fundamental changes to SharePoint's architecture and future development plans. Gartner analysts said SharePoint Online will evolve relatively quickly by integrating with Yammer, Exchange Online and Lync Online, to the extent that the lines between the various elements of the overall Office 365 suite will seem to disappear, although it remains possible to buy them separately. On premises SharePoint Server will follow a different path with slower updates.
Gartner’s Maverick research is designed to spark new, unconventional insights. Maverick research is unconstrained by Gartner’s typical broad consensus-formation process to deliver breakthrough, innovative and disruptive ideas from the company’s research incubator to help organizations get ahead of the mainstream and take advantage of trends and insights that could impact IT strategy and the wider organization.
SharePoint Today:
SharePoint has proven to be a highly successful product, bringing billions of dollars of annual revenue to Microsoft. It is used, in some form, at a majority of Gartner's clients. SharePoint does not excel in any particular area when compared with best-of-breed, single-purpose products. Instead, it provides "good enough" features across a variety of integrated capabilities. A large part of its success comes from providing reasonable support for most of the things, most people, need most of the time. Together with support from the third-party developer ecosystem, this brand promise has made SharePoint widely deployed. However, few end users really love using it. It remains a tool that people are required to use, not one they want to use.
Dilemmas, Microsoft is facing regarding SharePoint:
·         SharePoint needs to go to the cloud, but some customers can't or won't —Microsoft needs to move SharePoint to the cloud for its own interests, as well as the interests of its customers. However, many organizations using SharePoint cannot go to the cloud because they have regulatory restrictions or complex, customized implementations that prevent adopting SharePoint Online. Some third-party add-ons they depend on are not available for the cloud version. Others do not trust the cloud or see no reason to change, so they won't make the move.
·         Users want improvements, but IT doesn't want to upgrade — We regularly hear end users and administrators complain about features or user-experience improvements that they would like to see in SharePoint. Although they want new functionality, they are less keen to have more upgrades, which are seen as expensive, disruptive and time-consuming. It is difficult to see how users can expect to get changes without implementing new versions. If upgrades were easier, they might be less reticent to install new versions. This is a move Microsoft is trying to address with the app model introduced in SharePoint 2013.

How should users handle the overlapping functionality between Yammer and SharePoint?
Microsoft has recommended that users adopt the Yammer activity stream rather than the SharePoint newsfeed, and provided tools to do so. Customers who don't want to or cannot use Yammer (because it is cloud-based, for example) can continue to use the SharePoint newsfeed, although new developments will concentrate on the Yammer activity stream. Capabilities such as "following" documents are provided by SharePoint 2013's native interface, but do not support Yammer's activity stream.
Aside from this recommendation about the Yammer activity stream versus the SharePoint newsfeed, there is little guidance on how to handle the overlaps. Organizations must decide whether to use Yammer or SharePoint for groups, discussions, Q&A, blogs, wikis and file storage. Without guidance, users are unsure which way to go to avoid future difficulties.

 Will Microsoft Kill SharePoint?
In a word, "No." Gartner expects that the SharePoint product franchise will continue for quite some time, with new releases for both the on-premises and the cloud product. In one way, nothing has changed: SharePoint Server continues to be supported and developed, with new versions expected at pretty much the same schedule as with earlier versions.
However, this argument ignores the monumental efforts Microsoft is devoting to SharePoint Online and Yammer. It is disingenuous to expect that these cloud efforts will not affect the on-premises products, which would simply go on as before. Given how Microsoft is shifting focus to the cloud, and with differences emerging between SharePoint Online and SharePoint Server, it will become increasingly difficult to consider them the same product, especially as Microsoft integrates SharePoint Online ever more closely with Yammer, Lync Online and Exchange Online.

 What should organizations with complex, on-premises SharePoint installations do?
The implications I’ve mentioned will unfold slowly over several years — there is no need to take panicky, immediate action. SharePoint Server 2013 will be a viable platform for doing what it does now, at least until 2018 (when mainstream support ends). However, it is not too early to start planning for a post-SharePoint world.

While Microsoft will not walk away from this product line, there are strong arguments that the changes coming will split the on-premises and online versions of SharePoint sufficiently, and that Microsoft should acknowledge that they cannot remain as one product, and help customers plan accordingly.

Credit : http://www.gartner.com/newsroom/id/2605118

Tuesday, March 3, 2015

Setting custom scope in Advanced Search Web part and metadata property on Created Date of items in SharePoint 2010.

Some days back I have written about how to hide unnecessary links from a Advance Search Web part. Here I am adding some more points to make this search more user friendly and usable with minor tweaks.

Very first one is related to narrow down the scope of our search Web part. By default an advanced  search web part search for the whole Content source. We can not limit the scope of a Content source to a particular list or library. To get this we need to create scopes in SharePoint. While creating a scope if you want to narrow it down to a list level, then you need to put the URL of the list refer below:

http://test/sites/DemoSite/Lists/My%20List/



Add Url in the marked way, press OK and rule will be added to your scope.

Now we need to add this scope into our Advanced Search web part to narrow down the scope. For achieving  this we need to modify the XML for it. Top open the XML we need to edit the web part and click on area marked with arrow :




Once you click it will open the customized XML you are using for it. Below is the by default XML after adding your managed properties which you want to add on it.

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  <PropertyDefs>    <PropertyDef Name="Path" DataType="text" DisplayName="URL"/>    <PropertyDef Name="Size" DataType="integer" DisplayName="Size (bytes)"/>    <PropertyDef Name="Write" DataType="datetime" DisplayName="Last Modified Date"/>    <PropertyDef Name="FileName" DataType="text" DisplayName="Name"/>    <PropertyDef Name="Description" DataType="text" DisplayName="Description"/>    <PropertyDef Name="Title" DataType="text" DisplayName="Title"/>    <PropertyDef Name="Author" DataType="text" DisplayName="Author"/>    <PropertyDef Name="DocSubject" DataType="text" DisplayName="Subject"/>    <PropertyDef Name="DocKeywords" DataType="text" DisplayName="Keywords"/>    <PropertyDef Name="DocComments" DataType="text" DisplayName="Comments"/>    <PropertyDef Name="CNACreatedDate" DataType="datetime" DisplayName="Created Date"/>    <PropertyDef Name="CNAClientName" DataType="text" DisplayName="Client Name"/>    <PropertyDef Name="CNAClientNumber" DataType="text" DisplayName="Client Number"/>    <PropertyDef Name="CNACountry" DataType="text" DisplayName="Country"/>    <PropertyDef Name="CNACurrency" DataType="text" DisplayName="Currency"/>    <PropertyDef Name="CNAEMLTMSref" DataType="text" DisplayName="EML or TMS Ref "/>    <PropertyDef Name="CNAGBPEquivalent" DataType="text" DisplayName="GBP Equivalent"/>    <PropertyDef Name="CNAIPType" DataType="text" DisplayName="IP Type"/>    <PropertyDef Name="CNAManualCredit" DataType="text" DisplayName="Manual Credit"/>    <PropertyDef Name="CNAProjectReference" DataType="text" DisplayName="Project Reference"/>    <PropertyDef Name="CNARequestor" DataType="text" DisplayName="Requestor"/>    <PropertyDef Name="CNAStatus" DataType="text" DisplayName="Status"/>    <PropertyDef Name="CNATeam" DataType="text" DisplayName="Team"/>  </PropertyDefs>  <ResultTypes>    <ResultType DisplayName="Credit Note Approval" Name="Credit Note Approval">      <KeywordQuery />      <PropertyRef Name="CNACreatedDate" />      <PropertyRef Name="CNAClientName" />      <PropertyRef Name="CNAClientNumber" />      <PropertyRef Name="CNACountry" />      <PropertyRef Name="CNACurrency" />      <PropertyRef Name="CNAEMLTMSref" />      <PropertyRef Name="CNAGBPEquivalent" />      <PropertyRef Name="CNAIPType" />      <PropertyRef Name="CNAManualCredit" />      <PropertyRef Name="CNAProjectReference" />      <PropertyRef Name="CNARequestor" />      <PropertyRef Name="CNAStatus" />      <PropertyRef Name="CNATeam" />    </ResultType>  </ResultTypes></root>

In the above you just need to find the bold text and replace it with below text:

<KeywordQuery>Scope:"Your Scope Name"</KeywordQuery>

It will set search scope to only particular URl which we have added in our Scope Rule URL at that time.

Now we will talk about second part of this blog related to search on Created Date of list items. Its about finding the right crawled property to map it with our created date. For the List Items its always indexed in crawled property Basic:15(Date and Time):

For Author or Created By in a list:



 Hope it helps someone.

Thursday, January 15, 2015

Creating a SharePoint solution without any tool WSP Builder and VS2010. (Learning Basics)

To deploy anything into SharePoint you need below given three files :

1. Manifest.xml - Data about your solution structure.
2. ddf - Data 
3. dll - 

These are the files we need to deal with while deploying a solution in SharePoint. However now a days we have all these file creation and deployment would be done by Visual Studio or WSP builder.
These are aweesome tools and are very efficient, But as a Sharepoint Developer we still need to learn what happens behind the scene, files and its roles.

1. dll file - Just rebuild your solution and open BIN folder of your solution. Copy this dll file and copy it to the deployment folder of your application. Copy this DLL file into GAC and get details of public key token.

2, Manifest,xml -  Just add this file into Deployment folder. And provide all details as per your solution. 
SolutionId - Create a new GuId in registry format and add it.
PublicKeyToken - Details of your dll from GAC.

<?xml version="1.0" encoding="utf-8" ?>
<Solution xmlns="http://schemas.microsoft.com/sharepoint/"
 SolutionId="{04B8CC83-70A0-49cb-A745-91A89437A93F}" >

  <Assemblies>
    <Assembly DeploymentTarget="GlobalAssemblyCache" Location="TestByKrishna.dll">
      <SafeControls>
        <SafeControl Assembly="TestByKrishna, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1723b722c17f1304" Namespace="TestByKrishna" TypeName="*" Safe="True" />
      </SafeControls>
    </Assembly>
  </Assemblies>

</Solution>

3. ddf file - This file will be used as an input file for running makecab.exe utility. Just replace the dll file name and name of the WSP you want.

; makecab.exe tool takes a pointer to a .ddf file, 
;which describes the structure of the .cab file.  
;The This file is for WSP CAB Generation
;A WSS or in this case MOSS solution file is essentially a .cab file, 
;use the makecab.exe tool to create the solution package. 
;Theformat of a .ddf file is basically that
;you declare a standard header and 
;then enumerate, one file per line, the set of files by where they live on disk, 
;separated by where they should live in the .cab file

.OPTION EXPLICIT     ; Generate errors 
.Set CabinetNameTemplate="TestByKrishna.wsp"
.set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory
.Set CompressionType=MSZIP;** All files are compressed in cabinet files
.Set UniqueFiles="ON"
.Set Cabinet=on
.Set DiskDirectory1="Package"
;All file reference should be from the project root
;Files to place into the CAB Root

; Manifest
Manifest.xml

; DLLS
TestByKrishna.dll

Now run the following command from by cmd by pointing to the Deployment folder of your solution. Which contains these three files. 


You can see WSP in the package folder of your solution as per below image :


Now you can deploy your WSP on any server using Stsadm or powershell or Central Admin.

Tuesday, January 13, 2015

Get all duplicate values from a Asp.net data table for a particular column.

Here is a method which I have created to get all the rows which have duplicate values for title column. Code is as below :

protected DataTable FormatDataTableForClientDICBIC(DataTable objDatatable)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Column1");
            dt.Columns.Add("Column2");
            dt.Columns.Add("Column3");
            dt.Columns.Add("Column4");
            dt.Columns.Add("Column5");
            dt.Columns.Add("Column6");
            dt.Columns.Add("Title");
// Below content in bold format will help us to find all the Title which are present more than once in list with all number of occurences.
            var duplicates = objDatatable.AsEnumerable()
            .Select(dr => dr.Field<string>("Title"))
            .GroupBy(x => x)
            .SelectMany(grp => grp.Skip(1));

            if (duplicates.Count() > 0)
            {
                DataTable dtTitle = new DataTable();
                dtTitle.Columns.Add("Title");
                foreach (var item in duplicates)
                {
                    DataRow dr = dtTitle.NewRow();
                    dr["Title"] = Convert.ToString(item);
                    dtTitle.Rows.Add(dr);
                }

// Gets distinct values from each of them.

                DataView view = new DataView(dtTitle);
                DataTable distinctValues = view.ToTable(true, "Title");

                //List<DataRow> rows = new List<DataRow>();
                foreach (DataRow item in distinctValues.Rows)
                {
                    string ICName = Convert.ToString(item["Title"]);
                    //DataRow dr = dt.NewRow();
                    //dr["IC Name"] = ICName;
                    //dt.Rows.Add(dr);


                    if (!string.IsNullOrEmpty(ICName) && (!(ICName.Equals("TBD") || ICName.Equals(@"N/A") || ICName.Equals("Declined"))))
                    {
                        var dataResults = from r in objDatatable.AsEnumerable()
                                          where (Convert.ToString(r["Title"]) == ICName)
                                          select r;
                        if (dataResults.Count() > 0)
                        {
                            foreach (var subitems in dataResults)
                            {
                                DataRow dr = dt.NewRow();
                                dr["Column1"] = subitems["Column1"];
                                dr["Column2"] = subitems["Column2"];
                                dr["Column3"] = subitems["Column3"];
                                dr["Column4"] = subitems["Column4"];
                                dr["Column5"] = subitems["Column5"];
                                dr[""Column6] = subitems["Column6"];
                                dr["Title"] = subitems["Title"];

                                dt.Rows.Add(dr);
                            }
                        }
                    }
                }
            }

            return dt;

        }

Now we can use this returned data table to show all repeated titles with details of all columns. If you want you can also use the schema of Same DataTable which is an input parameter, instead of writing a new one. Hope it helps. Please let me know if there is any better way (performance wise) to do it. 

Tuesday, January 6, 2015

How to Force an MSI Package to Install Using Administrator Mode

I was installing a nintex package to one of my SharePoint 2010 server. But was getting an error regarding user's credentials. Then I noticed I am not getting options for Running option as administrator. her Courtesy to this link: I have found an option to install it. Please go through below options :



00_lead_image_uac_dialog_for_msi_file
When you need to install a program as an administrator, you can right-click on the .exe file and select Run as administrator. However, that option isn’t available for MSI packages. We will show you how to add an Install as administrator option for MSI packages.
01_selecting_run_as_administrator
To add the Install as administrator option to the context menu for MSI packages, right-click on the Start button and select Run from the command menu, if you’re using Windows 8.1. If you’re using Windows 7 or another earlier version, select Run from the Start menu.
NOTE: You can also press the Windows key + R to access the Run dialog box.
02_selecting_run_from_winx_menu
Enter “regedit” (without the quotes) in the Open edit box and click OK.
03_entering_regedit_on_run_dialog
If the User Account Control dialog box displays, click Yes to continue.
NOTE: You may not see this dialog box, depending on your User Account Control settings.
04_uac_dialog_for_regedit
Navigate to the following key:
HKEY_CLASSES_ROOT\Msi.Package\shell
Right-click on the shell key and select New | Key from the popup menu.
05_creating_new_key
The new key is added as a sub-key under shell. Rename it to “runas” (without the quotes).
06_renaming_new_key
Right-click on the Default value in the right pane and select Modify from the popup menu.
NOTE: You can also double-click on Default to edit its value.
07_modifying_default_value_for_runas_key
On the Edit String dialog box, enter “Install as &administrator” (without the quotes) in the Value data edit box and click OK.
08_entering_value_data_for_runas
Now, you need to add a sub-key to the runas key. Right-click on the runas key and select New | Key from the popup menu. Rename the sub-key “command” (without the quotes).
09_creating_new_subkey
Select the command sub-key and double-click Default in the right pane to edit its value. On the Edit String dialog box, enter the following in the Value data edit box:
msiexec /i “%1”
Click OK.
10_entering_value_data_for_command
Close the Registry Editor by selecting Exit from the File menu.
11_closing_registry_editor
Now, when you right-click on an MSI installation package file, the Install as administrator option is available.
12_selecting_install_as_administrator
When you select the Install as administrator option, the User Account Control dialog box may display, as shown at the beginning of this article, depending on your UAC settings.