Friday, July 27, 2012

NPOI or EPPlus? Which is better?

In my current project, I had a requirement to export and import the data to an excel file. There are plenty of free libraries available, but only NPOI and EPPlus are worth taking a look.

After initial searching and experimentation, i have come to the following conclusion.
Pls. note that these conclusions have been arrived at, only after my personal trials.

NPOI
1) The library is good and extensive, but the API's are not at all intuitive and user friendly
2) Performance in terms of time and memory, is a big disappointment.
3) The only advantage in favour of NPOI, according to me, is its ability to generate xls and xlsx files.

EPPlus
1) The library is very well written and API's are user-friendly, very much identical to Interop.excel
2) Performance is big big gain while using EPPlus. Thousands of cells can be read/written in a matter of seconds.
3) It can generate file only in xlsx format. No facility of xls. But one can always download the Microsoft Compatibility pack to overcome this problem.

Wednesday, July 18, 2012

WCF Service Traces using SVC Trace Viewer

In WCF projects, one would invariably need some kind of mechanism to ascertain whether the data is sent/received over the communication channel. One can definitely use fiddler for monitoring the data traffic over an http channel. But, WCF tracing provides a nifty way of verifying whether the data has been received/sent from WCF side.

It is easy to add the Tracing information in the WCF project. One would just need to add the diagnostics element in the web.config / app.config file of the WCF hosting project.
A sample element structure is shown below.

<system.diagnostics>
    <sources>
      <source name="System.ServiceModel" switchValue="Information" propagateActivity="true">
        <listeners>
          <add name="corr"/>
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="corr"/>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="corr" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\personal\Service.svclog">
      </add>
    </sharedListeners>
  </system.diagnostics>

"c:\personal\Service.svclog" is the absolute file path for the log file that will be generated from the WCF traces.
Navigate to the file location and view the log file in the SVC Trace Viewer for easy debugging.

Friday, July 6, 2012

Logging using log4net

In almost every application (windows or web based) one needs to monitor the health of the system. Meaning, every application invariably maintains an audit trail which can be inspected by the development team in-order to understand the application flow and rectify the errors (if any).

I have been addressing the above requirement by implementing a singleton, thread-safe logger class for such purposes.

But recently, I learnt a much easier way to do the logging using a freely available library named as log4net.

log4net dll can be downloaded from Log4net.

1) Inorder to use log4net we need to configure the expected behavior in the app.config or web.config files (depending upon the application type)
I am explaining only the web.config part here. But the same holds good for app.config.

1.1) Create a new section node under the <configSections>  in the web.config file as shown below
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>

1.2) Now, create a log4net node in the web.config file,

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

<!-- File Appender -->
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value=""/>
               <StaticLogFileName value="false"/>
               <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
              <appendToFile value="true"/>
<rollingStyle value="Composite"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
             <datePattern value=".yyyy-MM-dd'.lo\g'"/>
<encoding value="unicodeFFFE"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="RollingLogFileAppender"/>
</root>
</log4net>

The best part of log4net is that you can have multiple appenders for logging the data. Also, several processes can log to the same file, provided you do the correct settings in the <lockingModel> node.

So, as per the above settings,
we are asking log4net library to create a Rolling log file, with lockingModel type as MinimalLock [for multiple processes to log to same file], each file size to be of 10MB and maximum file backups to be maintained as 10.
Further, the file name should end with ".yyyy-MM-dd.log". where yyyy-MM-dd represents the file creation date.

Usage:


log4net.Appender.IAppender[] AppenderList = D2DELLogger.ms_log.Logger.Repository.GetAppenders();
                        foreach (var item in AppenderList)
                        {
                            if (item.Name == "RollingLogFileAppender")
                            {
                                ((log4net.Appender.RollingFileAppender)(item)).File = Path.Combine(System.Configuration.ConfigurationManager.AppSettings["LogFilePath"].ToString(), "D2DLogs\\D2DTrace.log");
                                ((log4net.Appender.RollingFileAppender)(item)).ActivateOptions();
                            }
                        }

Note: We are calling ActivateOptions() method, because the configuration properties are being modified in the preceding line. [ in a real world scenario, every application would be developed to have a customizable file name, hence we modify the file name that was configured via. the web.config file].

Hope this post helps everyone.






Tuesday, July 3, 2012

Method extensions and Useful Enum Method Extension

In many of the projects, there is a requirement to get the string values from the enum definition.
One attribute that can be used off-the-shelf is [Flags] attribute. But this attribute gives only the string representation of the enum variable, which means you cannot have spaces or long strings.

So to overcome this, one can write a handy enum extension for this.
Consider the following enum,

internal enum XlColumnHeaders
    {       
        [StringValue("Section")]
        xlSection = 1,

        [StringValue("Question Text")]
        xlQuestionText = 2,

        [StringValue("Free Text")]
        xlFreeText = 3,

        [StringValue("Yes No")]
        xlYesNo = 4,               
    }
Now whenever I wish to get a string representation of xlSection, I should get "Section". Similarly, for xlQuestionText I should get "Question Text" [Note: the space between the 2 words].

To achieve the above result, Create a static class with a public static method as follows.
static class StringEnum
    {
        public static string GetStringValue(this Enum value)
        {
            // Get the type
            Type type = value.GetType();

            // Get fieldinfo for this type
            FieldInfo fieldInfo = type.GetField(value.ToString());

            // Get the stringvalue attributes
            StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(
                typeof(StringValueAttribute), false) as StringValueAttribute[];

            // Return the first if there was a match.
            return attribs.Length > 0 ? attribs[0].StringValue : null;
        }
    }

Usage:
XlColumnHeaders temp = new XlColumnHeaders();
temp = XlColumnHeaders.xlQuestionText;
temp.GetStringValue();             // this would return "Question Text"

Hope this post is helpful.