October 19, 2016

How to create Custom action to deploy with Sharepoint Add-ins(Apps)

There are two basic types of SharePoint Apps/Add-ins: SharePoint Hosted and Provider Hosted. Here, I will show how we can create custom action in host web document library through SharePoint Add-ins and open a model popup on click. Follow below steps:

Step 1:
Open your SharePoint App project in Visual Studio Solution. Add New Item, select Ribbon Custom action and give it name and click on Add.


Step 2:
Now in second dialog box, we have to set properties for custom action. In Dialog box. Select appropriate option based on requirement. Here, I have selected custom action scope to "List Template" and custom action scope location set to "Document Library" and click on Next.

You can select any type like Custom List, Calendar, Form Library etc.


Step 3:
Now in third dialog box, we have to specify the settings to generate a button control for ribbon. Here, I have selected "Ribbon.Documents.EditCheckout" as control location (Ribbon group where you would like to put the Control), "Demo Modal" as button control text (Name of your Control), and provide default page URL where button control navigates. Click on Finish. Now, custom action is created.


Step 4: 
Open Elements.xml file and add following attributes in <CustomAction> tag.

                HostWebDialog="TRUE"
                HostWebDialogWidth="600"
                HostWebDialogHeight="400" 


Your Elements.xml file looks like below

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="26a48039-5fc9-45fc-aabb-287b3ccedd3f.Demo_Modal"
                RegistrationType="List"
                RegistrationId="101"
                Location="CommandUI.Ribbon"
                Sequence="10001"
                HostWebDialog="TRUE"
                HostWebDialogWidth="600"
                HostWebDialogHeight="400"
                Title="Demo Modal">
    <CommandUIExtension>      
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.EditCheckout.Controls._children">
          <Button Id="Ribbon.Documents.EditCheckout.Demo_ModalButton"
                  Alt="Demo_Modal"
                  Sequence="100"
                  Command="Invoke_Demo_ModalButtonRequest"
                  LabelText="Demo_Modal"
                  TemplateAlias="o1"
                  Image32by32="_layouts/15/images/placeholder32x32.png"
                  Image16by16="_layouts/15/images/placeholder16x16.png" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler 
          Command="Invoke_Demo_ModalButtonRequest"
          CommandAction="~appWebUrl/Pages/Default.aspx?{StandardTokens}&amp;
          SPListItemId={SelectedItemId}&amp;SPListId={SelectedListId}&amp;SPListURLDir=      {ListUrlDir}&amp;SPSource={Source}"/>
      </CommandUIHandlers>
    </CommandUIExtension >
  </CustomAction>
</Elements>

Step 5:
Now open navigation page (App Page - default.aspx) of custom action and add below code:
<WebPartPages:AllowFraming ID="AllowFraming" runat="server"/>

All done! 
 
Now, we can deploy app in SharePoint and custom action will be created. It will open Modal Popup on click of "Demo_Modal".
 
Deployed app will looks like above Image. This is a great way to extend functionality of SharePoint.

If you have any questions you can reach out our SharePoint Consulting team here.

October 14, 2016

How to get all the Lotus Notes Documents and its metadata from a Lotus Notes Database programmatically using C#


Before understanding the code for getting the Lotus Notes Documents, we will understand the structure of the Lotus Notes Document and how to analyse the properties of a Lotus Notes Document.

Understanding the Lotus Notes Database structure:

When we open any Lotus Notes Database in Lotus Notes Client, we can see different views of the documents in left panel. In right panel, we can see the respective document items of the view selected in left panel as shown in below image.


Now, to identify the Lotus Notes Documents metadata(properties), we need to double click document in the right panel.  It will show the Lotus Notes Document body with properties like Creator/Author, Created Date, Subject as shown in below image.


The Lotus Notes Document contains many other metadata apart from the above.  To get the other metadata, we need to open the document properties by right clicking the Lotus Notes Document item in the right panel as shown in below image.

In Document Properties window, we can analyse different properties for the documents as shown in below image.


Thus, we can analyse all the metadata of the Lotus Notes Document Item.

Programmatically accessing the Lotus Notes Documents and its properties:

We will understand the code step by step following the below sequence:

Note: This will require to add reference of "Interop.Domino.dll" assembly. This assembly is also available as NuGet Package.

Get Lotus Notes Database

Below code is used to get Lotus Notes Database instance from the Database Path and Domino Server:


        //Used to Get Notes Database from the Database Path and Domino Server.
        public static NotesDatabase GetDatabase()
        {
            InitializeSession();
            if (session == null)
            {
                return null;
            }
            return session.GetDatabase(Common.DominoServer, Common.DatabasePath, false);
        }

        private static NotesSession InitializeSession()
        {
            if (session != null)
                return session;
            session = new NotesSession();
            session.Initialize(Common.ClientPassword);
            return session;
        }

