Monday, July 14, 2014

Generate a Zip file at run time from Azure Blob Storage

Generate a Zip file at run time from Azure Blob Storage


Introduction
Many a times we provide options to Update/download/upload file in applications. These files can be located at physical servers or on Azure at some blob storage. When the files are on Azure and you need to download multiple files, it would always be a good approach to
·         download the stream of these files
·         zip them
·         download the zip format containing all files

Solution

There are several solutions to this. One solution I am going to explain is using the SharpZipLib dll.
Referring the definition from SharpZipLib site “#ziplib (SharpZipLib, formerly NZipLib) is a Zip, GZip, Tar and BZip2 library written entirely in C# for the .NET platform. It is implemented as an assembly (installable in the GAC), and thus can easily be incorporated into other projects (in any .NET language)…..Read more
You can embed this library in to the solution by performing following steps:
1.       Right click the solution where you will write the code for zipping the files.
2.       Click Manage Package
3.       Find the shaprziplib dll in search text and then click Install.
Another way to add the library to your solution is running the following command in the Package Manager Console. The steps to use the Package Manager Console are described here.
Once you added the SharpZipLib dll reference to your solution, follow below steps for code to download and zip files:
Add the using statement in the class where you are adding the DownloadAll Code

using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;

Add below using statement for Azure
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;




Then add following method

public void DownnloadStreamToZip(List<string> files, string BlobContainer)
        {
            CloudStorageAccount storageAcc;
            storageAcc = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["AzureConnection"].ConnectionString);
            var storageHelper = new AzureStorageHelper();
            using (var zOutStream = new ZipOutputStream(Response.OutputStream))
            {
                zOutStream.SetLevel(0);
                Response.BufferOutput = false;
                Response.AppendHeader("content-disposition", "attachment; filename=AllFiles"".zip");
                Response.ContentType = "application/octet-stream";

                foreach (var file in files)
                {
                    var entry = new ZipEntry(file)
                    {
                        DateTime = DateTime.Now,
                    };
                    zOutStream.PutNextEntry(entry);
                    storageHelper.ReadToStream(BlobContainer, file, zOutStream);

                    Response.Flush();
                    if (!Response.IsClientConnected)
                    {
                        break;
                    }
                }
                zOutStream.Finish();
                zOutStream.Close();
            }
            Response.End();
        }


Call the DownnloadStreamToZip method from the event you want to trigger the Download All action, the method will download all the files from the specified BlobContainer.

Happy Coding!

Tuesday, June 17, 2014

SharePoint List Event Handler Types and Working with AfterProperties and BeforeProperties


Scenario:  I was having the requirement to execute my custom code when a SharePoint ListItem is updated.  This custom code should write some of the updated field values to database. My custom list consists of following fields:

TaskID, Task Name, Project Name,  Task Type, Cost, Work,  Reason For Change, Impact

When any listitem is updated, I need to check if the fields  Reason For Change or Impact have been changed. If these fields are changed then I need to update these field values in database also with my custom code.

Solution:
The List Event Handlers provide BeforeProperties and AfterProperties collection which should enable to compare original and edited field values and make decision when to execute the custom code.  If we do not compare the original and edited field values then the custom code will be executed every time the item is updated.

Before talking about the Properties, let me give a brief about type of Event Handlers. SharePoint 2010 offers 2 types of Event Handlers which we can attach to List, Libraries, etc. These are Synchronous and Asynchronous. The differences between these Event Handlers are:

Asynchronous
Synchronous
Executes after event is executed, these event handler methods end with ‘–ed’. For example ItemAdded, ItemUpdated, ItemDeleted
Executes before event occurs, these event handler methods end with ‘–ing’. For example ItemAdding, ItemUpdating, ItemDeleting
These event handlers are used when certain code is required to be executed after event occurs. These event handlers cannot stop/cancel the event execution.
These event handlers are mostly used when the execution of event is based on some condition. We can write the code to execute the event only when certain condition is true else we can stop the event execution.

 In the above case, as execution of custom code was based upon comparison of field values so I am running my code under the ItemUpdating event handler method.
 
 
values then the custom code will be executed every time the item is updated.
Before talking about the Properties, let me give a brief about type of Event Handlers. SharePoint 2010 offers 2 types of Event Handlers which we can attach to List, Libraries, etc. These are Synchronous and Asynchronous. The differences between these Event Handlers are:
Asynchronous
Synchronous
Executes after event is executed, these event handler methods end with ‘–ed’. For example ItemAdded, ItemUpdated, ItemDeleted
Executes before event occurs, these event handler methods end with ‘–ing’. For example ItemAdding, ItemUpdating, ItemDeleting
These event handlers are used when certain code is required to be executed after event occurs. These event handlers cannot stop/cancel the event execution.
These event handlers are mostly used when the execution of event is based on some condition. We can write the code to execute the event only when certain condition is true else we can stop the event execution.
 
