Friday, May 19, 2017

Create Self Signed Certificate for Development Environment

In the development environment we can use a self-signed certificate, but for production environment we will need a commercial certificate to publish Apps to store. So we will follow below steps to create a self signed certificate.

1. Open IIS Manager, and click on Server Certificates. (start > Run > inetmgr)


2. Double click on Server Certificates. It will open Server Certificates window, Click on Create Self Signed Certificate from Right most Action window.

3. Enter some meaningful name like "SharePointOnlieTest" and Click on Ok.

4. Certificate is created and will be displayed in Server Certificates window.
5. Now we need to export the personal exchange format (.pfx) file. Right Click on the "SharePointOnlieTest" Certificate in IIS click on Export and provide an accessible location. Also enter the password that you want to use and Click on Ok.

6. Now double click on the "SharePointOnlieTest" Certificate in IIS. Click on Details tab and click on Copy to File.

7. Follow Export Wizard (earlier we exported the .pfx file). Keep Clicking Next across the three screens. Below are the screenshots demonstrate the same. Just one thing to mark that now we are now exporting the .cer file. I choose the same location. Click on Save.

8.Finally, click on Finish. You should see you the message “The export was successful”.​​

Wednesday, May 17, 2017

SharePoint 2016 - SharePoint List in SharePoint Hosted App

In this post we will develop a SharePoint List in SharePoint hosted App.

SharePoint apps designed to provide specific functionality in SharePoint. So in this article we will talk about a simple scenario of adding the list. That is how we are normally going to use and develop the Apps on SharePoint. Follow below step by step instruction to create a List in SharePoint Hosted App.

Open Visual Studio 2015 and create SharePoint Add In Project.
Now Add New Item for Site Column. Name it "MyCustomCol".
Add New Item for Custom Content Type, name it "MyContentType"
Inherit Item content type on next wizard page and click on Finish.When MyContentType configuration page shows up, Select columns based on need along with custom created columns.
Now Add new Item - Select List - and Name list as  MyInterviewSchedule.
Make changes based on need.

Now next page will open in Visual Studio for Selecting Columns/ Content Type. Click on button to select our custom content type.
Select our custom content type from list. Remove other if needed.
Now columns are displayed in the List.

Build Project and Click on Deploy.Now on your SharePoint site you will see the App, in my case it is "Create List" under Site Content.

Now clicking on it will launch Default.aspx of the app.
But now where is my list which I have created and defined in Visual Studio? To Set list as starting page when we deploy app. We have to change Appmanifest.xml start page settings as "CreateList/Lists/MyInterviewSchedule".
Now Build and Deploy App. Once deployed click on "CreateList" app it will launch MyInterviewSchedule list default. Click on New item will launch below form.
Conclusion:
We learned how to develop SharePoint list in SharePoint hosted App.

Saturday, May 13, 2017

Error -- SharePoint 2013 Apps: The provided App differs from another App with the same version and product ID

I was doing development in Visual Studio 2015 and while was trying to deploy SharePoint Add-in it gave error.

Error : Error occurred in deployment step 'Install SharePoint Add-In' the provided app differ from The provided App differs from another App with the same version and product ID.

Reason :

You are not allowed to deploy Apps with the Farm Account.

  • Create a new User in Active Directory. 
  • Add new created User to the SQL SharePoint Config database.
  • Add to Local Computer ‘Administrators’ group, 
  • Add to the SharePoint Farm Administrators group in Central Admin and also to the Site Collection Admin as of the Developer Site Collection.


This should resolve issue.

Friday, May 12, 2017

Generic SharePoint Jquery / Javascript functions - 2

This is another part of SharePoint jQuery / Javascript functions.

//Get element from page with partial element id
//elemIdPart is the second half (after GUID) of the client id of hidden input 

function GetElement(elemIdPart) {
var inputElems = document.getElementsByTagName('input');
for (i = 0; i < inputElems.length; i++) {
if (inputElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
var inputElement = inputElems[i];
return inputElement;
}
}
}

//Disable element from page with partial element id
//elemIdPart is the second half (after GUID) of the client id of hidden input 

