How to create Scheduled Jobs in .net web applications.

30 08 2008

How to create Scheduled Jobs in .net web applications.

Calling a function at predefined iteration of time has been one of the key requirements of web applications.
Example:
You want to automatically archive the data.
You want to automatically purge the data.
You want to automatically send the News Letters.
You want to take backup of the files or database etc.

Generally this type of functionality can be easily archived by creating and configuring scheduled jobs in SQL Server.

What if you are using the express edition of SQL Server?
You cannot take advantage of this feature because all the editions of SQL Server do not provide this functionality.

In this article I will explain how we can achieve this functionality using purely .Net framework class.

First of all let’s thanks System.Threading class. The main cream lies inside this class shipped in .Net Framework. Many of us usually do not use it but believe me its one of the most beautiful classes of the framework.

Anyways

Following are the steps which you need to perform:

Step 1) Create a class called Jobs.cs


namespace myScheduler
{
    public sealed class Jobs
    {
        public Jobs(){}

        public static void DailyJob(object state)
        {
           //Your dream goes here.
        }

        public static void HourlyJob(object state)
        {
            //Your dream goes here.
        }
    }
}

Jobs class includes the below two functions that will be called by our scheduler which we will create in the second step.
I have created two functions for this purpose.
DailyJob: Will be called daily by the scheduler.
HourlyJob: Will be called hourly by the scheduler.

 

Step 2) Create a class called Scheduler.cs


using System;
using System.Threading;

namespace myScheduler
{
    public sealed class Scheduler
    {
        public Scheduler() { }

        public void Scheduler_Start()
        {
            TimerCallback callbackDaily = new TimerCallback(Jobs.DailyJob);
            Timer dailyTimer = new Timer(callbackDaily, null, TimeSpan.Zero, TimeSpan.FromHours(24.0));

            TimerCallback callbackHourly = new TimerCallback(Jobs.HourlyJob);
            Timer hourlyTimer = new Timer(callbackHourly, null, TimeSpan.Zero, TimeSpan.FromHours(1.0));
        }
    }
}

Scheduler class contains the actual mechanism for running jobs created in Jobs class in Step one.

Timer: Mechanism for executing method at specified time intervals. This method has 5 overloads which we can use as per our needs. Some of its parameters are
TimerCallback: Represents the method that you want to actually callback on at a particular interval of time.
State: Any type of object you want to pass to your callback method.
Due Time: Amount of delay after which callback will be invoked. TimeSpan.Zero means immediately.
Period: Time period between invocations of callback function.

 

Step 3) Add Global.asax file to your web project. In Application_Start event instantiate Scheduler object and make a call to Scheduler_Start() method.


<%@ Application Language="C#" %>
<%@ Import Namespace="myScheduler" %>

<script RunAt="server">

    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
        Scheduler objmyScheduler = new Scheduler();
        objmyScheduler.Scheduler_Start();
    }

    void Application_End(object sender, EventArgs e)
    {
        //  Code that runs on application shutdown
    }

    void Application_Error(object sender, EventArgs e)
    {
        // Code that runs when an unhandled error occurs
    }

    void Session_Start(object sender, EventArgs e)
    {
        // Code that runs when a new session is started
    }

    void Session_End(object sender, EventArgs e)
    {
        // Code that runs when a session ends.
        // Note: The Session_End event is raised only when the sessionstate mode
        // is set to InProc in the Web.config file. If session mode is set to StateServer
        // or SQLServer, the event is not raised.

    }
      
</script>

 

You are done.

How it works?
Whenever the applications is first started the  Application_Start() in Global.asax is called and this calls Scheduler_Start() method which configures all the Jobs that we have created.

I have demonstrated a daily and hourly job in the above examples. In order to debug and test this code you need to wait for an Hour or a Day. Don’t panic I have done this intentionally. So in order to brush up your above learning’s prepare a job in Jobs.cs file that would be called every minute. Configure the callback and timer for your new job in Scheduler.cs file and enjoy the gist of scheduling.

