Tuesday, 3 February 2015

Quick deploy to Azure Cloud Service using Web Deploy for web roles

Problem :
Recently we moved our Azure Web Site application to Azure Cloud Service and after that we were facing problems with huge deployment time. It used to take around 30 mins for each deploy (here we were deploying the cloud project). This is a known issue with Cloud Service as stated here.

Solution :
We were able to solve the problem by enabling web deploy for web role and publishing web role instead of deploying the entire cloud project all over again.

Steps to implement :
1. Right click on the cloud project and select Publish.

2. On the publish window, check the option boxes for "Enable Remote Desktop for all roles" and "Enable Web Deploy for all web roles" and set up user name and password for the same.



3. Click on Publish - this will be a complete cloud project deploy as before and as per settings, this will enable Remote Desktop for all roles and Web Deploy for all web roles.

4. If it asks for certificate, allow and save the certificate for future reference.

5. After publish is done, right click on the web role project and click Publish. You can also do some test changes before that to make sure the web deploy is working.

6. You can find the settings and connections are already populated for you. Just confirm things and click on Publish.




7. This will open up pop up for entering user name and password for web deploy. Provide the user name and password you did set up while enabling web deploy.



This will deploy the web role in much lesser time than the complete cloud project deployment. Actually, the time depends on the amount of changes you are going to deploy. If the changes are less, that will take lesser time to be published. You can also take advantage of file publish options for enabling pre-compilation Etc. 

Tuesday, 13 January 2015

Precompiling ASP.NET MVC views in Azure Cloud Service - RazorGenerator

Problem -

Recently, we moved our application from Azure Website to Cloud Service. In website, we were using pre-compilation as that gives a significant performance improvement. When we moved to cloud service and wanted to use pre-compilation, we found that this is not as easy as it was for website. For websites, we are having option in Visual Studio (a check box that you can check) to enable pre-compilation, but, Visual Studio does not provide any such option.

Solution -

One very easy and effective solution for this is to use RazorGenerator – a visual studio extension and a Nuget package (you need both).

Steps to implement -

Below are the steps to implement RazorGenerator for your ASP.NET MVC application -
  1. Install RazorGenerator from Visual Studio extension gallery.
  2. Install package RazorGenerator.mvc from Nuget package to your class library.
  3. Go to view > properties (you can get this by right clicking on the view file in solution explorer or pressing Alt + Enter).
  4. Set Custom Tool to RazorGenerator (you need to do the same for all existing views those you want to be precompiled).
  5. Save the property and you are done.



How this works -

When you set Custom tool to RazorGenerator, this will create a precompiled .cs file named [yourViewName].generated.cs, and the .cs file will be used when the application is running.





Sunday, 16 November 2014

Parallel processing with C# - Working with Task factory

While we were working on performance improvement of our project, we found that one foreach loop is taking long time to execute and hence, decreasing the performance rapidly. The code looked like something following - 
 
                    if (!String.IsNullOrWhiteSpace(lstScreenIds))
                    {
                        // Create business class object
                        BLVisitList objVisitList = new BLVisitList();
 
                        // Loop through each Screen and call DoPrevInfo
                        var screenIds = lstScreenIds.Split(',').ToList();
                        
                        foreach (var screenId in screenIds)
                        {
                            objVisitList.DoPrevInfo(ActualUserId, PatientId, ActualRoleId, visitId, screenId, IpAddress);
                        }
                    }
 
Here, lstScreenIds is a comma-separated list of some screen-ids and DoPrevInfo was supposed to be called for each screen id in the list.
 
DoPrevInfo is doing some big Inserts and Updates in DB and hence, if the number of screen ids is more (generally we had some 20-25 screen ids), it was taking huge time to execute and complete the operation. It was taking almost 50 seconds to complete the operation
 
