Monday, September 25, 2017

Does C# support multiple inheritance?

C# does not support multiple inheritance (meaning a single class inherits from multiple classes). You can, however, implement multiple interfaces in a single class.
As far as chaining together inherited classes, there isn't a limit per-se. Just keep in mind the complexity you will introduce to your system. When using inheritance, make sure you are using it in a "is a" scenario.

A dog is an animal. A Honda is a car. Otherwise, your inheritance tightly couples your classes with a design that becomes much more difficult to maintain.
If they are static "utility" methods, just invoke them directly without inheriting. Unless those methods belong to the entity you are creating, you should not use inheritance.

Saturday, September 23, 2017

WCF vs WebAPI

Some fact about WCF :

If you need to communicate over pure TCP socket or any other protocol then HTTP use WCF. WCF can communicate is wide range of protocol.
Creating services that are transport/protocol independent. Single service with multiple endpoints.
Like one WCF service can have multiple endpoints based on clients. For example- One  web application request protocol -> http and response -> xml, another client could be TCP and Binary response.

If you have limitation and stuck with .Net framework 3.5 then create WCF restful service otherwise use WebAPI Resuful service. Lot of configuration is required to turn WCF service to turn in to Restful service.

Now WebAPI:
WebAPI is Restful service which only rely on HTTP protocol.

REST Constraints:
Client Server: In REST architecture there is always a client and a server where the communication is always initiated by the client. The client and server are decoupled by a uniform interface there by making both the client and server to develop independently. Every resource in the server is accessed by a unique address (URI).

Stateless : we should not storing anything related to client on server.

Cacheable: some data provided by server does not change that often, so let client know how long data is good and does not require change and avoid requests to server.

Uniform Interface: An important concept of REST is the uniform interface. The uniform interface contains a set of methods that can be understood by both the client and the server. In the HTTP uniform interface the important methods are GET, POST, PUT, DELETE, HEAD and OPTIONS. It is important to choose the right method for the right operation. For ex. if the client is going to get the resource from the server then they should use GET method.

Friday, September 22, 2017

What is event loop in javascript?

I was reading more details on Heap and Stack in JavaScript. I came across video of Philip Roberts where he discuss how event loop works and what is execution process of JavaScript engine. Really nicely explained concept.

He also developed tool LOUNE to understand how JavaScript executes and processes requests.

Worth listening and understanding as web developer.

Friday, September 1, 2017

Remote Event Receiver - Difference Process Event() And Process One Way Event()

Remote Event Receiver in SharePoint (2013 and more up to date), we go over two methods that are available default when we create a remote event receiver *.svc file (generated by system). These are --
  • ProcessEvent()
  • ProcessOneWayEvent()
Both the methods are always confusing as for their usage. There is very limited information available on the web with respect to these methods. In this way, here is the essential difference between them by which one can get the unmistakable fundamental thought of them both, subsequently, choosing the required one between them to write their business codes.

We should comprehend the sorts of events fired in event receivers. There are for the most part 2 types event fired on any operations on list or libraries - "before events" and "after events".
Now all events finishing with "- ing" are named as “Before events”, while every one of the events finishing with "- ed" are called as “After events”.
Below are the Before and After Events -
Before Events
After Events
ListAdding
ListAdded
ListDeleting
ListDeleted
FieldAdding
FieldAdded
FieldDeleting
FieldDeleted
FieldUpdating
FieldUpdated
ItemAdding
ItemAdded
ItemUpdating
ItemUpdated
ItemDeleting
ItemDeleted
ItemCheckingOut
ItemCheckedOut
ItemCheckingIn
ItemCheckedIn
ItemUnCheckingOut
ItemUnCheckedOut
ItemAttachmentAdding
ItemAttachmentAdded
ItemAttachmentDeleting
ItemAttachmentDeleted
ItemFileMoving
ItemFileMoved
ItemVersionDeleting
ItemVersionDeleted
Now, when we are aware of After and Before events, it becomes easy to understand the basic difference between these methods.

