Saturday, March 26, 2016

Limit Telerik's date and time pickers to working days and hours

Recently I was asked if we can limit date and time selection to working days and hours only. So I was hoping Telerik Rad Calendar simply allows to disable weekend days, and was looking for something like that:

dpDeliveryDate.Calendar.DisableWeekendDays = true;

However, there is no such feature in Rad Calendar. Instead, there is a much more generic feature called Special Days, which allows to control weekends, holidays, birthdays or any other special day.
Here is the code required to disable all Saturdays from now on:

            var day = new Telerik.Web.UI.RadCalendarDay();
            day.Repeatable = Telerik.Web.UI.Calendar.RecurringEvents.Week;
            day.IsDisabled = true;
            day.IsSelectable = false;
            var date = DateTime.Today.AddDays(DayOfWeek.Saturday - DateTime.Today.DayOfWeek);
            day.Date = date;
            dpDeliveryDate.Calendar.SpecialDays.Add(day);

As a Special Day is based on a specific date, this code does a little trick in order to get the date of the next Saturday. The code can be reused in order to disable the selection of Sundays as well. So this can be the final code:

        private void DisableDayOfWeekInCalendar(DayOfWeek dayOfWeek)
        {
            var day = new Telerik.Web.UI.RadCalendarDay();
            day.Repeatable = Telerik.Web.UI.Calendar.RecurringEvents.Week;
            day.IsDisabled = true;
            day.IsSelectable = false;
            var date = DateTime.Today.AddDays(dayOfWeek - DateTime.Today.DayOfWeek);
            day.Date = date;
            dpDeliveryDate.Calendar.SpecialDays.Add(day);
        }

         DisableDayOfWeekInCalendar(DayOfWeek.Saturday);
         DisableDayOfWeekInCalendar(DayOfWeek.Sunday);

This code is not enough if you want to deal with different cultures, which may have their weekend on other days of the week. This issue can be solved by getting user input. You could think that using the value

Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek

would solve this issue, but this value refers to the first day of the week in a calendar, not the first business day. For most cultures it would actually work, but not for en-US. So if this issue is relevant, user input is probably the best way to go.

Finally, limiting the time picker to working hours is very simple:

            radTimeDefaultValue.TimeView.StartTime = new TimeSpan(9, 0, 0);
            radTimeDefaultValue.TimeView.EndTime = new TimeSpan(17, 0, 0);

Working hours can also vary, and again, user input is probably the right way to handle it.

Saturday, February 20, 2016

Great usage of Themes with Telerik controls

Telerik controls allow us to focus on the core of our features and deliver them faster. However, Telerik controls' rendering was not easy for skinning and not very responsive. But Telerik has improved it lately using a new property called Render Mode. Setting this property allow us to get a different rendering for the controls, which is more light weight and responsive. For example, here you can see the rendering difference for Rad Calendar.

This is a really cool feature, but I wouldn't want to just go ahead and apply it, for two reasons. The first most obvious reason, is that it is a lot of work to go over all the controls. It ain't fun at all. The second reason is much more crucial. We have hundreds of happy customers who have their own skins which might break with the change in rendering.

Asp.Net Themes come to the rescue by offering a very simple solution to both these problems. We can set this property in the .skin file the following way:
<rad:RadCalendar SkinID="RadCalendar_SkinID" Skin="Default" runat="server" RenderMode="Auto" />
By doing so, we applied the new property for all Rad Calendar controls in our application, and we did it on the skin level, without affecting other skins. Once this property is set, the HTML rendering of this control is changed for this skin only, so CSS changes which might be required, can also be applied on this skin only.

We saw how the Render Mode property allows us to improve the rendered HTML, and using Themes allows us to do it easily and without breaking any working skin. We can now easily create much more responsive skins without worrying about backwards compatibility.

Thursday, February 21, 2013

When the new keyword met reflection

The New Keyword

Consider the following code:

    public class BaseClass
    {
        public int? TheProperty { get; set; }
    }

    public class DerivedClass : BaseClass
    {
        public new int TheProperty
        {
            get { return base.TheProperty ?? 0; }
            set { base.TheProperty = value; }
        }
    }