This 50 seconds is the sum of the times taken by the method for all the screen ids. Say, for screenId 'A', the method takes 10 seconds to execute, for 'B' it takes 15 seconds and for 'C' it takes 25 seconds - as the method is called for one screenId only after it completes the execution for the previous one (in serial way), so, the total time taken is (10 + 15 + 25) = 50 seconds.
 
To fix this, we used parallel processing approach as I am describing below. We changed the code to use tasks - 
 
 
                    if (!String.IsNullOrWhiteSpace(lstScreenIds))
                    {
                        BLVisitList objVisitList = new BLVisitList();
 
                        //Loop through each Screen and Call the DoPrevInfo Function
                        var screenIds = lstScreenIds.Split(',').ToList();
 
                        // This line creates a list of tasks that we will be using in future
                        List<Task> tasks = new List<Task>();
 
                        // Saving the current context
                        var current = HttpContext.Current;
 
                        foreach (var screenId in screenIds)
                        {
                            // Starting a new task for each screenId to make it execute parallely
                            tasks.Add(Task.Factory.StartNew(() =>
                            {
                                // Setting current context
                                HttpContext.Current = current;
 
                                // Call the method
                                objVisitList.DoPrevInfo(ActualUserId, PatientId, ActualRoleId, visitId, screenId, IpAddress);
                            }));
 
                        }
                        
                        // Wait until all the tasks are over, then leave the code block.
                        Task.WaitAll(tasks.ToArray());
                    }
 
With this change, we made the foreach loop to use separate tasks for separate screen id and go on parallel way - at the same time. So, the time taken now is the longest time that is taken by the method for individual screenIds.
 
To explain, from our above example, now the complete process will take 25 seconds (that is the maximum time among 'A'/'B'/'C' the method takes to complete execution) - given that, the execution for the other screen ids (10 seconds and 15 seconds respectively) will be completed within that maximum time span!
 
This approach made our code to execute only in 9 seconds from 50 seconds (Obviously that is not 'only' if you are concerned on performance, I am saying from the old time-taken reference :) ) without touching/changing/optimizing the DoPrevInfo method or any DB query/stroed-procedure - This is only due to this tasking.
 
Please refer to the comments to understand what the code is doing. I will still explain some code and why we needed these.
 
1. Inside DoPrevInfo method, we were accessing HttpContext.Current object, but after the task implementation, we found that we are not getting the HttpContext.Current object value being inside tasks. So, there we need to set the HttpContext.Current object value everytime we enter a task.
 
var current = HttpContext.Current; - This line fetches the Current object value being outside the task and after that, we are setting the value by 
HttpContext.Current = current; inside the task. This works fine :)
 
2. Task.WaitAll(tasks.ToArray()); - This line makes the program control to wait for all the tasks to complete before leaving the code block - Otherwise, the control leaves the code block after the first task is completed.

StartDate-EndDate validation with Kendo datepicker and MVC

 If we have two DatePicker controls for StartDate and EndDate and we are writing long validation methods to check if user has given start date greater than end date etc., we can try something else - We can restrict user to select wrong dates.
 
To explain, if user has selected StartDate as 1st Jan 2014, then the EndDate control should populate dates starting from 1st Jan 2014 and not the previous dates.
 
On the other hand, if user selects EndDate first as say 10th Jan 2014, then StartDate should have a maximum selectable date as 10th Jan 2014 and not the dates after that. 
 
Restricting user to select wrong dates at the time of input is obviously better than checking after user clicks a button and expects some output. This improves user experience.
 
This is how we can implement this using KendoUI and MVC - 
 
<label for="start"> Start Date </label>
@(Html.Kendo().DatePicker()
    .Name("start")
    .Events(e => e.Change("StartDateChanged"))
)

<label for="end"> End Date </label>
@(Html.Kendo().DatePicker()
    .Name("end")
    .Events(e => e.Change("EndDateChanged"))
)

