středa 19. října 2016

.NET and Windows proxy problems

Windows has two HTTP APIs, which are unfortunatelly not 100% compatible in case of proxy settings:
  • WinINet, used by Internet Explorer and most of the Windows C/C++ applications. Window proxy settings dialog sets the proxy for the WinINet
  • WinHTTP used by .NET.
So, when you develop a .NET application, is may happen that on a certain computer the Internet Explorer and other apps are connecting well, while your .NET app cannot connect to the Internet.
Since some proxy settings are hidden to the user by the "Automatically detect settings"checkbox, I have made a simple program WinProxyViewer, which may be run with a inexperienced user and the result sent to the application authors.

Default Credentials


.NET does not pick up the proxy credentials entered in the Windows proxy settings, e.g. see this StackOverflow thread. One solution is to add to the application config:

<system .net="">
  <defaultproxy usedefaultcredentials="true" />
</system>
But I preffer the solution in the code (at least for the desktop apps):
try
{
    System.Net.IWebProxy proxy = System.Net.WebRequest.DefaultWebProxy;
    PropertyInfo propInfo = proxy.GetType().GetProperty("WebProxy", BindingFlags.NonPublic | BindingFlags.Instance);
    ((System.Net.WebProxy)propInfo.GetValue(proxy)).UseDefaultCredentials = true;
}
catch (Exception ex)
{
    // log the exception
}


More proxies


The automatic proxy script for the WinINet may contain more proxy servers. The WinINet chooses next cycle the list until it finds the first proxy working. While the .NET (WinHTTP) use the first proxy from the list always, event when it does not work. So the .NET app may be disconnected, while the Internet Explorer is working. There is not known remedy for that. Fortunately, such situations are very rare.

NTLM proxy


.NET (WinHTTP) cannot automatically detect NTLM proxy and use Window credentials for it like the WinINet. There is not known remedy for that. NTLM proxies are sometimes used in the enterpise environments.

Summary


.NET app cannot be 100% compatible with all the Windows proxy settings. A possible solution for that is to have own proxy settings in the app. But the app may be used by people who cannot (security or have no knowledge) to set the proxy settings in the .NET app. So they may be situations, when .NET stays disconnected.

čtvrtek 19. května 2016

Atlassian Bamboo and xUnit testing

I needed to run xUnit test on the Atlassian Bamboo Cloud (OnDemand) build server. It has no runner for xUnit, but can be run from the command line by xunit.runner.console.

Configure your build server


On the build server, just NuGet the runner:
nuget.exe xunit.runner.console
The Bamboo cannot parse xUnit output. It can handle the nUnit output nd the xUnit has an option to print results in the nUnit format. So, create a simple xunit.cmd script:
@echo off
@rem xunit runner for Bamboo

if "%2"=="" (
  echo Usage: test.dll report.xml
  exit /b 1
)

if not exist %~dp2 mkdir %~dp2

"c:\path\to\xunit.runner.console.2.1.0\tools\xunit.console.exe" %1 -nunit %2

Configure Bamboo


Then go to your Bamboo Administration - Agents Summary and choose your agent. Add a new capability:
Capability typeExecutable
Executable labelxUnit
Pathc:\path\to\xunit.cmd

To add the xUnit to you plan's job, just add the Command task after the project build (e.g. MSBuild, or NAnt). I expect you have a module MyProjectTests in your solution. Then configure the xUnit task:
ExecutablexUnit
Argumentbin\Release\MyProjectTests.dll test-reports\MyProjectTests.xml
Working sub directoryMyProjectTests

The final trick is to add the NUnit Parser task, just take care to put is as the final task:
NUnit Test Results File/DirectoryMyProjectTests/test-reports/*.xml

The bamboo logic is, that:
  1. Any task fails, and no test result is found, it assumes the compilation error has occurred.
  2. Any task fails, and a test result is found, it assumes a test has failed.
  3. All tasks pass, the build is OK. If the test results are found, they are picked up.

pátek 18. března 2016

C# Caliburn.Micro Check Unmatched Elements

Caliburn.Micro is a great C# MVVM framework. It saves the developer's fingers with the binding by the x:Name convention:
<textbox x:name="Username" />
However, when one mistypes the x:Name or rename the property in the ViewModel then the Caliburn silently does not apply the binding. Such mistakes are hard to track. Fortunately Caliburn comes with the help of ViewModelBinder.HandleUnmatchedElements. We have a simple rule in the project: if the x:Name starts with the capital letter, then it has to be binded by the Caliburn. Then I have been able to plug in a simple method to check for unmathched elements starting with the capital:
ViewModelBinder.HandleUnmatchedElements = (elems, type) =>
{
    if (!elems.Any())
        return;

    // elems with Name with the first letter upper case
    elems = elems.Where(e => !string.IsNullOrEmpty(e.Name) && e.Name.StartsWith(e.Name.Substring(0, 1).ToUpperInvariant()));
    if (!elems.Any())
        return;

    throw new InvalidOperationException(type + " contains Caliburn unmatched elements " + string.Join(",", elems.Select(e => e.Name)));
};