Friday, 4 July 2014


In this blog I am going to give basic information which helps you to start working with knockoutJS.
Below are the concepts that we will be covering here.
  • What is knockoutJS
  • MVVM pattern
  • Starting with knockoutJS
  • How to do things with and without knockoutJS
  • Observables
  • Computed Properties
  • ObservableArray
  • Built in Bindings
  • Templates
  • Custom binding handlers
What is knockoutJS

From the official site, Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model. Any time you have sections of UI that update dynamically (e.g., changing depending on the user’s actions or when an external data source changes), KO can help you implement it more simply and maintainably.
It follows MVVM pattern.
Entirely written in Javascript.
Wide browser compability.

MVVM pattern

It is abbreviation of Model-View-ViewModel. In MVVM, UI layer will be separated into physical and logical layers.
VM (view-model) is the Logic layer. This, in general is a JavaScript function. It is a UI layer set of classes. It is a logical representation of User interface. We can think of UI in logical terms like properties/collections instead of textboxes or listboxes.
V(View) is the Physical layer.
M(Model) is the actual data.

Starting with knockoutJS

Before we get started with knockout, we need to download knockoutJS script file. We can get it from .Just refer it in the file where we need knockoutJS functionality using the below code
<script type='text/javascript' src='knockout-2.1.0.js'></script>

HTML5 “data-“ tags will be used by Knockout. How to use KnockoutJS will be discussed using the following 3 steps.

1. Declarative binding:
We use data-bind (data- attribute which is the feature of html5) attribute to work with knockout. We will be giving a key value pair to data-bind attribute. This key-value pair specifies what item should I use to what type of binding.
Lets consider the below example:
<input data-bind="value: name" />
Here I am binding name item (property) to value type of binding.
Note: Type of bindings are casesensitive. Specifying Value instead of value will lead to unexpected results.

2. Creating a ModelView that can be used in the declarative binding:
As we have discussed previously, ModelView is just a javascript function. Consider the following modelview object
var personModel = 
name : ko.observable("person1");
age : 20;
Here ko is a knockout defined object and observable is a special function of knockout. Observable means, if the value changes on UI, ko tells the underlying model that the value got changed and update all its references. In the similar way if the underlying value changes, it tells the UI that the underlying value got changed and get updated accordingly. This is nothing but a two-way binding. These observable properties are monitored by the framework to keep UI in sync with the ViewModel.
In the example, name is an observable property and age is not.
Consider the property age. This is not observable. If there are any updates done on that property, it will not be reflected. It just sends the data to the UI and not back. If we need any UI part associated with age property updated accordingly, we need to do it explicitly using JQuery or some other way. This is only one way binding. These kind of variables can be mostly used as readonly variables. There will be no events that will be invoked for this kind of properties.

3. Activating knockout:
This is the last and the most important step that we should not forget. After we are done with the above two steps, we need to bind the viewmodel to the view. This can be done using the following code snippet usually written in document.ready of the page.
applybindings can have an optional second parameter too. If we don’t specify the second parameter, it says to bind the viewmodel to the entire document. The second parameter when specified, helps us to bind a viewmodel to a specific section (say to a single div in the entire document). For example, the below code applies bindings to element with id "div1" only.

How to do things with and without knockoutJS
Let’s see with an example how a task can be done using knockout and JQuery. For now just look into the amount of code that we write for both. We will do an example in later stages.
The two code snippets below renders a text box and a message Welcoming the user (name given in the text box) using knockout and JQuery.
Using knockout:
<title>Using Knockout</title>
<div id="div1">
<span>FirstName: </span>
<input type="text" data-bind="value :firstName" /><br />
Welcome <span data-bind="text: firstName"></span>. </div>
<script type='text/javascript' src='knockout-2.1.0.js'></script>
<script type="text/javascript">

