Mar 20, 2013

Proper configuring Log4Net in ASP.NET in separate file

There is a lot on net about Log4Net but still this fantastic tool falls in category "setup initially and forget".
This means that after you once configure it you forget is there for months and just use its fluent logging capabilities.
Hence on project kick off I tend to always spend time looking for proper way to configure it and sometimes run into questions.

Here goes recipe for configuring Log4Net for ASP.NET 4.5 MVC hosted in Visual Studio Development server.

  1. First use NuGet and install Log4Net for your project.
  2. For Web only! This is not necessary for Desktop when you execute 8.!
    In your web.config configsections register Log4Net section:
<configSections>
...

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

  </configSections>

3. For Web applications create log4net.xml and reference it as in 4. as standalone Log4Net config file.
For desktop create log4net.Config and reference it using assembly reference (see 8.)  Here is simple example:

<?xml version="1.0"?>
<log4net>
  <appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="log4net_applog.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>
  <root>
    <!-- OFF, FATAL, ERROR, WARN, DEBUG, INFO, ALL -->
    <level value="DEBUG" />
    <appender-ref ref="FileAppender" />
  </root>
</log4net>

4. Use this for WEB. In web.config  AppSettings section add reference to above Log4Net.xml:

  <appSettings>
...

  <add key="log4net.Config" value="log4net.xml" />   

...

5. Give write rights to folder in which log resides. This depends on your OS version. For Win 7 it is NETWORK SERVICE account. If you are using Local IIS then check in your IIS under which account runs your ASP.NET application pool.

6. In Global.asax.cs configure Log4Net instance as external:


 protected void Application_Start()
        {
            log4net.Config.XmlConfigurator.Configure();
...



7. In every class you wish to use log4net register log instance:



   private readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);


8. Use this for Desktop. Add this to your Assembly Properties file:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
Attribute watch enables to change configuration on the fly without restarting app.

9. If working in Desktop app go to properties of log4net.config and select "Copy If Newer".



Mar 19, 2013

ASP.NET 4.5 WEB API with Fiddler2

During my learning ASP.NET 4.5 WEB API I've spent too much time on one glich.
Here is my API controller action:

public DummyWrapper Post(DummyWrapper dummy)
        {            
            return "success";
        }



I was trying using Fiddler2 to emulate POST request:


User-Agent: Fiddler

Content-Type: application/json; charset=utf-8

Host: localhost:1600

Content-Length: 40


 {"dummy":{"value":"This is the title"}}

Initial version of my POCO on WEB API service


 public class DummyEntity
            {
                public string value { get; set; }
            }


I could not make Action model binder to deserialize above json object to dummy POCO.
After some time it hit me.
The catch was to wrap up entity in wrapper class.



 public class DummyWrapper
        {
            public DummyEntity dummy { get; set; }
           public class DummyEntity
            {
                public string value { get; set; }
            }
        }  

.NET HttpClient synchronous POST & GET

How to consume  ASP.NET REST-full WEB API in .NET Windows forms client app?
Visual Studio 2012 has introduced async methods and Tasks etc.
Hence it took me some effort to Google-out and figure out correct and cleanest way to POST & GET some POCO to ASP.NET WEB API and return it.

Class System.Net.Http HttpClient has gone through revamping and is ASYNC ready. Therefore it was hard to figure out simple stuff.

Bellow are two generic methods that perform converting POCO to Json using Json.NET framework and POST it to ASP.NET WEB API service. There is also simple GET variant.

Magic word  when using ASYNC methods is property Result.
It instructs method basically to switch to SYNCHRONOUS mode dropping all Task, await etc. stuff.

Yes, this approach negates whole async model of these methods.


using System.Net.Http;
using Newtonsoft.Json;

    public TResponse Post<TResponse, TRequest>(TRequest postdata, string postUrl)            
        {
            using (HttpClient client = new HttpClient())
            {
                var postdataJson = JsonConvert.SerializeObject(postdata);
                var postdataString = new StringContent(postdataJson, new UTF8Encoding(), "application/json");
                var responseMessage = client.PostAsync(postUrl, postdataString).Result;
                var responseString = responseMessage.Content.ReadAsStringAsync().Result;
                return JsonConvert.DeserializeObject<TResponse>(responseString);
            }
        }

        /// <summary>
        /// Perform HTTP Get the specified post ASP.NET WEB API URL.
        /// Try to convert response to TResponse
        /// </summary>
        /// <typeparam name="TResponse">The type of the response.</typeparam>
        /// <param name="postUrl">The post URL.</param>
        /// <returns></returns>
        public TResponse Get<TResponse>(string postUrl)
        {
            using (HttpClient client = new HttpClient())
            {
                var responseMessage = client.GetStringAsync(postUrl).Result;
                return JsonConvert.DeserializeObject<TResponse>(responseMessage);
            }
        }




Links:
http://forums.asp.net/t/1773007.aspx/1/10
http://blogs.msdn.com/b/webdev/archive/2012/08/26/asp-net-web-api-and-httpclient-samples.aspx

Mar 14, 2013

.net formatting double as percentage

Double value has to be represented as percentage value.

Double amount = 0.02;
string amountPercentage = amount.ToString("#,##0.0000 %");

Observe that % is command not sign.

Mar 12, 2013

ASP.NET MVC 4 Mobile project template

When you create new ASP.NET MVC 4 site you can choose "mobile application" project template.
This is just reminder to review this in future:

Mar 11, 2013

Enumaration revisited

Enum's can be used more efficiently and economically to describe constant values.
I tend to forget this syntax so here it is:


Example from Chess class. Elegantly describing chess piece using Flags in enum.
  [Flags]
        public enum PieceE : byte {
            /// <summary>No piece</summary>
            None      = 0,
            /// <summary>Pawn</summary>
            Pawn      = 1,
            /// <summary>Knight</summary>
            Knight    = 2,
            /// <summary>Bishop</summary>
            Bishop    = 3,
            /// <summary>Rook</summary>
            Rook      = 4,
            /// <summary>Queen</summary>
            Queen     = 5,
            /// <summary>King</summary>
            King      = 6,
            /// <summary>Mask to find the piece</summary>
            PieceMask = 7,
            /// <summary>Piece is black</summary>
            Black     = 8,
            /// <summary>White piece</summary>
            White     = 0,
        }

Explicit setting of type and value for Enum


    public enum MoveTypeE : byte {
            /// <summary>Normal move</summary>
            Normal                  = 0,
            /// <summary>Pawn which is promoted to a queen</summary>
            PawnPromotionToQueen    = 1,
            /// <summary>Castling</summary>
            Castle                  = 2,
            /// <summary>Prise en passant</summary>
            EnPassant               = 3,
            /// <summary>Pawn which is promoted to a rook</summary>
            PawnPromotionToRook     = 4,
            /// <summary>Pawn which is promoted to a bishop</summary>
            PawnPromotionToBishop   = 5,
            /// <summary>Pawn which is promoted to a knight</summary>
            PawnPromotionToKnight   = 6,
            /// <summary>Pawn which is promoted to a pawn</summary>
            PawnPromotionToPawn     = 7,
            /// <summary>Piece type mask</summary>
            MoveTypeMask            = 15,
            /// <summary>The move eat a piece</summary>
            PieceEaten              = 16,
            /// <summary>Move coming from book opening</summary>
            MoveFromBook            = 32
        }