function DisableField(elemIdPart) {
    if (elemIdPart.toString().match("Lookup$") == "Lookup" || elemIdPart.toString().match("Choice$") == "Choice") {
        var selectElems = document.getElementsByTagName('select');
        for (i = 0; i < selectElems.length; i++) {
            if (selectElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
                var selectElement = selectElems[i];
                selectElement.style.display = "none";

                var newElem = document.createElement("nobr");
                if (selectElement.selectedIndex >= 0 && selectElement.options[selectElement.selectedIndex])
                    newElem.innerHTML = selectElement.options[selectElement.selectedIndex].text;

                selectElement.parentNode.insertBefore(newElem, selectElement);
                break;
            }
        }
    }    
    else if (elemIdPart.toString().match("DateTimeFieldDate$") == "DateTimeFieldDate") {
        var inputElems = document.getElementsByTagName('input');
        for (i = 0; i < inputElems.length; i++) {
            if (inputElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
                var inputElement = inputElems[i];
                inputElement.style.display = "none";
                inputElement.parentNode.parentNode.parentNode.parentNode.style.display = "none"; // hide Table
                var newElem = document.createElement("nobr");
                newElem.innerHTML = inputElement.value;
                inputElement.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(newElem);
                break;
            }
        }
    }
    else {
        var thisElem = null;
        var inputElems = document.getElementsByTagName('input');        
        for (i = 0; i < inputElems.length; i++) {
            if (inputElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
                thisElem = inputElems[i];
                var inputElement = inputElems[i];
                inputElement.style.display = "none";

                var newElem = document.createElement("nobr");
                if (inputElement.type == 'checkbox') {
                    if (inputElement.checked)
                        newElem.innerHTML = 'Yes';
                    else
                        newElem.innerHTML = 'No';
                }
                else {
                    newElem.innerHTML = inputElement.value;
                }
                inputElement.parentNode.insertBefore(newElem, inputElement);
                break;
            }
        }

        if (thisElem == null) { // If type input not found, check in textarea
            var inputElems = document.getElementsByTagName('textarea');
            for (i = 0; i < inputElems.length; i++) {
                if (inputElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
                    thisElem = inputElems[i];
                    var inputElement = inputElems[i];
                    inputElement.style.display = "none";

                    var newElem = document.createElement("nobr");                   
                    newElem.innerHTML = inputElement.value;
                    inputElement.parentNode.insertBefore(newElem, inputElement);
                    break;
                }
            }
        }
    }

    return 0;
}

// Function to disable lookup fields which have large number of items
function DisableLookUpField(elemIdPart) {
    var inputElems = document.getElementsByTagName('input');

    for (i = 0; i < inputElems.length; i++) {
        if (inputElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
            var inputElement = inputElems[i];
            inputElement.style.display = "none"; // hide the input element

            var newElem = document.createElement("nobr");
            newElem.innerHTML = inputElement.value;

            inputElement.nextSibling.style.display = 'none'; // hide the drop down arrow image

            inputElement.parentNode.insertBefore(newElem, inputElement);

            break;
        }
    }

    return 0;
}

//Function to disable people/group picker field in Sharepoint.
Where, 
//elemIdPart is the second half (after GUID) of the client id of hidden input Element ().
//This input element is the first child node of , the starting tag for the people picker field.

function DisablePeoplePickerField(elemIdPart) {
    var inputElems = document.getElementsByTagName('input');

    for (i = 0; i < inputElems.length; i++) {
        if (inputElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
            var inputHiddenElement = inputElems[i];

            /*
            Value of the hidden input element is in the format ##.....
            Split the value using # as the separator, the resulting array will have USERACCOUNT(UID) at it's Odd(Even) positions.
            */
            var useraccounts = inputHiddenElement.value.split('#');
            var strUserAccounts = "";
            for (j = 1; j < useraccounts.length; j += 2) {
                strUserAccounts += useraccounts[j] + " ";
            }

            var newElem = document.createElement("nobar");
            newElem.innerHTML = strUserAccounts;

            inputHiddenElement.parentNode.childNodes[2].style.display = 'none';
            inputHiddenElement.parentNode.insertBefore(newElem, inputHiddenElement);

            break;
        }
    }

    return 0;
}