function EmployeeViewModel() {
this.firstName = ko.observable();

ko.applyBindings(new EmployeeViewModel(), document.getElementById("div1"));

Using JQuery:
    <title>Using Knockout</title>
    <div id="div1">
        <span>FirstName: </span>
        <input type="text" id="txtFirstname"/><br />
        Welcome <span id= "spanFirstname"></span>.
<script src="jquery-1.7.2.min.js" type="text/javascript"></script>
<script type="text/javascript" >

    $(document).ready(function () {
        $("#txtFirstname").blur(function () {



In JQuery we need to handle onblur event dynamically, whereas in Knockout, the framework takes care of everything. This is just one of the example.
Note: Knockout is not a competitor for JQuery. It just does some of the task easy.


As I have already discussed that observables are special knockout functions. When a property is specified as "observable", they get the ability to detect changes and update the view or the underlying viewmodel accordingly.
Reading and writing observables
Lets check the below example to know how to read an observable.
Here is my updated view model.
function PersonViewModel()
    firstname = ko.observable('John');
    lastname = ko.observable('L');
    score = ko.observable(25);
    fullname = ko.computed(function () {
        return firstname() + ' ' + lastname();
Below is my view (html page):

First Name: <span data-bind="text: firstname"></span><br />

Score: <input type="text" data-bind="value: score, style:{ color: score() < 20 ? 'red' : 'black' }" /><br />

Hi <span data-bind="text: fullname"></span> Your Score is <span data-bind="text: score, style:{ color: score() < 20 ? 'red' : 'black' }"></span>
If you see the view model part, observables are used as functions(look at the fullname).
In View, when a observable is used in any expression, if will be used as a function.
Suppose we need to update score value, this can be done using personViewModel.score(30);

Computed Properties
Computed properties are those which will be updated whenever value of an observable changes.
These will be defined using knockout's computed function. In the previous example, fullname is a computed property which will be recalculated when ever either firstname or lastname changes.
Observable Array

Similar to observables, observableArrays will be automatically reflected when any change occurs. If we have only one object that changes, we can use observables and if have a list of objects we can go with observableArrays.
This can be useful in working with a list of items.
Lets consider an example to display a list of food items using an observableArray. This can be done as below.
I have updated my view model to include 2 extra properties.
fooditems = ko.observableArray(['Pizza', 'Sandwitch', 'Burger', 'Veg-Roll', 'Fruits', 'Vegetables']);
selectedfooditem = ko.observable('');
and below is my updated view
<select data-bind="options: fooditems , value: selectedfooditem, optionsCaption: 'Choose...'"></select>
<span data-bind="text: selectedfooditem"></span>
If you look into the above change, I am using options binding to bind the fooditems observable array to the dropdown. value binding is used to get the selected item (Here selectedfooditem observable will be updated whenever selection changes).
Whenever you are trying to bind an observablearray of objects to the dropdown, you will need to specify which property of that object should be shown in the dropdown. This can be done using optionsText binding. We will specify the property name like in the example below:
Here is my updated View model part:
fooditems = ko.observableArray([{ item: 'Pizza', price: 30 }, { item: 'Sandwitch', price: 50 }, { item: 'Burger', price: 60 }]);
selectedfooditem = ko.observable('');

Here is my updated view part:
<select data-bind="options: fooditems , optionsText: 'item', value: selectedfooditem, optionsCaption: 'Choose...'"></select>
<span data-bind="text: selectedfooditem().item"></span>
Important Note:
  • Dont forget to put single-quotes for the property name used for optionsText
  • We have used selectedfooditem().item to get the fooditem name in the span
Built in Bindings
The following bindings are available in knockout.js
Bindings that control text and appearance
  • visible: This binding causes the associated DOM element to be hidden or shown based on the value we pass
  • text: This binding causes the associated DOM element to display the text that is passed.
  • html: Similar to text binding. But renders the value as html.
  • css: Adds or removes the css class specified.
  • style: If we want to set style instead of css class, we can use this
  • attr: In knockout.JS only few attributes can be bound directly. Suppose if we want to bind 'src' of img tag, we can use this attr binding. This can be used as data-bind="attr:{src: imagePath}". Here imagePath is a property in the viewmodel.
As the name suggests Templates are reusable code. A part of code can be repeated in multiple places which helps in reducing duplicate code.
Templating can be done in the following ways.
Native Templating:
Native templating is nothing but using templating concept as inline feature. We can use a foreach loop to have an inline templating.
For example:
<div data-bind="foreach: fooditems">
        <span data-bind="text: item"></span><br />
        <span data-bind="text: price"></span><br />
If you see the above example, spans will be repeated for all the items in the array fooditems. This means we are reusing the same part of code again and again.
String based Templating:
Here we will be using an external template, pass our model values to the template and inject the resulting markup in the document. This will be generally written in script tags. If we have some part of code that will be used in multiple places, we simply create a template for it and use it at all the required places. template binding will be used in this case. Consider the following example.
<div data-bind="template: { name: 'display-template', data: {firstname: 'John', age : 22 } }"></div>
<div data-bind="template: { name: 'display-template', data: {firstname: 'Mark', age : 19 } }"></div>
<script src="Scripts/knockout-3.1.0.js"></script>
<script src="Scripts/jquery-2.1.1.js"></script>
<script type="text/html" id="display-template">
Hi <span data-bind="text: firstname"></span> Your age is <span data-bind="text: age"></span>
function MyViewModel() {
var self = this;
$(function () {

var myvm = new MyViewModel();

If you see the above code, the template with name 'display-template' is used. This display-template is defined in script tags with the same as id. Whereever we use the template binding with the templatename as 'display-template', the script will be rendered as the result. As in the above example, we can pass parameters using the 'data' attribute and access them in the template declaration.

Custom Binding Handlers
Go for custom binding when can't find the right binding that you want to use. Custom bindings can go handy when you want to do the following.
  • Integrate some third party widgets with knockout.
  • Update built-in bindings to give more functionality.
Lets look at custom bindings a bit closer.
All bindings in knockoutJS come from bindingHandlers. It mainly provides 2 callback methods.
  1. init: knockout calls this function for every DOM element that you use this binding for.
  2. update: knockout calls this function along with init function and also whenever there are any changes to the observables that we access.
Basic syntax of custom binding:
ko.bindingHandlers.yourBindingName = {
init: function(element, valueAccessor, allBindings, bindingContext) {
// knockout calls this function for every DOM element that you use this binding for.
update: function(element, valueAccessor, allBindings, bindingContext) {
// knockout calls this function along with init function and also whenever there are any changes to the observables that we access.
The parameters to these functions are optional.
  • element: You might need to know the element that invoked this binding. In this case, you can use element parameter.
  • valueAccessor: Used to get current viewmodel property bound to this element.
  • allBindings: Used to get values of all the bindings associated to the DOM element.
  • bindingContext: Used to get the bindingContext of the currently bound element.
Integrate third party widgets with knockout
We can integrate third party tools like JQuery UI with knockoutJS. All we have to do is create a custom binding to that. Lets consider an example to use JQuery datepicker.
Consider the below code:
<script src="Scripts/knockout-3.1.0.js"></script>
<script type="text/javascript">

    ko.bindingHandlers.datepicker = {
        init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {

            var dateFormat = allBindings().dateFormat;
            var buttonImage = allBindings().buttonImage; // allBindings.get('dateFormat');

            if (typeof dateFormat == 'undefined') {
                dateFormat = 'mm/dd/yyyy';

            if (typeof buttonImage == 'undefined') {
                buttonImage = "Images/icon_date_picker.png";

            var options = {
                showOtherMonths: true,
                selectOtherMonths: true,
                dateFormat: dateFormat,
                buttonImage: buttonImage,
                showOn: "both"

            if (typeof valueAccessor() === 'object') {
                $.extend(options, valueAccessor());


        update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {

            var v = valueAccessor()();
            bindingContext.$data.message('You selected '+v);


    var viewModel = {
        myDate: ko.observable(''),
        dateFormat: ko.observable('mm/dd/yyyy'),
        message : ko.observable('')

    $(document).ready(function () {

<span data-bind="text: message"></span><br />
<input data-bind="datepicker: myDate, value: myDate,defaultDate: '', dateFormat: 'dd, MM yy'" />
If you see the above example, I have created a custombinding named 'datepicker'. In the init function, I have used 'allBindings()' to get the required bindings associated with this element. Finally I am using those bindings as input values to options. Using $(element).datepicker(options); statement, we are adding JQuery datepicker using knockoutJS Update function will be invoked whenever there is a change in the value bound to the element i.e.., when we select any date from the datepicker.
Update built-in bindings to give more functionality:
As discussed in "Built in bindings" section, In knockoutJS only few attributes can be bound directly. Suppose if we want to bind 'src' of img tag, we can use this attr binding. Instead of using attr binding with src property, we can create a custom binding so that it can be used whenever we want to set src for image tag.
This can be done as below
ko.bindingHandlers.customImgSrc = {
update: function (element, valueAccessor) {
ko.bindingHandlers.attr.update(element, function () {
return { src: valueAccessor() }
From the above custom binding, we can see that we are using 'update' to the built-in binding 'attr'. Now, the UI binding can be as below:

<img data-bind="customImgSrc: myImage" />
<img data-bind="customImgSrc: 'Images/icon_date_picker.gif'" />
instead of
<img data-bind="attr:{ src: 'Images/icon_date_picker.gif' }" />

That's all from my side. If you find anything intersting in knockoutJS, try sharing it.
Let me know if you have any suggestions.

Friday, 4 April 2014

Working with Log4net


  • A small introduction
  • Start working with log4net
  • Levels of logging
  • Loggers and Appenders
  • How to debug issues with log4net
  • Layouts – and types
  • Filters – and types

A Small introduction: 

From, you can see Log4net framework is based on log4j. In short we can say, log4net is for Microsoft .Net applications and log4j is for java. 
So why do we need log4net or log4j?
This tool helps the programmer to log information to different targets. 
So what kind of information we log and what are those targets?
Suppose, we have a project in production. During its daily usage, there might be some case where it might have caused some unexpected error. Now how will you track that issue? Or how will you confirm that some specific code caused that issue? This can be done by logging some information.
What is a target?
Targets can be a file system, database or any other location to log information, which we will be discussing later.

Start working with log4net:

To log some information, we need to configure it. This can be done in the following ways
BasicConfigurator: Supports logging to only one source. 
When this configurator is used, by default the logged information will be shown on Console (Supports only logging to Console). When we use this, the consoleappender is logically added to the root logger.
DomConfigurator: (deprecated. Use Xml configurator instead of this.)
XmlConfigurator: This means that we are using a file written in xml format to configure log4net (Supports logging to different places at a time).

These configurators look for a config section element with name log4net in web.config / app.config file. The below one should be added as child to the configuration element in config file:

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>

This line will be added only when we are writing entire configuration in either web.config/app.config file. If we using a seperate file to configure log4net, the above lines are not necessary

Configuring using the above configurators can be done either through 
  1. Code or 
  2. Assembly-level attributes.

Using code: 

We need to write the below line well before using log4net to perform any logging operations. Generally this will be written in Application_Start(arg1,arg2) of global.asax.


We can use BasicConfigurator/ DomConfigurator in the similar way.
The static Configure() is overloaded to accept a file, stream, URI, or an XmlElement object as input to it. The parameter-less method is used to refer to the application’s web.config or app.config file.

In addition to this, we are having ConfigureAndWatch() which will accept the file info as reference.
ConfigureAndWatch (parameter) method watches the file to keep track of any changes made to it. If there is a change in the file the log4net configuration will be automatically configured.

Using Assembly level attributes:

Instead of configuring log4net via code, it can also be done using AssemblyInfo.cs file located in properties. 
We can configure log4net in the below ways:
  1. [assembly: log4net.Config.XmlConfigurator(Watch=true)]
    This, by default, looks for web.config or an app.config file to load appenders, loggers etc. This is similar to Configure() that we write from code.

  2. [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)]     
  3. [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4netexplicitfile.txt", Watch = true)]
    Using this, we can have a separate file for configurations to log4net instead of writing in application’s web.config or app.config file.
    Mentioning it as a separate file helps us to change the configuration without restarting the application again.
Here the parameters ConfigFile can be any file (say txt, xml etc). 
Watch: Implies, It keeps track of any changes to that file. If this is false, even if configuration file changes, there will be no impact to log4net functionality.
Suppose we have added a text file having configuration settings as below. 

<?xml version="1.0" encoding="utf-8" ?>
<appender name="AppenderFile" type="log4net.Appender.FileAppender">
<file value="LogFileName1.log" />

<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d{hh:mm:ss} %message%newline" />

<level value="DEBUG" />
<appender-ref ref="AppenderFile" />

And this file has been configured using assembly statement as in point 3. 
Publish two different binaries one with watch = false and the other with watch = true.

Do the following steps with both the binaries.
  • Run the project and ensure logging is happening.
  • Open the log4netexplicitfile.txt file and change file attribute value to someother filename.
  • Perform action that logs something using log4net.
  • See whats happening with both the binaries. You should be seeing the following.

  • With watch = true: A new file is created and it will be used hereon for logging purposes.
    With watch = false: The changes done will not be recognized and will continue logging to the same old file.

Levels of logging:  

  • Debug
  • Info
  • Warn
  • Error
  • Fatal

Loggers and Appenders: 


Loggers control the levels of message that needs to be logged. It has two important parts.
  1. level
  2. appernder-ref
Consider the following logger example

<logger name="SmtpAppenderLog4net.WebForm1">
<level value="All" />
<appender-ref ref="WebForm1logger" />

Here, name of the logger is SmtpAppenderLog4net.WebForm1. This indicates, SmtpAppenderLog4net is the namespace and WebForm1 is a class inside it or inner namespace. Level mentioned is “All”. This indicates the logger accepts all the levels of logging. It can be anyone of the below:
  • All
  • Off – Logging will not be done.
  • Fatal
  • Error
  • Warn
  • Info
  • Debug

Appender-ref is which appender we should refer. Here WebForm1logger is an appender name. In the previous examples, you might have seen an xml element <appender>. Now let’s discuss what exactly an appender is.


Appenders say where to store the log messages in our application. There can be one or more appenders in the configuration. If we have multiple appenders, its name must be unique. You can see the list of appenders in For now, we will have small info on the below appenders
  • ConsoleAppender
  • FileAppender
  • Rolling file appender
  • AdoNetAppender


This appender logs messages to the console. This can be configured as below:

<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.SimpleLayout" />


This appender when used logs the messages to the specified file. This can be written as below:

<appender name="LoggingToFileAppender" type="log4net.Appender.FileAppender">
<file value="FileToLog.txt"/>
<appendToFile value="false" />
<layout type="log4net.Layout.SimpleLayout" />

Here logging of messages will be done to FileToLog file.
appendToFile element specifies whether we should append the logs to the previous content in the file or not.


This logs messages to different files depending on size or date or both. You might think we are having a fileappender and why again this RollingFileAppender. Using FileAppender is not recommended because the file can grow in size in a time frame. Opening/reading such a file takes much time. Using RollingFileAppender, we can have backup of files.

<appender name="LoggingUsingRollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="LoggingUsingRollingFileAppender.txt"/>
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="10MB" />
<staticLogFileName value="false" />
<countDirection value="-1"></countDirection>
<layout type="log4net.Layout.SimpleLayout" />

Here logging of messages will be done to LoggingUsingRollingFileAppender file based on size. Here I specified maximumFileSize as 10MB which means for every 1kb a new file will be created and the previous logs will be as backup.
Number of backup files that willbe saved depends on the maxSizeRollBackups value. Here at any time, 2 backup files will be present.
RollingStyle is Size. This means that rolling of files should happen based on size. Here in this example, for every 10MB file generated, rolling should happen.

We can have the following values for RollingStyle:
  • Size - Rolling will happen based on Size
  • Date - Rolling happens based on Date
  • Composite - Rolling happens considering both size and date
  • Once - Rolling happens every time log4net is configured. To check this just make some changes to the log4net configuration and run your project again. This will leave a backup file and create a new file
appendToFile element specifies whether we should append the logs to the previous content in the file or not.


Using this, we can log messages to a table in the database.
We will create a table in database and use it as source to store logs. For now I am using below SQL statement to create a table in database.

CREATE TABLE [dbo].[Log] (
[Id] [int] IDENTITY (1, 1) NOT NULL,
[message] [varchar] (2000) NULL

AdoNetAppender can be configured using the below snippet.

<appender name="SQLServerAppender" type="log4net.Appender.ADONetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="Data Source=yourDataSource;Initial Catalog=YourDatabase;User ID=userid;password=password" />
<commandText value="INSERT INTO Log ( [message] ) VALUES ( @message )" />
<parameterName value="@message" />
<dbType value="String" />
<size value="2" />
<layout type="log4net.Layout.PatternLayout" value="%message" />

Element bufferSize specifies that, log4net will keep these many records in memory before inserting into the database. Suppose if we specify its value as 10, After 10 logs you will see data to be inserted into database.
dbtype is the datatype of the value.
size: here only 2 characters are allowed and logged. Suppose the log message is "Hello World", only "He" will be seen in database column.

Once I ran into an issue where I saw nothing is written to my database(I have used ADONetAppender). I crosschecked the connectionstring, the appenders part and all and felt everything is perfect. Thanks to log4net guys for adding a way to find out whats wrong with the configuration. I have added the following key to app settings in web.config(in your case may be in app.config). Ran the application again and looked into the Output window (ctrl+W,O) in Visual studio and found that I have given wrong column name.
So guys, from the next time, if you find nothing is being logged, dont forget that there is a debugging feature in log4net.

Layouts and types:

In appender section, you might have seen xml element <layout> . So what is a layout? Layout is just a template for your messages. You can customize your message using this.
  • SimpleLayout
  • PatternLayout
  • XMLLayout
  • RawPropertyLayout
  • RawTimeStampLayout
  • RawUtcTimeStampLayout etc…...


This is the simplest layout which contains minimal information about the logged message. It gives only level and the message of the logged message

<appender name="WebForm1logger" type="log4net.Appender.FileAppender">
<file value="WebForm1logger.txt" />
<layout type="log4net.Layout.SimpleLayout"></layout>

Logs in WebForm1logger.txt will be of format level_of_logged_message message


This is similar to printf statement in C or the string.Format() in C#. Simply to say, it is a conversion pattern. We have the flexibility to format the message by adding some information to it.

Some of the conversion patterns are listed below:

Pattern name Effect seen at the time of logging event
Appdomain Outputs appdomain name
Date Outputs date
Exception Outputs exception passed with the message
Level Outputs level of logging event
Logger Outputs the logger that logged the event
Message Outputs the message passed with the logging event call
Newline Inserts a new line
Property Used to output an event specific property. The property will be specified within braces. Example : property{customproperty}. This will look for the key named customproperty and will get the value associated to it. If no specific key is given, then all the keys and their values are printed in a comma separated list.
Timestamp Used to output the number of milliseconds elapsed since start of the application till the logging event.
Thread Used to output name of the thread. If no name is given, number will be considered.
Utcdate Outputs date in universal time.
% Prints a %

We can use PatternLayout using the below code:

<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />

This results in date - message_passed_from_the_logger


This logs information in xml format.This can be used in the following way:

<layout type="log4net.Layout.XMLLayout"></layout>


This is mostly used in ADOAppender while adding value to new column. This can be used as:

<parameterName value="@Email" />
<dbType value="String"/>
<size value="255"/>
<layout type="log4net.Layout.RawPropertyLayout">
<key value="CustomPropertyEmailid"></key>

Here Email is the column name in log4net. We are binding a property “CustomPropertyEmailid” value to this column. Value to this property can be set using the following line (this is one of the way):

log4net.ThreadContext.Properties["CustomPropertyEmailid"] = "";

RawTimeStampLayout, RawUtcTimeStampLayout will be used mostly in ADONetAppender.

Filters - Its types

Suppose there is a case where you need to log Info, debug, warn level logs to one file and Error, Fatal level logs to other. Or suppose we need to log messages that match certain search criteria or reject messages matching some criteria. How this can be accomplished? Log4net comes up with Filters concept to accomplish this. It has the following filters.
  • LevelMatchFilter
  • LevelRangeFilter
  • LoggerMatchFilter
  • StringMatchFilter
  • PropertyFilter
  • DenyAllFilter
LevelMatchFilter: This filters messages against this specific level. It accepts the following properties
levelToMatch: this contains the level that needs to be matched.
acceptOnMatch: Boolean value to indicate whether to accept this level or reject it. Default is true

<appender name="LoggingToFileAppender" type="log4net.Appender.FileAppender">
<file value="Debuglogs.txt"/>
<appendToFile value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %logger %message %newline "/>
<filter type="log4net.Filter.LevelMatchFilter">
<acceptOnMatch value="true" />
<levelToMatch value="DEBUG" />
<filter type="log4net.Filter.DenyAllFilter" />

The above filter logs only when the level matches debug. You can check this in Debuglogs file. Dont forget to include denyAllFilter filter.

LevelRangeFilter: This filters messages that fall within the range specified or not in the range depending on acceptToMatch property.

<appender name="LoggingToFileAppender" type="log4net.Appender.FileAppender">
<file value="DebugToWarnlogs.txt"/>
<appendToFile value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %logger %message %newline "/>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="WARN" />
<filter type="log4net.Filter.DenyAllFilter" />

The above filter logs only when the level is in range of debug to warn. All others will be ignored. You can check this in DebugToWarnlogs file. Dont forget to include denyAllFilter filter.

LoggerMatchFilter: This filters messages against the logger that logged the message. This uses startsWith() operation to check for logger match.

<appender name="LoggingToFileAppender" type="log4net.Appender.FileAppender">
<file value="loggerMatchFilter.txt"/>
<appendToFile value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %logger %message %newline "/>
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="MyLog4netProject"></loggerToMatch>
<filter type="log4net.Filter.DenyAllFilter" />

Here the logger that will be match will be those that start with "MyLog4netProject".

StringMatchFilter: This helps to filter messages based on the message content. This can be configured as below:
regexToMatch: regex expression can be given to match the log message.
StringToMatch: Filters messages by checking whether message contains this string or not. It is case sensitive search.
acceptOnMatch: Boolean property.

<appender name="LoggingToFileAppender" type="log4net.Appender.FileAppender">
<file value="StringMatchFilter.txt"/>
<appendToFile value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %logger %message %newline "/>
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="MyLog4netProject"></stringToMatch>
<filter type="log4net.Filter.DenyAllFilter" />

The above example logs messages if the message contains the string "MyLog4netProject". The search is case sensitive.
Usually, we specify either regexToMatch or stringToMatch property. If we specify both, regexToMatch will be considered and stringToMatch will be simply ignored.

PropertyFilter: Here match is made against the value of the property specified in the “key” attribute.
Key: Here we will specify on which property the match should happen.
And all the attributes available for StringMatchFilter are also available for PropertyFilter.

DenyAllFilter: This denies logging. Usually we will specify this at the end of all filters. This will be added as below.

<filter type="log4net.Filter.DenyAllFilter" />

Any suggestions are welcomed. Please comment if anyone has any issue with this post.