ProcessEvent()
  • It handles "Before" events and returns an object to SharePoint that reports on whether it should cancel the current process or terminate it.

  • If you want to use any of the “-ing” events, then write your codes in ProcessEvent().

  • Example: If you wish that there should be only excel (*.xlsx) file uploaded in particular document library, this can be done using the file type extension setting in SharePoint Server Administration.

    But, what about SharePoint Online?

    So, here you have to create remote event receiver and in that, you can use the event of ItemAdding and check whether the uploaded document is of *.xlsx type or not. If not, then you can cancel the uploading event. This cancelled event will return back to SharePoint by this ProcessEvent() as this is 2 way method. This can be achieved by writing your logic code in ProcessEvent().
ProcessOneWayEvent()
  • It handles "After" events. It runs asynchronously and does not return anything to SharePoint.

  • If you are using any code which is to be run after the “-ed” event, then write your codes in ProcessOneWayEvent().

  • Example: Let's say, you want to duplicate the document uploaded in document library to any other document library, in that case, you can use ItemAdded. This does not require any 2 way communications between SharePoint, so you can use ProcessOneWayEvent() for this kind of requirement.


Friday, August 18, 2017

MVC Controller - Disambiguating actions

When two actions match through routing, MVC must disambiguate to choose the 'best' candidate or else throw an exception. For example:
public class ProductsController : Controller{
public IActionResult Edit(int id) { ... }
[HttpPost]
public IActionResult Edit(int id, Product product) { ... }
}

This controller defines two actions that would match the URL path /Products/Edit/17 and route data { controller = Products, action = Edit, id = 17 }. This is a typical pattern for MVC controllers where Edit(int) shows a form to edit a product, and Edit(int, Product) processes the posted form. To make this possible MVC would need to choose Edit(int, Product) when the request is an HTTP POST and Edit(int) when the HTTP verb is anything else.



The HttpPostAttribute ( [HttpPost] ) is an implementation of IActionConstraint that will only allow the action to be selected when the HTTP verb is POST. The presence of an IActionConstraint makes the Edit(int, Product) a 'better' match than Edit(int), so Edit(int, Product) will be tried first.

You will only need to write custom IActionConstraint implementations in specialized scenarios, but it's important to understand the role of attributes like HttpPostAttribute - similar attributes are defined for other HTTP verbs. In conventional routing it's common for actions to use the same action name when they are part of a show form -> submit form workflow. The convenience of this pattern will become more apparent after reviewing the Understanding IActionConstraint section.
If multiple routes match, and MVC can't find a 'best' route, it will throw an AmbiguousActionException.

Wednesday, June 28, 2017

Closure in JavaScript

“…an inner function always has access to the
vars and parameters of its outer function, even
after the outer function has returned.”
-- Douglas Crockford

In Non Closure variable value will be lost once function return. And whenever it is called it will be assigned new value. Below is example of non closure.

function NonClosureFunct(){
var counter = 0;
counter += 1;
return counter;
}

Closure  help to address this problem and retain value of variable even after return from function.Variable stays around even after function returns.

function ClosureFunct(){
var counter = 0;
return function(){ counter +=1;};
}

Monday, June 12, 2017

SPUtility.js is a JavaScript library used to make modifications to SharePoint's list forms

SPUtility.js is a JavaScript library used to make modifications to SharePoint's list forms (NewForm.aspx and EditForm.aspx in a survey, custom list or library). It works with SharePoint 2007, 2010, and 2013 (including SharePoint Online / Office 365).
SPUtility.GetSPField('Title').SetValue('Hello world!');
Features:
  • Set or get field values in Document Libraries, all sorts of List forms (custom lists, issues, etc), and survey
  • Make a field read only
  • Hide a field from view
  • No server side code to deploy!
This can be used for:
  • Preventing a user from selecting a value when an item is initially created (ex: Status must be PENDING when the item is created)
  • Hiding fields from a submitter but allowing the field to be edited (or vice versa).
  • Auto-populating the form using a URL with query parameters
  • Auto-populate a list column with a sequential number
  • Hide/Show field on list form based on value from another field

Thanks to authors for making this wonderful utility.

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;
});