Note:
  1. Common. DominoServer is Domino Server full name.
  2. Common.DatabasePath is the database path in domino server.
  3. Common.ClientPassword is the password used for Lotus Notes Client.

Get all Documents Collection from database

Below code is used to get all the documents from the database:

     //Get document collection from Lotus Notes Database
     NotesDatabase database = null;
     NotesDocument doc = null;
     database = GetDatabase();
     NotesDocumentCollection documents = database.AllDocuments;
     doc = documents.GetFirstDocument();
     while (doc != null)
     {
         // Do Your Stuff with Lotus Notes documents
         doc = documents.GetNextDocument(doc);
     }

     //If we want to get documents from specific view, below code can be used:
     //Get “All” view from the Lotus Notes Database.
     NotesView view = null;
     NotesDatabase database = null;
     NotesDocument doc = null;
     database = GetDatabase();
     view = database.GetView("All");
     doc = view.GetFirstDocument();
     while (doc != null)
     {
         // Do Your Stuff with Lotus Notes documents
         doc = view.GetNextDocument(doc);
     }

Iterate the Lotus Notes Documents one by one and get its properties

Below code is used to access each documents properties from a document collection or a view:

     //Variables used to store Metadata
     static string category = string.Empty;
     static string subject = string.Empty;
     static string immediateParentSubject = string.Empty;
     static string newsLetterSubject = string.Empty;
     static string composedDate = string.Empty;
     static string composedTime = string.Empty;
     static object[] from = null;
     static object[] Authors = null;
     static string form = string.Empty;
     static object[] proLeader = null;
     static string body = string.Empty;
     static bool hasParent = false;
     
     //Iterating each document in a view or All Document collection.
     while (doc != null) {
      docMap = new Dictionary < NotesEmbeddedObject, string > (); //used to store the attachments of Notes Documents shown in body.
      object[] items = (object[]) doc.Items; //items object used to retrieve the properties of  document like Subject,  Body, etc.
      DateTime composedDateTime = (DateTime) doc.Created;

      //Retrieving  authors of Document
      Authors = (object[]) doc.Authors;
      if (Authors != null && Authors.Length > 0) {
       Authors = Authors.Where(val => val.ToString() != "").ToArray();
       Authors = Authors.Distinct().ToArray();
      }

      //If document has any attachments or any files
      if (doc.HasEmbedded) {
       NotesRichTextItem body = (NotesRichTextItem) doc.GetFirstItem("Body");
       if (body != null) {
        foreach(object filea in body.EmbeddedObjects) {
         NotesEmbeddedObject file = (NotesEmbeddedObject) filea;
         if (file.type.ToString() == "EMBED_ATTACHMENT") {
          docMap.Add(file, file.Source);
         }
        }
       }
      }

      //Get all properties of specific document from Lotus Notes database.
      foreach(NotesItem nItem in items) {
       if (nItem.Name == "Categories") // if item is “Categories” Property
       {
        category = ((object[]) nItem.Values)[0].ToString();
       } else if (nItem.Name == "Subject") // if item is “Subject” Property
       {
        subject = ((object[]) nItem.Values)[0].ToString();
       } else if (nItem.Name == "ParentForm") // if item is “ParentForm” Property
       {
        hasParent = true;
       } else if (nItem.Name == "ImmediateParentSubject") // if item is “ImmediateParentSubject” Property
       {
        immediateParentSubject = ((object[]) nItem.Values)[0].ToString();
       } else if (nItem.Name == "NewsLetterSubject") // if item is “NewsLetterSubject” Property
       {
        newsLetterSubject = ((object[]) nItem.Values)[0].ToString();
       } else if (nItem.Name == "Form") // if item is “Form” Property
       {
        if (((object[]) nItem.Values).Length > 0)
         form = ((object[]) nItem.Values)[0].ToString();
       } else if (nItem.Name == "From") // if item is “From” Property
       {
        if ((object[]) nItem.Values != null) {
         from = (object[]) nItem.Values;
        }
       } else if (nItem.Name == "ProLeader") // if item is “ProLeader” Property
       {
        if ((object[]) nItem.Values != null) {
         proLeader = (object[]) nItem.Values;
        }
       } else if (nItem.Name == "Body") // if item is “Body” Property
       {
        if (!string.IsNullOrEmpty(nItem.Values)) {
         body = body + nItem.Values;
        }
       }
      }
     
      doc = view.GetNextDocument(doc); // or doc=documents.GetNextDocument(doc);                                
     
     }

Thus, we can add conditions for more properties in above code snippet while iterating the document to access the property value.

To summarize, the above code helps us to access Lotus Notes Database, Lotus Notes Documents and Lotus Notes Document Properties programmatically using C#.Net.

If you have any questions you can reach out our SharePoint Consulting team here.

October 6, 2016

Sharepoint 2010: Excel Services workbook larger than maximum size allowed to be opened in browser.