The new keyword is used in order to hide a property or method of the base class. It can be used in order to give another implementation for the property even if the property is not defined as virtual in the base class. As it hides the property of the base class it can even have a different type. In this example, the property of the base class is of type int? while the property of the derived class is of type int.
In the following code the property of the base class is called:

            BaseClass instance = new DerivedClass();
            instance.TheProperty = null;

While in the following code the property of the derived class is called:

            DerivedClass instance = new DerivedClass();
            instance.TheProperty = 5;

The Problem

The following method is using reflection in order to get the value of a property:

        public static object GetPropertyValue(object obj, string propertyName)
        {
            System.Reflection.PropertyInfo propertyInfo = obj.GetType().GetProperty(propertyName);
            object value = propertyInfo.GetValue(obj, null);
            return value;
        }

This method generally works fine, but when obj is an instance of DerivedClass (and propertyName is "TheProperty"), the first line of the method will throw the following exception: "Ambiguous match found.". That is because the DerivedClass does not have a single property called TheProperty, but rather two different properties of different types by that name.

Possible Solutions

First we should consider dropping the new keyword. Hiding a property is not an obvious thing to do, so first I would review why hiding was used in the first place. As we seen in this post hiding can be a little confusing so I think it should be considered carefully.

If we do decide to keep hiding the property, we can modify the GetPropertyValue method to support it by using the following code:
        
        public static object GetPropertyValue(object obj, string propertyName)
        {
            System.Reflection.PropertyInfo propertyInfo = 
                obj.GetType().GetProperties().FirstOrDefault(prop => prop.Name == propertyName);
            object value = propertyInfo.GetValue(obj, null);
            return value;
        }

If you are looking specifically for any one of the properties you can update the predicate used by FirstOrDefault to consider DeclaringType (for example, prop.DeclaringType == typeof(DerivedClass)) or PropertyType (for example, prop.PropertyType == typeof(int?)).

In our case we decided to modify the GetPropertyValue as it is part of our infrastructure, and we decided we would rather have our infrastructure support such cases.

Saturday, January 12, 2013

The Session Story

Prologue

Programming in ASP.NET we use the Session object in order to keep user information on the server while the user is working with the application. That way you can easily access that information when the server is working and require that information. Usually we use the session on the main ASP.NET thread. What would happen if you use the session in another thread? Can you update the session while on another thread? So here is the story.

The Feature

We developed a very cool feature which enables users to upload their PDF files, and then view and manipulate them before completing an order for printing the composite document. When a user uploads a file we have to analyse it and turn its pages into images (in order to display them in the browser). This processing takes time. The user will have to wait, but we do not want the web server to wait, taking over application pool threads, but rather do this processing in separate threads.

The Problem

When the processing of a file completes we need to update the session object with the newly uploaded file and its properties, so we could handle the order on the server side. At first, we did this update on the same thread that did the processing. When we use In Proc session state mode it worked well, but when we use SQL Server session state mode (required for clustering), the session will not update.

Why?

We wondered why does it work that way. At first it felt very strange and we said it's probably some bug. But we also felt that it may be that we are misusing the session, so we did some more research and thinking, and this is what we came up with.
In Proc session state mode simply keeps the session in memory. When we update the session from one thread and then read it from the main thread, they both access the same place in memory, so it works.
SQL Server session state mode needs to serialize the session to the database in order to save it, and deserialize it in order to read it. Deserialization occurs when a request hits the server, and serialization occurs when the request ends and the response goes to the client.
When updating the session in another thread, it happens after the request ends, and it also occurs after the session was serialized and saved in the database, so this explains why it cannot work that way.
Doing some further reading, I found out that the session was designed to work only in the scope of a request, so also in the case of using only In Proc session state mode, updating the session from another thread after the request is over is an abuse and breaks the session design.

The Solution

We decided to simply change our design a bit, so the request to upload a file, which triggers its processing and should have saved it to the session, will not do the saving. Instead, as the client waits for processing to end by asking the server whether processing is over, when the server finds out processing is done, it saves the file information to the session, and returns the correct response to the client. That's easy to implement and easy to understand.

Epilogue

So far I was only telling stories on this blog. I hope to put some code into my next post, so keep on following!

