Dec 15 2009

Setup your solution and project for success by proper naming conventions, namespace configuration and folder structure

Category: ASP.NETryancmartin1976 @ 20:56

First Strategy:

Second Strategy:

Let's say you’re building a web application which connects to a database. This is a very normal and consistent scenario for business developers on a day to day basis. Right off the bat you now have two projects to build within one solution; the UI Layer and the Data Access Layer. I will also add two more projects to this solution, UI Tests and Data Access Tests.

STEP 1

Create the solution and projects

IpswitchftWeb.sln

  1. IpswitchftWeb.csproj (Web Application)
  2. IpswitchftCore.csproj (Data Access)
  3. IpswitchftWebTests.csproj (Web Application Tests)
  4. IpswitchftCoreTests.csproj (Data Access Tests)

STEP 2

Update the assembly and default namespaces

Next you want to update assembly name and default namespace values the properties tab for all four projects within Visual Studio.

  1. Ipswitchft.IpswitchftWeb (Web Application)
  2. Ipswitchft.IpswitchftCore (Data Access)
  3. Ipswitchft.IpswitchftWebTests (Web Application Tests)
  4. Ipswitchft.IpswitchftCoreTests (Data Access Tests)

STEP 3

Add folders to your project that make sense

Open up your IpswitchftCore.csproj and six folders:

  1. Core (root)
  2. Core/DataAccess (interfaces)
  3. Core/DataAccess/Impl (concrete classes)
  4. Core/Domain (data model)
  5. Core/Service (interfaces)
  6. Core/Service/Impl (concrete classes)

STEP 4

Here is an example of requesting data from the data access layer from the service layer that can be called from the web application.

IpswitchftCore/Core/DataAccess/ITestRepository.cs
using StructureMap;
 
namespace Ipswitchft.IpswitchftCore.Core.DataAccess
{
    [PluginFamily("Default")]
    public interface ITestRepository
    {
        string GetData();
    }
}
IpswitchftCore/Core/DataAccess/Impl/TestRepository.cs
using StructureMap;
 
namespace Ipswitchft.IpswitchftCore.Core.DataAccess.Impl
{
    [Pluggable("Default")]
    public class TestRepository : ITestRepository
    {
        public string GetData()
        {
            return "data from a linq object";
        }
    }
}
IpswitchftCore/Core/Service/ITestService.cs
using StructureMap;
 
namespace Ipswitchft.IpswitchftCore.Core.Service
{
    [PluginFamily("Default")]
    public interface ITestService
    {
        string GetTestDataAndValidate();
    }
}
IpswitchftCore/Core/Service/Impl/TestService.cs
using Ipswitchft.IpswitchftCore.Core.DataAccess;
using StructureMap;
 
namespace Ipswitchft.IpswitchftCore.Core.Service.Impl
{
    [Pluggable("Default")]
    public class TestService : ITestService
    {
        private ITestRepository testRepository;
 
        public TestService()
        {
            testRepository = ObjectFactory.GetInstance<ITestRepository>();
        }
 
        public string GetTestDataAndValidate()
        {
            return testRepository.GetData();
        }
    }
}
IpswitchftWeb/TestString.aspx.cs
using System;
using Ipswitchft.IpswitchftWeb.Interface;
using Ipswitchft.IpswitchftWeb.Presenter;
 
namespace Ipswitchft.IpswitchftWeb
{
    public partial class TestString : System.Web.UI.Page, ITestString
    {
        private TestStringPresenter _presenter;
 
        protected override void OnInit(EventArgs e)
        {
            _presenter = new TestStringPresenter();
            _presenter.Init(this);
        }
 
        public void ShowString(string message)
        {
            lblString.Text = message;
        }
    }
}
IpswitchftWeb/Presenter/TestStringPresenter.cs
using Ipswitchft.IpswitchftCore.Core.Service;
using Ipswitchft.IpswitchftWeb.Interface;
using StructureMap;
 
namespace Ipswitchft.IpswitchftWeb.Presenter
{
    public class TestStringPresenter
    {
        private ITestString _view;
        private ITestService _testService;
 
        public void Init(ITestString view)
        {
            _view = view;
            _testService = ObjectFactory.GetInstance<ITestService>();
            _view.ShowString(_testService.GetTestDataAndValidate());
        }
    }
}
IpswitchftWeb/Interface/ITestString.cs
namespace Ipswitchft.IpswitchftWeb.Interface
{
    public interface ITestString
    {
        void ShowString(string message);
    }
}

Tags: , , , , ,

Dec 15 2009

Add Log4net .dll to your projects for easy logging and optimal error handling

Category: ASP.NETryancmartin1976 @ 20:55

First Strategy:

Second Strategy:

Building your own logging framework can be time consuming and a waste of time because log4net already did it for you.

STEP 1

Download the dll and config from there site: http://logging.apache.org/log4net/download.html

STEP 2

Drop the dll and the config file into your bin directory and add a reference to the dll from Visual Studio project.

STEP 3

Add a Log directory under your root directory

STEP 4

Add this code, preferably to your Data Access or Service layer and name it Log.cs:

using System;
using System.Collections.Generic;
using System.IO;
using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Layout;
 