In the above case, as execution of custom code was based upon comparison of field values so I am running my code under the ItemUpdating event handler method.
Now, the event handler method provides the SPItemEventProperties properties object which provides three ways to access the field values:
-          properties.ListItem[FieldName]
-          properties.AfterProperties
-          properties.BeforeProperties
The link Working with BeforeProperties and AfterProperties on SPItemEventReceiver  describes very well when above 3 returns null and when they return values. The summary is as following
Here are the results for a list:
List
BeforeProperties
AfterProperties
properties.ListItem
ItemAdding
No value
New value
Null
ItemAdded
No value
New value
New value
ItemUpdating
No value
Changed value
Original value
ItemUpdated
No value
Changed value
Changed value
ItemDeleting
No value
No value
Original value
ItemDeleted
No value
No value
Null
Here is the same test against a document library:
Library
BeforeProperties
AfterProperties
properties.ListItem
ItemAdding
No value
No value
Null
Now, the event handler method provides the SPItemEventProperties properties object which provides three ways to access the field values:
-          properties.ListItem[FieldName]
-          properties.AfterProperties
-          properties.BeforeProperties
The link Working with BeforeProperties and AfterProperties on SPItemEventReceiver  describes very well when above 3 returns null and when they return values. The summary is as following
Here are the results for a list:
List
BeforeProperties
AfterProperties
properties.ListItem
ItemAdding
No value
New value
Null
ItemAdded
No value
New value
New value
ItemUpdating
No value
Changed value
Original value
ItemUpdated
No value
Changed value
Changed value
ItemDeleting
No value
No value
Original value
ItemDeleted
No value
No value
Null
Here is the same test against a document library:
Library
BeforeProperties
AfterProperties
properties.ListItem
ItemAdding
No value
No value
Null
ItemAdded
No value
No value
New value
ItemUpdating
Original value
Changed value
Original value
ItemUpdated
Original value
Changed value
Changed value
ItemDeleting
No value
No value
Original value
ItemDeleted
No value
No value
Null
 
But while accessing the BeforeProperties and AfterProperties, you cant access them directly as shown in the following code
 
if (properties.ListItem["FieldName"] != properties.AfterProperties["FieldName"])
{
    properties.Cancel = true;
    properties.ErrorMessage = "This column cannot be changed";
}
The above code works fine when the internal name of the column is same as display name. If the field display name has space, for example:  If FieldName =  ‘Reason For Change’ then the internal name will be ‘Reason_x0020_For_x0020_Change’ and in suchcase the above code will fail.
So It’s always better to use the Internal FieldName by default  while working with AfterProperties and BeforeProperties. You can use any of following was to access the value
properties.AfterProperties["Reason_x0020_For_x0020_Change"].ToString();
or
foreach (DictionaryEntry entry in properties.AfterProperties)
               {
                   if (entry.Key.Equals(["Reason_x0020_For_x0020_Change"))
                       editedReasonForChange = entry.Value.ToString();
               }
 
So my code for comparison looks like as following:
 
 
/// <summary>
       /// An item is being updated.
       /// </summary>
     public override void ItemUpdating(SPItemEventProperties properties)
     {
       base.ItemUpdating(properties);
       string originalReasonForChange = string.Empty;
       string originalImpact = string.Empty;
       string editedReasonForChange = string.Empty;
       string editedImpact = string.Empty;
       originalReasonForChange = properties.ListItem[(["Reason_ For _Change"].ToString();
       originalImpact = properties.ListItem["Impact"].ToString();
       editedReasonForChange =    properties.AfterProperties[(["Reason_x0020_For_x0020_Change"].ToString();
       editedImpact = properties.AfterProperties[["Impact"].ToString();
//Execute the code only following 2 fields value is changed
       if (editedImpact.ToLower() != originalImpact.ToLower() ||                                 editedReasonForChange.ToLower() != originalReasonForChange.ToLower())
 
       SaveUpdatesToDB(editedImpact, editedReasonForChange, properties.ListItem[SnapItConstants.ChangeReportListFields.TASK_GUID].ToString(), properties.ListTitle);
           }
       }
 
 
 
Happy Coding!!