I have log4net implemented in a Visual Studio 2010 VB.NET Windows service. It used to work, but not anymore.
I have a sub RunTasks that gets started by the service every minute.
When I debug this procedure using a console project in the same solution, the logging works. However when I install the service and run it, and debug it using VS by attaching to the process, I found out that IsInfoEnabled, IsDebugEnabled, IsErrorEnabled etc. are all set to false, and I guess that's why the logging is not working, although RunTasks is executed by the service.
I have the following class, if I understand things right the XMLConfigurator is started before GetLogger.
Imports System.Reflection
<Assembly: log4net.Config.XMLConfigurator(ConfigFile:="LogConfig.xml", Watch:=True)>
Public NotInheritable Class Logging
Private Shared _LogName As String
Private Shared _ilog As log4net.ILog
Private Sub New()
End Sub
Public Shared ReadOnly Property ILog() As log4net.ILog
Get
If _ilog Is Nothing Then
_ilog = log4net.LogManager.GetLogger(LogName)
End If
Return _ilog
End Get
End Property
Private Shared ReadOnly Property LogName() As String
Get
If _LogName = "" Then
'If GetType(MySettings).GetProperty("LogName") IsNot Nothing Then
' _LogName = GetType(MySettings).GetProperty("LogName").GetValue(MySettings.Default, Nothing)
'End If
If _LogName = "" Then _LogName = "DefaultLogger"
End If
Return _LogName
End Get
End Property
End Class
The logging itself looks like this:
ILog.Info("Starting RunTasks ... ")
And here is my LogConfig.xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<log4net>
<appender name="textfileAppender" type="log4net.Appender.RollingFileAppender">
<file value="myLogFile.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="3" />
<maximumFileSize value="100KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{yyyy-MM-dd HH:mm:ss} %-5level - %message%newline" />
</layout>
</appender>
<logger name="DefaultLogger">
<level value="ALL" />
<appender-ref ref="textfileAppender" />
</logger>
</log4net>
</configuration>
I found the answer myself, I had to move the following line of code:
<Assembly: log4net.Config.XMLConfigurator(ConfigFile:="LogConfig.xml", Watch:=True)>
... (see first code block above) to the AssemblyInfo.vb of the solutions startup project. XMLConfigurator has to be executed before GetLogger is.
Related
I have to write Groovy script log in to a text file, I am able to write request and response of any Soap step using context.expand.
To write test request and response I am using:
def request = context.expand('${SoapRequest#Request}')
new File ("D:/RequestFile.txt").write(request)
What I want is to save the log output in a file:
Suggest me a way to write Groovy script log in a text file.
Config way log4j.xml
There is already a file for Groovy log configured in SOAPUI log4j configuration file.
In SOAPUI_HOME\bin\soapui-log4j.xml:
<appender name="GLOBAL_GROOVY_LOG" class="org.apache.log4j.FileAppender">
<errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
<param name="File" value="${soapui.logroot}global-groovy.log"/>
<param name="Threshold" value="DEBUG"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<logger name="groovy.log">
<level value="INFO" />
<appender-ref ref="GLOBAL_GROOVY_LOG" />
</logger>
A possible way is to add another custom FileAppender in this config file. If you change this file remember to restart SOAPUI in order that it can load the changes.
Something like this can do the trick:
<appender name="GLOBAL_GROOVY_LOG" class="org.apache.log4j.FileAppender">
<errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
<param name="File" value="${soapui.logroot}global-groovy.log"/>
<param name="Threshold" value="DEBUG"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<appender name="MYLOG_CUSTOM" class="org.apache.log4j.FileAppender">
<errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
<param name="File" value="/absoultePath/yourlogFile.txt"/>
<param name="Threshold" value="DEBUG"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<logger name="groovy.log">
<level value="INFO" />
<appender-ref ref="GLOBAL_GROOVY_LOG" />
<appender-ref ref="MYLOG_CUSTOM" />
</logger>
Dinamically using Groovy
However it seems that you want to do it dynamically using Groovy script, hence you can use the follow code to get <logger name="groovy.log"> and add a FileAppender to it; in order that you can save the logs in a custom file:
import org.apache.log4j.Logger
import org.apache.log4j.PatternLayout
import org.apache.log4j.RollingFileAppender
// get the groovy logger by name
def groovyLogger = Logger.getLogger('groovy.log')
// pattern Layout
PatternLayout layout = new PatternLayout("%d{ISO8601} [%t] %-5p %c %x - %m%n")
// create a file appender
RollingFileAppender fileAppender = new RollingFileAppender(layout, "/absolutePath/myLog.txt")
groovyLogger.addAppender(fileAppender)
log.info 'someText to the logger'
NOTE: If you don't use an absolute path in FileAppender the log file is saved relative to *SOAPUI_HOME\bin*
When you configure this the rest of logs in Groovy testSteps will be appended to this file. If you want to get only the log for a specific Groovy testStep then you can simply remove the appender at the end of the script:
groovyLogger.removeAppender(fileAppender);
UPDATE:
From you comment: I want to store output for each run, and if I am executing this again it should rewrite the file.
So you want to store output for each run... but you want to overwrite the file if you execute again? This is contradictory isn't?
If you want to overwrite the file instead of append the content you can use setAppend(false):
fileAppender.setAppend(false)
fileAppender.activateOptions()
groovyLogger.addAppender(fileAppender)
I created a web service project that uses Log4Net to log to the event viewer and optionally to a .log file. Everything works great on my machine, when I try to deploy it on another machine it won't even log to the text file or the event viewer. The fact that it's not even writing to the text file makes me think it's not able to find the log4net.dll or something to that effect?
I'm also receiving an error message when it hits the noted line below in my global.asax:
log4net:ERROR XmlConfigurator: Failed to find configuration section 'log4net' in the application's .config file. Check your .config file for the and elements. The configuration section should look like:
section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /
I'm stumped, I have no idea why this isn't working, help!
Ran an exe compiled from the following code that adds the source to the eventlog in Windows, like I said, works fine on my machine:
Option Explicit On
Option Strict On
Imports System
Imports System.Diagnostics
Imports System.Threading
Module Module1
Sub Main()
If Not EventLog.SourceExists("LendingService") Then
EventLog.CreateEventSource("LendingService", "Application")
Console.WriteLine("Creating Event Source: LendingService")
Else
Console.WriteLine("LendingService events already defined to this system.")
End If
End Sub
End Module
Web.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="ACEConfigFileFullPath" value="C:\somepath\Bin\ACEFile.xml" />
<add key="ILConfigFileFullPath" value="C:\somepath\Bin\IL.xml"/>
<add key="log4net.Config" value="log4net.config"/>
<add key="log4net.Config.Watch" value="True"/>
</appSettings>
<connectionStrings/>
<system.web>
<!--
Visual Basic options:
Set strict="true" to disallow all data type conversions
where data loss can occur.
Set explicit="true" to force declaration of all variables.
-->
<compilation debug="true" strict="false" explicit="true" targetFramework="4.0"/>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Windows"/>
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<clear/>
<add namespace="System"/>
<add namespace="System.Collections"/>
<add namespace="System.Collections.Generic"/>
<add namespace="System.Collections.Specialized"/>
<add namespace="System.Configuration"/>
<add namespace="System.Text"/>
<add namespace="System.Text.RegularExpressions"/>
<add namespace="System.Linq"/>
<add namespace="System.Xml.Linq"/>
<add namespace="System.Web"/>
<add namespace="System.Web.Caching"/>
<add namespace="System.Web.SessionState"/>
<add namespace="System.Web.Security"/>
<add namespace="System.Web.Profile"/>
<add namespace="System.Web.UI"/>
<add namespace="System.Web.UI.WebControls"/>
<add namespace="System.Web.UI.WebControls.WebParts"/>
<add namespace="System.Web.UI.HtmlControls"/>
</namespaces>
</pages>
<identity impersonate="true" />
</system.web>
</configuration>
log4net.config:
</configSections>--> Yes it still works on mine with this commented out.
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<param name="ApplicationName" value="Lending Service" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message %newline %exception" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO"/>
<levelMax value="FATAL"/>
</filter>
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<threshold value="FATAL"/>
<file value="webLog.log"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="5"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline%exception"/>
</layout>
</appender>
<root>
</root>
<logger name="LendingService.Global_asax">
<appender-ref ref="RollingFileAppender"/>
<appender-ref ref="EventLogAppender" />
</logger>
<logger name="LendingService.LendingService">
<appender-ref ref="RollingFileAppender"/>
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
AssemblyInfo.vb:
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
<Assembly: log4net.Config.XmlConfigurator(ConfigFile:="log4net.config", Watch:=True)>
Global.asax:
Imports System.Web.SessionState
Imports IntelliLenderBUClasses
Public Class Global_asax
Inherits System.Web.HttpApplication
'Public objApplicant As New IntelliLenderBUClasses.ApplicantBU
Private Shared ReadOnly log As log4net.ILog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType)
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
' Fires when the application is started
'ACE
Dim sACEPath As String
sACEPath = System.Configuration.ConfigurationManager.AppSettings("ACEConfigFileFullPath")
AceClientNet.BaseConfig.InitializeBU(sACEPath)
'IL
Dim sILPath As String
sILPath = System.Configuration.ConfigurationManager.AppSettings("ILConfigFileFullPath")
IntelliLenderBUClasses.BUBaseConfig.InitializeBU(sILPath)
'LOGGING
log4net.Config.XmlConfigurator.Configure() 'Error message happening here
log.Info("LendingService Application Started")
End Sub
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
' Fires when the session is started
End Sub
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
' Fires at the beginning of each request
End Sub
Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
' Fires upon attempting to authenticate the use
End Sub
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Fires when an error occurs
Dim sendString As String = sender.ToString
log.Error("LendingService Application Error: " & Server.GetLastError.Message)
End Sub
Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
' Fires when the session ends
End Sub
Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
' Fires when the application ends
log.Info("LendingService Application Ending")
End Sub
End Class
You are looking for you configuration in your app.config file. To change this you can use:
// Configure log4net using the .log4net file
[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)]
// This will cause log4net to look for a configuration file
// called TestApp.exe.log4net in the application base
// directory (i.e. the directory containing TestApp.exe)
// The config file will be watched for changes.
or
log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)]
as reference:
// Configure log4net using the .config file
[assembly: log4net.Config.XmlConfigurator(Watch=true)]
// This will cause log4net to look for a configuration file
// called TestApp.exe.config in the application base
// directory (i.e. the directory containing TestApp.exe)
// The config file will be watched for changes.
I am able to use a Logback PropertyDefiner to access a single property from a logback.xml configuration file. If I have 3 properties to access, I am currently using 3 separate implementations of PropertyDefiner (one for each property).
Is there a way to access multiple properties from a single PropertyDefiner implementation? Or perhaps there is another interface that supports multiple properties?
I want to be be able to use properties to plugin different values, based on environment (dev, ist, uat, perf, prod) for various logging configurations (context name, log levels, appender file names, file sizes, etc.).
I found this question, which is similar, but did not answer the question of how to access multiple properties.
Create a PropertyDefiner implementation class. The PropertyDefinerBase implementation is already provided.
package foo.bar;
import java.util.HashMap;
import java.util.Map;
import ch.qos.logback.core.PropertyDefinerBase;
public class LoggingPropertiesDefiner extends PropertyDefinerBase {
private static Map<String, String> properties = new HashMap<>();
static {
properties.put("encoderPattern", "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %message%n");
properties.put("maxFileSize", "50MB");
properties.put("rootLogLevel", "INFO");
}
private String propertyLookupKey;
public void setPropertyLookupKey(String propertyLookupKey) {
this.propertyLookupKey = propertyLookupKey;
}
#Override
public String getPropertyValue() {
//TODO In the real world, get properties from a properties loader.
return properties.get(propertyLookupKey);
}
}
In the logback.xml, use the same PropertyDefiner class for each property. Provide a different lookup key for each:
<define name="encoderPattern" class="foo.bar.LoggingPropertiesDefiner">
<propertyLookupKey>encoderPattern</propertyLookupKey>
</define>
<define name="maxFileSize" class="foo.bar.LoggingPropertiesDefiner">
<propertyLookupKey>maxFileSize</propertyLookupKey>
</define>
<define name="rootLogLevel" class="foo.bar.LoggingPropertiesDefiner">
<propertyLookupKey>rootLogLevel</propertyLookupKey>
</define>
Reference the property names in the logback.xml:
<root level="${rootLogLevel}">
<appender-ref ref="FILE"/>
</root>
You could use the property resource support from logback
logback.properties
mode=prod
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
<property resource="logback.properties" />
<if condition='property("mode").equals("prod")'>
<then>
<include file="logback-prod.xml" />
</then>
</if>
<if condition='property("mode").equals("dev")'>
<then>
<include resource="logback-dev.xml" />
</then>
</if>
</configuration>
logback-prod.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--Daily rolling file appender -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${MYAPP_HOME}/myApp.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>myApp.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>2</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</Pattern>
</layout>
</appender>
<root level="ERROR">
<appender-ref ref="file" />
</root>
</configuration>
logback-dev.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--Daily rolling file appender -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${MYAPP_HOME}/myApp.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>myApp.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>2</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</Pattern>
</layout>
</appender>
<root level="TRACE">
<appender-ref ref="file" />
</root>
</configuration>
More detailed explaination here.
Does that help to resolve your problem?
I have log file location in web.config as follows.
<appSettings>
<add key="LogPath" value="D:\Service\"/>
</appSettings>
I have log4net config in web.config as follows
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="%property{LogName}"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%m%n"/>
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="RollingLogFileAppender"/>
</root>
</log4net>
Initialized GetLogger at the top of the Service class as follows
Private Shared ReadOnly log As ILog = LogManager.GetLogger(GetType(Service))
I have created GlobalContext property for LogName as follows
log4net.GlobalContext.Properties("LogName") = ConfigurationManager.AppSettings("LogPath") & "Service." & Format(Now, "ddMMyyyy") & ".txt"
Logging is done with log.Info as follows
log.Info(strComments)
In this scenario, the log file is created as "null" under Project folder and logging the details.
I want the log location to be "D:\Service\Service.30082012.txt" according to the code above.
What am I missing? Please help me out.
Typically I separate the log4net configuration from my web.config to avoid web application restarts ( How to prevent an ASP.NET application restarting when the web.config is modified? ) when you change the web.config file.
I usually just have a log4net.config file to store all of these settings and I configure it to watch the config file for changes:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
Also I'm not quite sure why you are storing your log file directory outside of the log4net configuration unless it's just easier for you to modify. I typically keep the path in the log4net config like so:
<appender name="File" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="${ALLUSERSPROFILE}/CompanyName/Logs/ApplicationName/%date{MM-dd-yyyy} - Whatever.log" />
Make sure you don't have any log commands before you set the LogName property.
Also check that logname is being set correctly ie, check that
ConfigurationManager.AppSettings("LogPath") & "Service." & Format(Now, "ddMMyyyy") & ".txt"
is not evalulating to null
I have a WCF service with two methods, Ping and PutAddress. Ping works fine, but PutAddress was failing to initialize NHibernate correctly. Narrowing down the issue, I realized that the relevant settings from Web.config were not being read by PutAddress.
Strangely, Ping does have access to the settings from Web.config. I removed all of the NHibernate code and boiled it down to just trying to read the settings. Ping is able to read the settings (returns non-null, values in result are correct) while PutAddress' result is null.
Again, NHibernate is now completely out of the picture. Both methods simply try to read the relevant settings from Web.config. Ping succeeds while PutAddress fails.
Any thoughts?
Interface:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string Ping();
[OperationContract]
Address PutAddress(Address address);
}
Implementation:
public class MyService : IMyService
{
public string Ping()
{
NHibernate.Cfg.ConfigurationSchema.HibernateConfiguration result =
(NHibernate.Cfg.ConfigurationSchema.HibernateConfiguration)
System.Configuration.ConfigurationManager.GetSection("hibernate-configuration");
if (result == null)
{
System.Diagnostics.Debugger.Break(); // Does NOT break, "Pong" returned
}
return "Pong";
}
public Address PutAddress(Address address)
{
NHibernate.Cfg.ConfigurationSchema.HibernateConfiguration result =
(NHibernate.Cfg.ConfigurationSchema.HibernateConfiguration)
System.Configuration.ConfigurationManager.GetSection("hibernate-configuration");
if (result == null)
{
System.Diagnostics.Debugger.Break(); // Breaks, result is null
}
return address; // Return version potentially modified with DB-assigned ID
}
}
EDIT:
Here is the (sanitized) Web.config
<?xml version="1.0"?>
<configuration>
<configSections>
<!-- NHibernate Section -->
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler,NHibernate"/>
<!-- Log4Net Section -->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<!-- NHibernate Configuration -->
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">
NHibernate.Dialect.MySQLDialect
</property>
<property name="connection.provider">
NHibernate.Connection.DriverConnectionProvider
</property>
<property name="connection.driver_class">
NHibernate.Driver.MySqlDataDriver
</property>
<property name="connection.connection_string">
Server=localhost;Database=DB;User ID=USER;Password=PASS
</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
<property name="show_sql">true</property>
<mapping assembly="MyService"/>
</session-factory>
</hibernate-configuration>
<!-- Log4Net Configuration -->
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender, log4net">
<layout type="log4net.Layout.PatternLayout, log4net">
<param name="ConversionPattern" value="%d %p %m%n"/>
</layout>
</appender>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="log.txt"/>
<param name="AppendToFile" value="true"/>
<param name="DatePattern" value="yyyy.MM.dd"/>
<layout type="log4net.Layout.PatternLayout,log4net">
<conversionPattern value="%d %p %m%n"/>
</layout>
</appender>
<root>
<priority value="DEBUG"/>
<appender-ref ref="ConsoleAppender"/>
</root>
<logger name="NHibernate" additivity="false">
<level value="WARN"/>
<appender-ref ref="RollingFile"/>
<appender-ref ref="ConsoleAppender"/>
</logger>
<logger name="NHibernate.SQL" additivity="false">
<level value="ALL"/>
<appender-ref ref="RollingFile"/>
<appender-ref ref="ConsoleAppender"/>
</logger>
</log4net>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Found the problem - one call was from a Unit Test that I hand-coded, which uses MyServiceClient that was generated by Visual Studio when I added a Service Reference. The other call was from a unit test that was created by the Visual Studio (2010) Unit Test wizard, which just instantiated MyService as an object. The VS-generated unit test was running in-process as a result.
I had an odd problem myself. I could not return "DataTable" objects from a WCF operation. I wonder if there could be a problem with returning an "Address" object from a WCF operation as well.
I don't know the complete answer to your question, but I would suggest the following
In your code for PutAddress, try replacing Address PutAddress(Address address); with string PutAddress(Address address); and replace return address; with return "Pong"
By doing so, you will ascertain the flow of execution through your code. Make sure that you are actually breaking and returning null as opposed to returning a null value of address.
If the new code returns null, then you are in fact having trouble reading from the file. I suspect that it will actually return "Pong", indicating that your code is returning Address, which somehow contains null because of WCF weirdness.