Saturday, October 27, 2012

Let's start from the beginning!

Goodbye Cvs Hello Git

Prologue

So I finally started writing my own blog! How exciting!

I was thinking what should be my first post about?! I can write on some technical problem and its solution, but that would probably be the subject of most of my posts. My first post should be something a bit different.

The most important tool that every team of developers should use is a source code management system. It enables the team to work together on the same files of code, to keep track of code changes, and be able to get one final version of all the code together, which will be compiled to the final product release. As my team recently went through a change, I think this is a good subject to begin with.


Why not Cvs?

Until a few months ago we were using Cvs. Cvs in a centralized version control system, keeping its repository on one server, and all of the developers are checking files in and out of that repository. I always used to find working with Cvs frustrating.
Cvs is generally slow, depending also on the quality of the server on which it is installed. Whenever I had to get the latest version from the server was always a good time to go and make myself some coffee...
We also used to have some strange problems from time to time. Sometimes code that we were thinking that was checked in was not really checked in, sometimes you knew that there is a newer version on the server, but the system insisted you had the latest version.
But the most significant disadvantage of Cvs is the lack of atomic check in. What does it mean? Let's say I fixed a bug, and I made changes to 3 different files. I would like to check them all at once, with a comment "bug number X was fixed". Then I will always be able to track this bug, and if I am asked to fix this bug for a hot fix or a minor version release I will be able to easily find all the relevant changes related to this bug. So using Cvs we used to answer such requests with "No", "We can't", "Impossible".


Why I think Git is better

So lately we started using Git, and it is so much fun working with it, that I even started using it at home for my weekend projects!
Git is a distributed version control system, which means that there can be more than just one repository. We have one central repository and a repository for each developer. At home I have a repository on my own computer and a remote repository at Bitbucket.org. It is good even if you have just one repository, then you do not have backup, but you still keep history of your code and can go back to each previous version that you like.
In my opinion, the advantages of using Git over Cvs are:
1. It does not mark files as read only, so you can just go ahead and edit them with no need for check out, which takes a few moments. It is much more fun working that way.
2. You are not dependent on the central repository when you code, so you can keep working and commit files even when the central repository or the network are down.
3. It handles much better deletion or renaming of files.
4. It handles conflicts much better.
5. It is much faster.
6. It has the atomic commit.
7. It also has a cherry pick option. This option allows you to select an atomic commit and apply it on another branch! So if you solved a bug for the next release, and you now want to create a hot fix for the previous release, it can be done very easily.
8. It is much easier to create new branches. In fact, many Git users recommend branching as much as you can.You can create a branch for each feature and merge it to the other branch when it is done.
9. I simply feel that it is more reliable, easier to work with and more fun.


Changing your perception

As far as I understood, Git does not manage files, but instead it manages change sets (each atomic commit is a change set), and by doing that it gets some of its advantages.
So far what we found annoying is the way of synchronizing between our own repository and the remote (central) repository. This is done by Pull (get code from the central repository) and Push (put code to the central repository). You must pull before you can push and you should not have any changes in your working directory when pulling. For anyone who used to work with Cvs this may be a little annoying.

However, when moving from Cvs to Git you should probably change your perception. As you have your own repository you may not sync with the remote repository as often as before. You can also create more branches and then pulling and pushing becomes easier as it is just for a smaller branch having less changes.
On the other hand, our CI (Continuous Integration) machine is based on the remote repository, so frequently pushing to the remote repository is good from that point of view.
Eventually, I guess it's all about finding the right balance , choosing what is best for you, and constantly looking for ways to improve.

Some installation and usage tips

Git comes from the Linux world and is typically used with a command prompt. For us as .Net developers this may be uncomfortable, so we use Git Extensions which has all the every day functionality you need. We already had the chance to use some more advanced commands using the command prompt, but these cases are rare.

The remote (central) repository is installed on a server to which access is very limited, in order to avoid damage to that repository, whether it is by accident or by intention. The access to the remote repository is done over HTTP using WebGit.NET, but there are also other such projects available, there is some more information about them here: http://stackoverflow.com/questions/438163/whats-the-best-web-interface-for-git-repositories.