How to log communication of a WebService running on IIS 6.0? - asp.net

I'm running an ASP.NET WebService on IIS 6.0 that shows a lot of HTTP 500 (probably just exceptions from the WebService) inside the log at %systemroot%\System32\LogFiles\W3SVC1 on a customers site.
Is it possible to log the content of those HTTP responses and there requests without modifying the WebService using IIS or a plug-in for IIS?
I thought of using Wireshark or Fiddler to sniff on the HTTP traffic but I would prefer to just turn on an option inside IIS to make him log the communication (this should not be to hard since it is logging the requested URLs anyway)

We've done this before using log4net. Here are the high level steps:
Create a log4net section in your web.config
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
and...
...
</system.web>
<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="c:\mysvc.log" />
<param name="AppendToFile" value="true" />
<param name="MaxSizeRollBackups" value="10" />
<param name="MaximumFileSize" value="1000000" />
<param name="RollingStyle" value="Size" />
<param name="StaticLogFileName" value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<!-- Setup the root category, add the appenders and set the default priority -->
<root>
<level value="DEBUG" />
<!--<priority value="DEBUG" />-->
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
...
In your Global.asax.cs call the log4net Configure()
protected void Application_Start(Object sender, EventArgs e)
{
log4net.Config.DOMConfigurator.Configure();
}
At the top of your web service .cs file, declare an instance of a log4net ILog
public class MyService : System.Web.Services.WebService {
{
private static readonly ILog log = LogManager.GetLogger(typeof(MyService));
In your web service methods, trap exceptions and log them
[WebMethod]
public void DoSomething()
{
try
{
// business logic
}
catch(Exception ex)
{
log.Error("Something bad happened", ex);
throw;
}
}
After these steps, in the example above any exceptions will appear in c:\mysvc.log

Create an HTTPModule and configure it in your ASP.NET configuration. You don't need to modify the existing Web Service's code (you needn't even have the sources), you just configure the HTTPModule in your Web.config.
In the HTTPModule, listen for events such as BeginRequest and EndRequest and you should be able to log the input to, and output from, the web service.
If you need to trap exceptions thrown in the web service, you could capture the Error event as described here and here.
Update:
According to this page, you can't use the Error event approach with web services as web service errors don't get routed to the Error event. Microsoft suggests that you use SOAP Extensions to log web service errors.

Related

CORS and Preflight (OPTIONS) response codes in case of authorization error

In a Preflight request wich codes should I use for authorization errors?
I mean, I can have 2 different unauthorized error:
User can't run a preflight (OPTIONS method is handled - so I think I should not use 405 - but user is not authorized to ask for OPTIONS)
User does not have the rights to call the requested method (specified by Access-Control-Request-Method)
I had a similar setup that was showing 405 errors and 500 errors as I was attempting to get CORS running on my web service. My fix basically needed a response.End() call if the Request was the pre-flight OPTIONS method. The web.config web handlers found in the CORS documentation was fine, as long as the OPTIONS was included in the list of allowed calls. I did NOT need to move any of the customer handlers into code.
Basically, my fix/setup includes this ONE MAJOR FIX in my ApplicationOnBeginRequest handler:
private void ApplicationOnBeginRequest( object sender, EventArgs eventArgs )
{
...
if ( context.Request.HttpMethod == "OPTIONS" )
response.End();
}
and these handlers in my web.config:
<system.webServer>
<!--Other handlers/modules ...-->
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Allow-Headers" value="Content-Type,Accept" />
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>

Log4net not working in IIS7 on windows server 2008

Logs are not created on the server (Windows 2008) and IIS7. I had given absolute path as well as relative path.
I had given all rights to the log folder. I had included network user, IUsr and IIS_IUSRS, and gave permission to every one. also.
It is not writing logs to that folder
the entries on the web config is as follows
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
<log4net>
<logger name="GeneralLogger">
<level value="ALL" />
<appender-ref ref="RollingFile" />
</logger>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="C:\\vhosts\\staging.customerportal.com\\log\\CustomerPortal.log"/>
<appendToFile value="true"/>
<datePattern value="yyyyMMdd"/>
<rollingStyle value="Date"/>
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true"/>
<levelMin value="DEBUG"/>
<levelMax value="FATAL"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d %5rms %X{addr} %-22.22c{1} %-18.18M - %m%n"/>
</layout>
</appender>
</log4net>
I had tried giving single slash and well as double slash in the file value in web config nothing works.
The code in the global.asax.cs is
public class MvcApplication : System.Web.HttpApplication
{
private static log4net.ILog log = log4net.LogManager.GetLogger(typeof(MvcApplication));
protected void Application_Start()
{
log4net.Config.XmlConfigurator.Configure();
}
code in assemblyinfo.cs is
[assembly: XmlConfigurator(ConfigFile="web.config", Watch=true)]
I had tried with this code and also without this code in assemblyinfo.cs
It is not working.
Where as When I use absolute path in localhost the logs are written to that folder properly
It fails on the server
I had tried both these options in the controller file
//private static log4net.ILog log =
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType) ;
private static log4net.ILog log = log4net.LogManager.GetLogger("GeneralLogger");
I had tried a path which does not exists, it did not created folder.
Please help me. Please help me how to enable logs using log4net in server
You are initializing your logger before configuring the logmanager (actually you configuring it twice) by calling the Configure on Application_Start.
Option 1:
public class MvcApplication : System.Web.HttpApplication
{
private static log4net.ILog log = log4net.LogManager.GetLogger(typeof(MvcApplication));
protected void Application_Start()
{
//Remove: log4net.Config.XmlConfigurator.Configure();
}
And keep:
[assembly: XmlConfigurator(ConfigFile="web.config", Watch=true)]
Option 2:
public class MvcApplication : System.Web.HttpApplication
{
private static log4net.ILog log;
protected void Application_Start()
{
log4net.Config.XmlConfigurator.Configure();
log = log4net.LogManager.GetLogger(typeof(MvcApplication));
}
And remove:
//Remove: [assembly: XmlConfigurator(ConfigFile="web.config", Watch=true)]

Log4net in a web service

I basically have the same question as
log4net only works when XmlConfigurator.Configure() is called
However, I couldn't comment there as I don't have any reputation (just signed up).
Thanks for any helpful comments.
If I do anything wrong here, please advise.
Thank you very much. Bernd
Update:
Thanks for constructive hints. I've have made some progress and therefore will explain in more detail:
I use log4net within a (VS generated C# web service). I do get the debug information in the debug file, however within VS (2012) I do get the message for every logging call:
log4net:ERROR An exception ocurred while retreiving stack frame information.
System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
bei log4net.Core.StackFrameItem..ctor(StackFrame frame)
I configured it via XML:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="Logs/debug.log" />
<encoding value="utf-8" />
<appendToFile value="true" />
<maximumFileSize value="10MB" />
<maxSizeRollBackups value="2" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level (%class#%method:%line):%message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingFile" />
</root>
</log4net>
My web service looks like this:
public class ObjectInfo : IObjectInfo
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public void DoWork() {
Logging.LoggingUtil.InitializeLogging();
log.Debug("Some message");
}
}
Hope this is quite sufficient. The LoggingUtil- class basically looks like this:
private const String Log4NetConfigurationFilePath = "log4net-config.xml"; //real path looks somewhat different
public static void InitializeLogging()
{
XmlConfigurator.Configure(new FileInfo(Log4NetConfigurationFilePath));
}
I wonder, if the problem is that the stack trace cannot be found out within Cassine as Microsoft doesn't allow this in order to protect their implementation of the web service?
As explained in LOG4NET-393, this error occurs when there is a dynamic method in the call chain.
There they claim to have this error fixed in versions > 1.2.12.

Background Application in AppHarbor and Logentries

Now I've a web application and 3 background application in AppHarbor .
I want to use logentries to log each app in different location.
based on logentries docs for AppHarbor https://logentries.com/doc/appharbor/ the token keys are read from web.config and app.config [configuration vars] enforced by appharbor.
How can I configure each application to log in different log location (eg. Appharbor/Website, AppHarbor/Console1, AppHarbor/Console2)?
You can override the config vars injected by AppHarbor by specifying the Token in the appender/target definition. Not sure which framework you're using but if its NLog then
where you have this line in your web/app.config
<target name="logentries" type="Logentries" debug="true"
layout="${date:format=ddd MMM dd} ${time:format=HH:mm:ss} ${date:format=zzz yyyy} ${logger} : ${LEVEL}, ${message}"/>
Add token="abc" so that you have this:
<target name="logentries" type="Logentries" debug="true" token="abc"
layout="${date:format=ddd MMM dd} ${time:format=HH:mm:ss} ${date:format=zzz yyyy} ${logger} : ${LEVEL}, ${message}"/>
And then if you're using the log4net plugin, where you have this section:
<appender name="LeAppender" type="log4net.Appender.LogentriesAppender, LogentriesLog4net">
<Debug value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d{ddd MMM dd HH:mm:ss zzz yyyy} %logger %: %level%, %m" />
</layout>
</appender>
Add so that you have this:
<appender name="LeAppender" type="log4net.Appender.LogentriesAppender, LogentriesLog4net">
<Debug value="true" />
<Token value="abc" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d{ddd MMM dd HH:mm:ss zzz yyyy} %logger %: %level%, %m" />
</layout>
</appender>
Token values set here will take precedence over those injected by Appharbor, so for each app that has its own web/app.config you can enter your own token using this method.
I Found that I can set the token in runtime by below lines :
private static readonly ILog log = log4net.LogManager.GetLogger(typeof(Program));
appender = (LogentriesAppender)log.Logger.Repository.GetAppenders()[0];
appender.Token = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
//now log method will use my token
log.Info("Hello World");

ASP.NET Web.config CustomErrors not working for the webservice

I have a simple webservice with two webmethods.
https://localhost/Sub/WS/Dash.asmx/test_error_methodnameXXXXXXXXXXX
When i call the above request from the browser. It gives me a error message saying something like this:-
System.InvalidOperationException: test_error_methodnameXXXXXXXXXXX Web
Service method name is not valid. at
System.Web.Services.Protocols.HttpServerProtocol.Initialize() at
System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type,
HttpContext context, HttpRequest request, HttpResponse response,
Boolean& abortProcessing)
I tried to make a work around with the help of web.config file as follows:-
<system.web>
<customErrors mode="On" defaultRedirect="~/Sub/ErrorPage/AppErrors.aspx">
<error statusCode="500" redirect="500.aspx" />
</customErrors>
</system.web>
Here in this case, the redirection is not happening to the 500.aspx page or the AppErrors.aspx.
I can see the change happening, if i change the value in the mode attribute..
Thanks.
I found the fix with the help of web.config.
Stick
<diagnostics suppressReturningExceptions="true"/>
To call web methods for javascript you should mark your webservice as a script service.
[ScriptService]
public class MyService : WebService
{
}
Include a reference to it in script manager:
<asp:ScriptManager ID="_scriptManager" runat="server">
<Services>
<asp:ServiceReference Path="Dash.asmx" />
</Services>
</asp:ScriptManager>
Call it in js
try {
Dash.MyService.ErrorMethodName();
}
catch(exception){
//handle exception
}
finally {
//round up
}

Resources