function DisableCascadingLookupField(FieldIdPart) {
    var selectElems = document.getElementsByTagName('select');

    for (i = 0; i < selectElems.length; i++) {
        if (selectElems[i].getAttribute('id').indexOf(FieldIdPart) > -1) {
            var CascadingFieldElem = selectElems[i];
            var strSelectedVals = "";

            for (i = 0; i < CascadingFieldElem.length; i++) {
                if (CascadingFieldElem.options[i].selected)
                    strSelectedVals += CascadingFieldElem.options[i].text + ";";
            }

            var newElem = document.createElement("nobr");
            newElem.innerHTML = strSelectedVals.substr(0, strSelectedVals.length - 1);

            CascadingFieldElem.style.display = 'none';
            CascadingFieldElem.parentNode.insertBefore(newElem, CascadingFieldElem);

            break;
        }
    }

    return 0;
}


//Function to hide fields in forms
//Parameter fieldLabelName is the name of the field label's element.

function HideFieldInDisplayForm(fieldLabelName) {
    var elems = document.getElementsByName(fieldLabelName);
    if (elems.length > 0) {
        var elemToHide = elems[0];
        while (elemToHide.tagName.toLowerCase() != "tr") {
            elemToHide = elemToHide.parentNode //traverse up the TR element
        }
        elemToHide.style.display = 'none';
    }
}

function HideField(elemIdPart) {
    var el = GetField(elemIdPart);
    if (el) {
        while (el.tagName.toLowerCase() != "tr") {
            el = el.parentNode; // breaks if no "tr" in path to root
        }

        el.style.display = "none";
    }
}

function ShowField(elemIdPart) {
    var el = GetField(elemIdPart);
    if (el) {
        while (el.tagName.toLowerCase() != "tr") {
            el = el.parentNode; // breaks if no "tr" in path to root
        }

        el.style.display = "";
    }
}

function HideDateTimeField(elemIdPart) {
    var el = GetField(elemIdPart);
    if (el) {
        while (el.tagName.toLowerCase() != "tr") {
            el = el.parentNode; // breaks if no "tr" in path to root
        }

        el = el.parentNode;

        while (el.tagName.toLowerCase() != "tr") {
            el = el.parentNode; // breaks if no "tr" in path to root
        }

        el.style.display = "none";
    }
}

function ShowDateTimeField(elemIdPart) {
    var el = GetField(elemIdPart);
    if (el) {
        while (el.tagName.toLowerCase() != "tr") {
            el = el.parentNode; // breaks if no "tr" in path to root
        }

        el = el.parentNode;

        while (el.tagName.toLowerCase() != "tr") {
            el = el.parentNode; // breaks if no "tr" in path to root
        }

        el.style.display = "";
    }
}

function GetField(elemIdPart) {
    var ElementField;
    if (elemIdPart.toString().match("Lookup$") == "Lookup" || elemIdPart.toString().match("Choice$") == "Choice") {
        var selectElems = document.getElementsByTagName('select');
        for (i = 0; i < selectElems.length; i++) {
            if (selectElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
                ElementField = selectElems[i];
                break;
            }
        }
    }
    if (elemIdPart.toString().match("DropDownChoice$") == "DropDownChoice") {
        var selectElems = document.getElementsByTagName('select');
        for (i = 0; i < selectElems.length; i++) {
            if (selectElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
                ElementField = selectElems[i];
                break;
            }
        }
    }
    else if (elemIdPart.toString().match("DateTimeFieldDate$") == "DateTimeFieldDate") {
        var inputElems = document.getElementsByTagName('input');
        for (i = 0; i < inputElems.length; i++) {
            if (inputElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
                ElementField = inputElems[i];
                break;
            }
        }
    }
    else {
        var inputElems = document.getElementsByTagName('input');
        for (i = 0; i < inputElems.length; i++) {
            if (inputElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
                ElementField = inputElems[i];
                break;
            }
        }
        if (ElementField) return ElementField;
        inputElems = document.getElementsByTagName('textarea');
        for (i = 0; i < inputElems.length; i++) {
            if (inputElems[i].getAttribute('id').indexOf(elemIdPart) > -1) {
                ElementField = inputElems[i];
                break;
            }
        }
    }

    return ElementField;
}

// Cookie related functions 

function createCookie(name, value, days) {
    if (days) {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        var expires = "; expires=" + date.toGMTString();
    }
    else var expires = "";
    document.cookie = name + "=" + value + expires + "; path=/";
}

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
    }
    return null;
}

function eraseCookie(name) {
    createCookie(name, "", -1);
}

You can use above function like below....