<script type="text/javascript">
    
    function StartDateChanged() {
        var startDate = this.value();
        var endPicker = $("#end").data("kendoDatePicker");
        
        if (startDate) {
            startDate = new Date(startDate);
            startDate.setDate(startDate.getDate());
            endPicker.min(startDate);
        }
        else {
                
        }
    }

    function EndDateChanged() {
        var endDate = this.value();
        var startPicker = $("#start").data("kendoDatePicker");

        if (endDate) {
            endDate = new Date(endDate);
            endDate.setDate(endDate.getDate());
            startPicker.max(endDate);
        }
    }
</script>
 
It will show only the valid Dates to user and user can select from there only.

Adding custom button to Kendo editor control

We can customize Kendo editor control with our own custom buttons. Like, say, in any place we are using the kendo editor control and we need to use the horizontal line separation between two Paragraphs. In that case, we will be using the horizontal line very frequently and this is better to add a custom button for drawing the horizontal line.
 
Here is an example how we can one custom button to the Kendo editor control - 
 
@(Html.Kendo().Editor()
    .Name("editor")
      .Tools(tool => tool.CustomButton(cb => cb.Name("custom")
                                               .ToolTip("Draw horizontal line")
                                               .Exec(@<text>
                                                          function() {
                                                            var editor = $(this).data("kendoEditor");
                                                            editor.exec("inserthtml", { value : "<hr />" })
                                                          } 
                                                    </text>))
        )
)
 
The custom button will be displayed in the tool box and we can simply click that to get our work done quickly.
 
We can add tooltip as well to the button. Like, in the upper example, the button will show a tooltip - "Draw horizontal line" to express what the button does.

Thursday, 16 October 2014

Re-sizing images with Image Resizer in .NET

Image Resizer is a Nuget package that allows resizing images in .NET in a very simple and efficient way. Hereby I am describing steps to use ImageResizer.
 
 1. Install ImageResizer from NuGet. Either search in the NuGet or run the following command in Visual Studio Package Manager Console - 
     PM > Install-Package ImageResizer
 
 2. Describe your resize settings as follows - 
 
 var imgSettings = new ResizeSettings {
    MaxWidth = maxWidthYouWant, // Can be any integer
    MaxHeight = maxHeightYouWant, // Can be any integer
    Format = formatOfYourChoice // Example - "jpg"
 };
 
// Apply resize settings to the image
// inputStream represents the original image (as FileStream/MemoryStream)
// outputStream represents the output stream after resizing
ImageBuilder.Current.Build(inputStream, outputStream, imgSettings);
 
var resized = outputStream.ToArray(); // Represents byte array of the image after resizing
 
Image resizing maynot be simpler than this and that also without performance overhead. And there are some more super cool features you can get here.

Deploying to Microsoft Azure Web Site from GIT

Microsoft Azure supports direct deployment from GIT. That is very much helpful if we have to publish our codes on a regular basis or multiple times a day.

 Following are the steps to set up the Azure deployment from source control - 
 
 1. Here I will assume you are already having a local GIT repository, if not, then get GIT and create one repository and put your source code in that.

 2. Login to Azure Portal.
 
 3. Select the web site for which you want to activate deployment.
 
 4. Goto DASHBOARD Tab.
 
 5. On quick glance section ( right side of the page ) select Set up deployment from source control - this will open up SET UP DEPLOYMENT dialog.
 
 6. Create your user name and password.
 
 7. Copy generated GIT URL.
 
 8. Open Git Bash.
 
 9. Change directory to GIT repository root.
 
 10. Run command - git remote add azure generatedGITUrl. So, for example, if the generated GIT Url ( from point #7 ) is say "xxx@yyy.scm.azurewebsites.net:445/therepository.git", then the command will be as follows - 
git remote add azure xxx@yyy.scm.azurewebsites.net:445/therepository.git
 
 11. For deploying local GIT repository content, run command -  git push azure master
 
 And that is all, every time you want a deploy, you just need to run the command of Point #11, and you are done. Easy and simple steps to make our life easy and in a better way.