Dec 22, 2015

RePost - ELMAH

Check this out :

https://code.google.com/p/elmah/

Oct 16, 2015

ASP.NET MVC routing ordering

Always place more specific route before less specific in your routes definitions ....
And I always forget it.
More specific route includes your parameters and so :
        
    routes.MapRoute("ReportsWithoutMISCode",
              "Reports/{Action}/{programObjectiveId}/{userName}",
              new { controller = "Reports", action = "Index" },
              new { programObjectiveId = @"\d+" },
              new[] { "Web.Controllers.Reports" });
     routes.MapRoute("ReportsWithMISCode",
              "Reports/{Action}/{programObjectiveId}/{userName}/{MISCode}",
              new { controller = "Reports", action = "Index" },
              new { programObjectiveId = @"\d+" },
              new[] { "Web.Controllers.Reports" });

; should be switched since second route ReportsWithMISCode is more specific, means having more parameters.

So it should be:

     routes.MapRoute("ReportsWithMISCode",
              "Reports/{Action}/{programObjectiveId}/{userName}/{MISCode}",
              new { controller = "Reports", action = "Index" },
              new { programObjectiveId = @"\d+" },
              new[] { "Web.Controllers.Reports" });
      routes.MapRoute("ReportsWithoutMISCode",
              "Reports/{Action}/{programObjectiveId}/{userName}",
              new { controller = "Reports", action = "Index" },
              new { programObjectiveId = @"\d+" },
              new[] { "Web.Controllers.Reports" });

It is interesting to note that in first case route works in awkward way. It gets matched but third parameter MISCode is appended as query param with question mark like this:

...ReportXXX/101/pt2?MISCode=MyMISCode

After switching to second solution we get friendly url.

Aug 19, 2015

Regex - Match only first occurence

In UTF-8 HTML text like this :

<table>
<tr class="dummy">
First
</tr>
<tr class="foo">
Second
</tr>
</table>
; you want to parse out list of two rows.

First,
Second

To achieve this use non greedy expression ?. Basically after you state what is pattern and how often it occurs by using ? you want to limit search only to first occurence.

Example regex with UTF8 greedy expression:

(?<=tr\sclass="\w+">)+?(?>\P{M}\p{M}*)+?(?:\<\/tr\>)+?
http://stackoverflow.com/questions/2503413/regular-expression-to-stop-at-first-match

Aug 6, 2015

RePost : C# - using statement tips

When using any class that implements IDisposable it is advisable to use using statement.

Now what I didn't know is that using statement is replacement for try finally with call to dispose.

Furthermore call to dispose internally calls Close() for Streams I think.

So using statement is real champion :)

Instead of:

try{

Stream s = new Stream();

}
finally
{
s.Flush();
s.Close();
s.Dispose();
}

Just this:

using ( Stream s = new Stream())
{
}

Important!

Flush() is NOT called automatically !
So using takes care of connections and resources but does not takes care that your data will be flushed from cache.
This makes sense since it primary protects from exceptions and developer should think about Flush().

http://stackoverflow.com/questions/911408/does-stream-dispose-always-call-stream-close-and-stream-flush

TODO Reading list . MSDN Network programming

https://msdn.microsoft.com/en-us/library/4as0wz7t(v=vs.100).aspx

RePost: Naming conventions by Microsoft

Good reading for which I never found time. Yet it is always subject of furious discussion with fellow programmers.

https://msdn.microsoft.com/en-us/library/ms229002(v=vs.110).aspx

Jun 2, 2015

Feb 26, 2015

Log4Net - Tips

In log4net.xml you define level of messages you wish to log.

  <root>
    <!-- OFF, FATAL, ERROR, WARN, DEBUG, INFO, ALL -->
    <level value="WARN" />
    <appender-ref ref="FileAppender" />
  </root>

Question is how to properly use these levels in your code?
The provided comment is incorrect.
Here is the correct hierarchy of levels order from most important to least important.:

FATAL
ERROR
WARN
DEBUG
INFO

Idea is when for example you set FATAL level ONLY log.Fatal methods will finish in your log and nothing else.
For ERROR level you will get ERROR + FATAL.
With WARN you have WARN + ERROR + FATAL.

Etc.  you got idea.


Some people use provided helpers: 

IsInfoEnabled()
IsDebugEnabled()

etc. 
If you DO NOT place some time consuming activity in your log.Info   statement forget it, you don't need it!
Log.Info will determine based on LEVEL from XML should it or should it not get written into log. Idea is with IsInfoEnabled() to suppress even start of execution log.Info().

Make different logging level for different types

When you create your logger instance in every type make sure to use typeof so that you can reference it, when needed, in Log4Net.xml as specific appender for that type.

readonly ILog log = LogManager.GetLogger(typeof(TypeName));

Watch it ! When configuring logging for specific type:

<logger name="MyNameSpace.MyType">
     <level value="DEBUG"/>
</logger>

; make sure to make fully qualify name for type including namespace.

Log different types in different log files

For example you wish to make logs for specific .NET type in different log apart from main.

Make specific new Appender in new log file :

<appender name="HelperAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="helper.log"/>
    <param name="DatePattern" value="yyyy.MM.dd" />
    <param name="RollingStyle" value="Size" />
    <param name="maxSizeRollBackups" value="10" />
    <param name="maximumFileSize" value="100KB" />
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%date{yyyy-MM-dd HH:mm:ss ffff} [%-3t] %-5p %logger{1}.%method: %message%newline" />
    </layout>  
  </appender>

Create new logger section with fully qualified .NET type name you wish to log and reference to above created Appender:

  <logger name="Log4NetTest.Helper">
    <level value="INFO"/>
    <appender-ref ref="HelperAppender"/>
  </logger>