Note: After running the project once do not forget to restart the IIS because Application_Start() wont be called every time you run your project. You know why?





How to Encrypt or Decrypt sections of Configuration file.

15 08 2008

How to Encrypt or Decrypt sections of Configuration file.

It is always a good practice to protect sensitive information in configuration files. One should always protect connectionStrings section from being easily readable; also some times it becomes necessary to encrypt appSettings section that may include some sensitive data. You know why…?

So in this Blog I will walkthrough the steps required for encryption\decryption of sections in configuration file.

.Net framework ships two providers for this purpose.
RsaProtectedConfigurationProvider and DpapiProtectedConfigurationProvider.
Here I will use RsaProtectedConfigurationProvider.

 
Step 1) First off all we will add provider to configuration section of web.config file that you want to play with. This provider is required for actual processing done while running commands depicted in step 3 and 4.


<configuration>
<configProtectedData defaultProvider="myProvider">
<providers>
 <clear/>
  <add name="myProvider"
  type="System.Configuration.RsaProtectedConfigurationProvider"
  keyContainerName="NetFrameworkConfigurationKey"/>
</providers>
</configProtectedData>
</configuration>

 RsaProtectedConfigurationProvider requires key container for encryption and decryption purpose. This container includes private\public keys that are required during encryption and decryption process by the attached provider.

NetFrameworkConfigurationKey : This is the default key container shipped by Microsoft. You can also create your own key container that includes private\public keys required for encryption\decryption. In order to avoid confusion I will depict these steps in my next article.

Note: As we are using default key container “NetFrameworkConfigurationKey” you can do away with the first step. This step will be added by machine.config file cause it includes declaration for both providers  (“RsaProtectedConfigurationProvider” and “DpapiProtectedConfigurationProvider”). But this will be helpful incase we are creating our own key container.

Step 2) After adding the provider in Step 1 go to the Visual Studio command prompt. Now In order to access “NetFrameworkConfigurationKey” key container your “ASPNET” account must have permission to access it. Run the below command to give access.

aspnet_regiis -pa “NetFrameworkConfigurationKey” “ASPNET”

 

Step 3) Run below command to encrypt connectionStrings section of your web.config file located in the virtual directory named “MyWebApplication”.

aspnet_regiis -pe connectionStrings -app /MyWebApplication

 

Step 4) Run below command to decrypt connectionStrings section of your web.config file located in the virtual directory named “MyWebApplication”.

aspnet_regiis -pd connectionStrings -app /MyWebApplication

Note: You can replace the “connectionStrings” section with the section name you want to encrypt\decrypt.
Eg: aspnet_regiis -pe appSettings -app /MyWebApplication
This will encrypt “appSettings” section of your web.config file located in the virtual directory named “MyWebApplication”.

To get more help about aspnet_regiis use the below command
aspnet_regiis help





Creating Custom Controls in ASP .Net

20 07 2008

Creating Custom Controls in ASP .Net

In this article I have simply demonstrated 2 code examples for creating Custom Web Controls.

Why Custom Controls?
To cater through the real world scenarios that may not be supplemented by inbuilt .Net controls, the need for Custom Control arises. Also their are several other reasons for creating custom control like reusability, centralized management over the control, ease of usage etc.

How to approach the requirement for creating Custom Controls?
If any of the inbuilt .Net control meets your requirement than you should always use these controls. If not than ask yourself a question

Would any of the existing control help me?

If yes than
Inherit from the existing control and add the new features to it and extend it further.
If No than
You need to build the control from scratch. In this case inherit from WebControl class.

 

How to create Custom Controls?

Their are two ways in which you can create a custom control.
1) You can inherit from existing .net web control to extend its features further. OR
2) You can directly inherit from WebControl class to create a web control from scratch.

Depending upon the approach you choose their will be several properties and methods for you to override. All of them cannot be explained here so I am explaining some important among them that I have used in my code samples.

