wtorek, 29 kwietnia 2008

System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.

Error:
Unable to connect to the remote server.
System.Net.Sockets.SocketException: Only one usage of each socket address
(protocol/network address/port) is normally permitted.

Scenario:
1. I had a web service proxy, generated automatically from the CrmServiceWsdl.wsdl file of the Microsoft Dynamics CRM 4.0.
2. I was loading a big amount of data to the CRM via the web services.
3. In the middle of the load I was gettingthe following error:
Unable to connect to the remote server
System.Net.Sockets.SocketException: Only one usage of each socket address
(protocol/network address/port) is normally permitted.

Reason:
Every time I was invoking a method of the web service, the proxy generated a new connection even tough I was using the default setting keep-alive. The new connection was being prepared because of the need to authenticate each request. The old connections were hanging on (240 seconds) before timing out. It can be seen with the netstat –n command. There were so many connections that it was not possible to a make a new connection.

Solution:
I simply turned off the keep-alive for the web service proxy. I had the Reference.cs file generated automatically and I did not want to change this file. I prepared a new file with the partial class implementation and the overridden GetWebRequest method.

Sample code of the partial class:
namespace Crm40
{
using System.Diagnostics;
using System.Web.Services;
using System.ComponentModel;
using System.Web.Services.Protocols;
using System;
using System.Xml.Serialization;

public partial class CrmService :
System.Web.Services.Protocols.SoapHttpClientProtocol
{
protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
System.Net.HttpWebRequest webRequest =
(System.Net.HttpWebRequest)base.GetWebRequest(uri);

webRequest.KeepAlive = false;

webRequest.ProtocolVersion = System.Net.HttpVersion.Version10;
return webRequest;
}
}
}


However I think I had already met the same issue a long time ago, I resolved it once again ;)

środa, 9 kwietnia 2008

Szybki start z log4net (Quick start with log4net)

Szybkie podłączenie i konfiguracja log4net dla aplikacji w .Net framework 2.0, 3.0, 3.5 w 5 krokach:
(Very short tutorial of connecting and configuring the log4net quickly for the .Net framework 2.0, 3.0, 3.5 in 5 steps:)

1. Skąd log4net? (Where to get the log4net from?)
Ściągnij wersję log4net z logging.apache.org/log4net. Po rozpakowaniu pliku incubating-log4net-1.2.10.zip z katalogu log4net-1.2.10/bin/net/2.0/release dodaj plik log4net.dll do GAC (c:\Windows\assembly).
(Download the log4net from logging.apache.org/log4net. After extracting the archive incubating-log4net-1.2.10.zip from the folder log4net-1.2.10/bin/net/2.0/release add the file log4net.dll to the GAC (c:\Windows\assembly).

2. Referencja do assembly (Assembly reference)
Do projektu w Visual Studio dodaj referencje do log4net (Menu lokalne na projekcie, opcja Add Reference).
(To the Visual Studio Project add a new reference to the log4net (Local menu over the project, option Add Reference))

3. Plik konfiguracyjny dla log4net (Configuration file for the log4net)
Do folderu aplikacji dodaj plik log4net.config z poniższą (przykładową) zawartością:
(To the application folder add a new file log4net.config with the following, sample content:)

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<root>
<level value="DEBUG" />
<appender-ref ref="FileAppender" />
</root>

<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<encoding value="unicodeFFFE" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern
value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>


</log4net>


4. log4net.config do aplikacji .Net (log4net.config to the .Net application)
Do pliku AssemlbyInfo.cs dodaj: (To the AssemblyInfo.cs file add the following lines:)

[assembly: log4net.Config.XmlConfigurator(ConfigFile =
"Log4Net.config", Watch = true)]


5. Użycie (The use)
Do klasy dodaj deklarację: (Add the following declaration to the class:)

public class Foo
{
private static readonly ILog logger = LogManager.GetLogger(typeof(Foo));
...
}

lub bardziej uniwersalną ale dłuższą: (or more universal but longer:)

public class Foo
{
private static readonly ILog logger = LogManager.GetLogger(
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
...
}

i wywołaj poniższy kod aby zalogować: (and call the following code to log:)

logger.Debug("zapisz ten tekst");
logger.Info("zapisz ten tekst");
logger.Warn("zapisz ten tekst");
logger.Error("zapisz ten tekst");
logger.Fatal("zapisz ten tekst");


Do sprawdzenia jaki jest obecnie ustawiony poziom logowania, żeby uniknąć niepotrzebnych obliczeń jeśli ich wyniki są logowane, mamy: (To check what is the current level of logging, to avoid unnecessary counting if its results are being logged, we may use:)

logger.IsDebugEnabled;
logger.IsInfoEnabled;
logger.IsWarnEnabled;
logger.IsErrorEnabled;
logger.IsFatalEnabled;

Rezultat
W pliku log-file.txt znajdziesz: (In the log-file.txt you will find:)

2008-04-09 08:26:51,646 [1] DEBUG Program [(null)] - zapisz ten tekst

Podsumowanie: (Summary:)
Jest to tylko krótki opis jak szybko uruchomić log4net w jakiejkolwiek aplikacji c#. Więcej opcji i szczegółów można znaleźć na stronach: (This is only a short description how to start using the log4net quickly in any c# application. More options and details may be found on the following websites:)
Wstęp do log4net
Więcej Appenderów do logowania, m.in. (More appenders for logging, i.e.) ConsoleAppender i EventLogAppender