public static class Log
{
    private static Dictionary<Type, ILog> _loggers = new Dictionary<Type, ILog>();
    private static bool _logInitialized = false;
    private static object _lock = new object();
 
    public static string SerializeException(Exception e)
    {
        return SerializeException(e, string.Empty);
    }
 
    private static string SerializeException(Exception e, string exceptionMessage)
    {
        if (e == null) return string.Empty;
 
        exceptionMessage = string.Format(
            "{0}{1}{2}\n{3}",
            exceptionMessage,
            (exceptionMessage == string.Empty) ? string.Empty : "\n\n",
            e.Message,
            e.StackTrace);
 
        if (e.InnerException != null)
            exceptionMessage = SerializeException(e.InnerException, exceptionMessage);
 
        return exceptionMessage;
    }
 
    private static ILog getLogger(Type source)
    {
        lock (_lock)
        {
            if (_loggers.ContainsKey(source))
            {
                return _loggers[source];
            }
 
            ILog logger = LogManager.GetLogger(source);
            _loggers.Add(source, logger);
            return logger;
        }
    }
 
    public static void Debug(object source, object message)
    {
        Debug(source.GetType(), message);
    }
 
    public static void Debug(Type source, object message)
    {
        getLogger(source).Debug(message);
    }
 
    public static void Info(object source, object message)
    {
        Info(source.GetType(), message);
    }
 
    public static void Info(Type source, object message)
    {
        getLogger(source).Info(message);
    }
 
    public static void Warn(object source, object message)
    {
        Warn(source.GetType(), message);
    }
 
    public static void Warn(Type source, object message)
    {
        getLogger(source).Warn(message);
    }
 
    public static void Error(object source, object message)
    {
        Error(source.GetType(), message);
    }
 
    public static void Error(Type source, object message)
    {
        getLogger(source).Error(message);
    }
 
    public static void Fatal(object source, object message)
    {
        Fatal(source.GetType(), message);
    }
 
    public static void Fatal(Type source, object message)
    {
        getLogger(source).Fatal(message);
    }
 
    public static void Debug(object source, object message, Exception exception)
    {
        Debug(source.GetType(), message, exception);
    }
 
    public static void Debug(Type source, object message, Exception exception)
    {
        getLogger(source).Debug(message, exception);
    }
 
    public static void Info(object source, object message, Exception exception)
    {
        Info(source.GetType(), message, exception);
    }
 
    public static void Info(Type source, object message, Exception exception)
    {
        getLogger(source).Info(message, exception);
    }
 
    public static void Warn(object source, object message, Exception exception)
    {
        Warn(source.GetType(), message, exception);
    }
 
    public static void Warn(Type source, object message, Exception exception)
    {
        getLogger(source).Warn(message, exception);
    }
 
    public static void Error(object source, object message, Exception exception)
    {
        Error(source.GetType(), message, exception);
    }
 
    public static void Error(Type source, object message, Exception exception)
    {
        getLogger(source).Error(message, exception);
    }
 
    public static void Fatal(object source, object message, Exception exception)
    {
        Fatal(source.GetType(), message, exception);
    }
 
    public static void Fatal(Type source, object message, Exception exception)
    {
        getLogger(source).Fatal(message, exception);
    }
 
    private static void initialize()
    {
        string logFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log4Net.config");
        if (!File.Exists(logFilePath))
            logFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"bin\Log4Net.config");
 
        XmlConfigurator.ConfigureAndWatch(new FileInfo(logFilePath));
    }
 
    public static void EnsureInitialized()
    {
        if (!_logInitialized)
        {
            initialize();
            _logInitialized = true;
        }
    }
}

STEP 5

Add a global.asax file and add this code to it

protected void Application_Start(object sender, EventArgs e)
        {
            Log.EnsureInitialized();
        }

STEP 6

Invoke an error and log it!

public string GetTestDataAndValidate()
        {
            try
            {
                string returnData = testRepository.GetData();
                if (string.IsNullOrEmpty(returnData))
                    Log.Warn(this, "there should be data coming back");
                else if (returnData.Contains("error"))
                    Log.Error(this, returnData);
                return returnData;
            }
            catch (Exception ex)
            {
                Log.Fatal(this, ex.InnerException);
                return "";
            }
        }

STEP 7

That's it! Done! Go see the error log results for yourself. If everything was configured correctly you should have an error log in your Logs directory under the root directory in your web application.

You should play around with the Log4Net.config file until you get the results your looking for.

<?xml version="1.0" encoding="utf-8"?>
<log4net debug="false">
  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
    <file type="log4net.Util.PatternString" value="Logs/log.xml" />
    <appendToFile value="true" />
    <datePattern value="yyyyMMdd" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="1000KB" />
    <layout type="log4net.Layout.XmlLayoutSchemaLog4j">
      <locationInfo value="true" />
    </layout>
  </appender>
  <root>
    <level value="DEBUG" />
    <appender-ref ref="RollingFileAppender" />
  </root>
  <logger name="StructureMap" additivity="false">
    <level value="WARN"/>
    <appender-ref ref="OutputDebugStringAppender" />
    <appender-ref ref="ConsoleAppender" />
  </logger>
  <logger name="NHibernate" additivity="false">
    <level value="INFO"/>
    <appender-ref ref="AspNetTraceAppender" />
  </logger>
</log4net>

Tags: , , , , ,