$(document).ready(function () {

var inputDateField = GetElement('ID of the element ... you can provide partial ID'); 
inputDateField.onvaluesetfrompicker = function () {
//do something here in funtion.
var titleField = GetElement('ID of Title Field'); //Title Field
title.value = "Nilesh";
title.parentNode.childNodes[0].innerHTML = "Nilesh";
}

inputDateField.onchange = inputDateField.onvaluesetfrompicker;
});

Generic SharePoint Jquery / Javascript functions -1

Below are few very generic Jquery / Javascript functions which can be used by SharePoint developer in daily activities.

var getFileName = function () {
    var chkVisible = $('[id*="_onetidIOFile"]').is(':visible');
    var filename;

    if (chkVisible) {
        filename = $('[id*="_onetidIOFile"]').val() + $("span[dir='ltr']").text();
    }
    else {
        filename = $("[id*='_onetidIOFile']:eq(1), span[dir='ltr']").text();
    }
    return filename;
}

var setTitleField = function (strTitleVal) {
    $("input[Title='Title']").val(strTitleVal);
}

var hideTitleRow = function () {
    $("input[Title='Title']").closest('tr').hide();
}

var hideInputFieldRow = function (fldName) {
    $("nobr:contains('" + fldName + "')").closest("tr").hide();
}

var btnTextChange = function () {
    //setButtonAvailability(
    //currentElem ,
    //strCondition
    //btnValue

    setButtonAvailability(this, 'This file can be Published to SP', 'Publish File');
}


var setButtonAvailability = function (currElem, strCondition, btnValue) {

    //currentElem ,
    //strCondition
    //btnValue

    if ((currElem.innerText === strCondition) && ($("input[value$='" + btnValue + "']").is(":disabled"))) {
        $("input[value$='" + btnValue + "']").prop('disabled', false);
    }
    else if ((currElem.innerText != strCondition)) {
        $("input[value$='" + btnValue + "']").attr("disabled", "disabled");
    }
}


var changeButtonValue = function (btnID, strNewValue) {
    var btnVal = document.getElementById(btnID).value;
    $("input[value$='" + btnVal + "']").attr('value', strNewValue);
}


var IsValidFileName = function (strFileName) {
    var fileNameAdditionalDots = new RegExp("[(?!\.\w*$)\.]");
    var fileNameSpecialCharacters = new RegExp("[~#%&*{}<>':;?/+|\"]");

    if (strFileName !== '') {
        //if (fileNameSpecialCharacters.test(strFileName) || fileNameAdditionalDots.test(strFileName)) {
        if (fileNameSpecialCharacters.test(strFileName)) {
            alert("Please remove the special characters or additional dots from the file name.");
            return false;
        }
        else {
            return true;
        }
    }
    else {
        alert("File name cannot be empty.");
        return false;
    }
}

var ifSelectionSelected = function (strDocType,strFldName) {
    if (strDocType === '' || strDocType === '(None)') {
        alert('Please select value for field '+strFldName);
        return false;
    }
    else {
        return true;
    }
}

var stringEncripte = function (strToEncript) {
    var xorKey = 129;
    var EncryptedString = '';
    for (i = 0; i < strToEncript.length; ++i) {
        EncryptedString += String.fromCharCode(xorKey ^ strToEncript.charCodeAt(i));
    }
    return EncryptedString;
}

var DisableBtnIfPublished = function (isPublishedFieldID, btnValue) {
    var isPublished = GetField(isPublishedFieldID);
    if (isPublished.checked) {
        $("input[value$='" + btnValue + "']").attr("disabled", "disabled");
    }
    else {
        $("input[value$='" + btnValue + "']").prop('disabled', false);
    }
}

var isElementVisible = function (strControl, strControlText) {
    return $(strControl).filter(function () {
        return $(this).text() === strControlText;
    }).is(':visible');
}

var ToggleButtonBehavior = function () {

    if (isElementVisible('div', 'Please select a Document Type.')) {
        $("input[value$='Publish File']").attr("disabled", "disabled");
    }
    else if (isElementVisible('table', 'This file has failed validation. Please see below for details:')) {
        $("input[value$='Publish File']").attr("disabled", "disabled");
    }
    else if (isElementVisible('table', 'This file has passed column name validation')) {
        var isPublishedFldId = $("input[Title='Is Published']").attr('id');
        DisableBtnIfPublished(isPublishedFldId, 'Publish File');
    }
    else {
        $("input[value$='Publish File']").attr("disabled", "disabled");
        setTimeout(ToggleButtonBehavior, 1000);
    }
    
    try {
        SP.SOD.executeOrDelayUntilScriptLoaded(SP.UI.ModalDialog.get_childDialog().autoSize(), 'sp.ui.dialog.js');
    }
    catch (error) {
        /*console.log('Waiting for File Validation.');*/
    } 
}