AddAttributesToRender – Adds HTML or Style attributes for any of your HtmlTextWriterTag. You can also use HtmlTextWriter’s “AddAttribute” , “AddStyleAttribute” methods to achieve the same functionality. Make sure that you add this attributes before using “RenderBeginTag” method.

RenderContents – Outputs HTML content of Server Control to HtmlTextWriter object. So override this method to manage the HTML that your custom control renders to the browser.

TagKey – WebControl renders a span TAG by default on the cient browser. But to render any specific TAG you need to override this method.

Inheriting from the existing control
This example depicts the creation of a new web control named “myButton” that is derived from the Button class. It has all the features that a normal button control has. But for a twist I have added a simple feature that prompts for a message before submitting the page back to the server. I have added a new property called “AlertMessage” to quench this requirement.


using System;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace myControlLib
{
    public class myButton : Button
    {
        public myButton() { }
        private string _AlertMessage = "Are you sure to process this request!";
        public string AlertMessage
        {
            set { _AlertMessage = value; }
            get { return _AlertMessage; }
        }
        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Onclick, "return confirm('" + _AlertMessage + "')"); base.AddAttributesToRender(writer);
        }
    }
}

Registering the control on the web page


<%@ Register Assembly="myControlLib" Namespace="myControlLib" TagPrefix="myUcl" %>

Using the control


<myUcl:myButton ID="MyButton1" runat="server" Text="MyButton 1"  AlertMessage="Custom Message here!"/>

<myUcl:myButton ID="MyButton2" runat="server" Text="MyButton 2" />

Inheriting from the WebControl class
This example depicts the creation of a new web control named “myImage” that is directly derived from the WebControl class. This control renders a Picture, Name of the Picture and Description of the Picture. Description of the Picture is displayed when the mouse is moved over the picture.
For this I have created 3 additional properties for this.

ImageUrl – The url of the image to be displayed

ImageName – The name of the image.

ImageDescription – The description for the image.


using System;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace myControlLib
{
    public class myImage : WebControl
    {
        public myImage() { }

        private string _ImageUrl = "";
        public string ImageUrl
        {
            get { return _ImageUrl; }
            set { _ImageUrl = value; }
        }
        private string _ImageName = "";
        public string ImageName
        {
            get { return _ImageName; }
            set { _ImageName = value; }
        }
        private string _ImageDescription = "";
        public string ImageDescription
        {
            get { return _ImageDescription; }
            set { _ImageDescription = value; }
        }
        protected override void RenderContents(HtmlTextWriter writer)
        {
            writer.AddAttribute("onmousemove", "javascript:document.getElementById('" + this.UniqueID + "_divDescription').style.display='';");
            writer.AddAttribute("onmouseout", "javascript:document.getElementById('" + this.UniqueID + "_divDescription').style.display='none';");
            writer.AddAttribute(HtmlTextWriterAttribute.Src, _ImageUrl);
            writer.RenderBeginTag(HtmlTextWriterTag.Img);
            writer.RenderEndTag();
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            writer.Write("Name : " + _ImageName);
            writer.RenderEndTag();
            writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
            writer.AddAttribute(HtmlTextWriterAttribute.Id, this.UniqueID + "_divDescription");
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            writer.Write("Description : " + _ImageDescription);
            writer.RenderEndTag();
            base.RenderContents(writer);
        }
        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }
    }
}

Registering the control on the web page


<%@ Register Assembly="myControlLib" Namespace="myControlLib" TagPrefix="myUcl" %>

Using the control


<myUcl:myImage ID="MyImage1" runat="server" ImageUrl="~/images/myImage1.jpg" ImageName="My Image Name"
ImageDescription="My Image Description........" />

Note: The above examples are the simplest controls that one can create. Remember that you can create more complex controls using the same approach. Choosing the best control that can serve the purpose of the requirement is our JOB and so make this decision very carefully.

How to make better appearance of your custom control in Visual Studio.

How to add custom control in Visual Studio Toolbox.