Issue: Recently, when I was trying to open Excel workbook from one of SharePoint document library in browser, getting this error: "This workbook is larger than the maximum workbook size allowed to be opened in the browser".


Resolution:
By default, SharePoint as out-of-the-box allows workbook size to be opened in browser is 10 MB. If we try to open it with more than 10 MB size, then will get this error.

As part of solution, we can change the workbook size setting from central administration by following below steps:

1. Login Central Admin as a Farm Administrator.
2. Click on “Application Management” in the left navigation.
3. Click on “Manage service applications” under Service Applications.
4. Click on “Excel Services Application”.
5. Click the “Trusted File Locations” link.
6. Select the Reports library or Document library where the files are (i.e. https://www.binaryrepublik.com/work)
7. Scroll down to “Workbook Properties” and change the “Maximum Workbook Size” as per requirement. (i.e. 50 MB).
8. Save the changes.
9. Now, any workbook up to 50 MB in size from the location can be opened in browser.

If you have any questions you can reach out our SharePoint Consulting team here.

Why Multiple Inheritance is not supported in C#/VB.Net?

As we know, Object oriented programming helps us to reuse common Data Members and Methods in different class with the help of Object Oriented Programming Concept called Inheritance.

In general, there are five types of inheritance –
  1. Single Inheritance
  2. Multiple Inheritance
  3. Hierarchical Inheritance
  4. Multilevel Inheritance
  5. Hybrid Inheritance

Among these, Multiple Inheritance is not supported in .Net.

What is Multiple Inheritance?
When a class acquires features from two or more base classes, it is called Multiple Inheritance.



Above diagram represents Multiple Inheritance example which is not supported in .Net. 


Let’s see now the reasons for this diamond problem – Why multiple inheritance is not supported in C#/VB.Net?

There is a possibility that Multiple Inheritance will cause ambiguity problems. It happens when two or more parent classes will have members with same identifier. Let’s understand this by an example.


In above example –

  1. Class A and Class B have same method called “Calculate(int val1, int val2)”.
  2. Class C inherits Class A & Class B. [.Net does not support this. It is shown here for example only].
  3. In Class C, we are trying to call a method from base class - “base.Calculate(10, 10)”.
  4. Now here, ambiguous situation arises. Compiler cannot identify which method to call, from Class A OR Class B.
  5. To avoid this situation, Multiple Inheritance is not supported in .Net.

So basically, Multiple Inheritance is not supported in .Net to avoid ambiguity. However, Interface is an alternate that can be used in .Net to avail Multiple Inheritance.

If you have any questions you can reach out our SharePoint Consulting team here.

October 5, 2016

Error occurred while restoring site to new tenant - 0x80070003

While restoring site collection from one farm to another using power shell command: Restore-SPSite, I am getting below error.

Error: :-  <nativehr>0x80070003</nativehr><nativestack></nativestack>.Exception.GetType().FullName, <nativehr>0x80070003</nativehr><nativestack></nativestack>.Exception.Message

Below are few possible reasons you might get this error:

1) SharePoint Version differs: Version may be lower in destination farm than source farm environment. It can be verified by Go to Central Administration --> System Settings --> Manage Servers in the farm and check version.

https://1.bp.blogspot.com/-FlaoqNYuwLE/V-PO4baHDqI/AAAAAAAAAA0/xwX8Ky-Z6yUbU0x5pRdDv0MDKr7lGjNAwCLcB/s320/blog%2Bpics.png


Resolution: Version in destination farm i.e. where we restore site collection must be same as source. Upgrade the version by installing necessary Service packs or Cumulative Updates.

2) SQL Server Version differs: SQL Instance version may differ in destination farm where we are restoring site collection, from the source farm where we have taken site collection backup.

Resolution: Install correct version of SQL Server with service pack in destination farm.

https://1.bp.blogspot.com/-eIIx3-ENerY/V-PQwvoTXUI/AAAAAAAAAA8/MWGCwfxKMIwQsSKGaxYqrDKuRny02ek8QCLcB/s400/sql%2Bserv.png


3) Memory Insufficient: In my case, both SharePoint farm and SQL Server versions were same. So, I checked SQL Server Logs through ULS log viewer and came to know that there was insufficient memory to execute queries in content database.

Resolution: Connect SQL Server by SQL Server Management Studio --> Right click and go to properties and increase Maximum Server Memory according to need.

https://4.bp.blogspot.com/-NIevkb_TAoU/V-PTKJINEEI/AAAAAAAAABM/0J71V6PkhO8HZMk65-y6OhI56D5YBCQXgCLcB/s640/3.png\



https://1.bp.blogspot.com/-upouqCG_JcQ/V-PTKFhqD_I/AAAAAAAAABI/ZemcqDy6o-wbPHz3pvUq2skECKv2ijcwQCLcB/s640/4.png


 If you have any questions you can reach out our SharePoint Consulting team here.