Automatic web.config changes using a SharePoint, File Size Upload,Web Application level feature

By default for SharePoint, Machine.config is configured to accept HTTP Requests up to 4096 KB (4 MB) and it is reflected in all your ASP.NET applications. TO upload larger files, You can change the Machine.config file directly, or you can change only the Web.config file of the respective application(s). Ideal way is to change web.config of the relevant application.

Now if you have access to server, you can modify web.config directly. Open your Web.config file, and just below the tag, add the following tag:

<system.web>
<httpRuntime executionTimeout="999999" maxRequestLength="2097151" />.....

But if the same changes required to be made to UAT or PROD environment, most of the time developer does not have access to servers where they can access web.config. In that scenario we have to achieve this by developing WebApplication level feature, which does this changes for us.

Below is the class which does same job on feature activated.

public class customWebConfigEventReceiver : SPFeatureReceiver
    {
        string modOwner = "LargeFileUpload";

        // Uncomment the method below to handle the event raised after a feature has been activated.
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
            RemoveAllCustomisations(webApp);

            Collection modsCollection = webApp.WebConfigModifications;
            bool configExist = false;
            for (int i = 0; i < modsCollection.Count; i++)
            {
                if (modsCollection[i].Owner == modOwner)
                {
                    configExist = true;
                    break;
                }
            }
            if (!configExist)
            {
                webApp.WebConfigModifications.Add(createWebConfigModification("/configuration/system.web/httpRuntime", "executionTimeout", modOwner, "999999"));
                webApp.WebConfigModifications.Add(createWebConfigModification("/configuration/system.web/httpRuntime", "maxRequestLength", modOwner, "2097151"));
                webApp.Update();
                webApp.Farm.Services.GetValue().ApplyWebConfigModifications();
            }


        }

        protected SPWebConfigModification createWebConfigModification(string sPath, string sName, string sOwner, string sValue)
        {
            //SPWebConfigModification myModification = new SPWebConfigModification(modName, modPath);
            SPWebConfigModification httpRuntimeModification = new SPWebConfigModification();
            httpRuntimeModification.Path = sPath;
            httpRuntimeModification.Name = sName;
            httpRuntimeModification.Sequence = 0;
            httpRuntimeModification.Owner = sOwner;
            httpRuntimeModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute;
            httpRuntimeModification.Value = sValue;
            return httpRuntimeModification;
        }

        private void RemoveAllCustomisations(SPWebApplication webApp)
        {
            if (webApp != null)
            {
                Collection collection = webApp.WebConfigModifications;
                int iStartCount = collection.Count;

                // Remove any modifications that were originally created by the owner.
                for (int c = iStartCount - 1; c >= 0; c--)
                {
                    SPWebConfigModification configMod = collection[c];

                    if (configMod.Owner == modOwner)
                    {
                        collection.Remove(configMod);
                    }
                }

                // Apply changes only if any items were removed.
                if (iStartCount > collection.Count)
                {
                    webApp.Update();
                    webApp.Farm.Services.GetValue().ApplyWebConfigModifications();
                }
            }
        }

        // Uncomment the method below to handle the event raised before a feature is deactivated.

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPWebApplication webApp = (SPWebApplication)properties.Feature.Parent;
            RemoveAllCustomisations(webApp);
            webApp.WebConfigModifications.Remove(createWebConfigModification("/configuration/system.web/httpRuntime", "executionTimeout", modOwner, "999999"));
            webApp.WebConfigModifications.Add(createWebConfigModification("/configuration/system.web/httpRuntime", "maxRequestLength", modOwner, "51200"));
            webApp.Update();
            webApp.Farm.Services.GetValue().ApplyWebConfigModifications();

        }
}

You can make settings value (True/False) in Feature Property based on need like,

  • Activate On Default
  • Always Force Install
  • Auto Active In Central Admin