Вы не можете получить доступ к информации об исключении, если канал расположен. Поэтому прекрасная конструкция using
не рекомендуется при доступе к службе WCF. Фактически, свойства Exception требуют наличия доступа к каналу для извлечения некоторой информации об исключении (не знаю, пропустила ли MS эту точку или имеются технические причины).
Я написал небольшой класс для упрощения вызова прокси-серверов WCF (этот сайт помогает мне понять проблему и написать класс):
using System;
using System.ServiceModel;
namespace Utility
{
public class ServiceHelper
{
/// <summary>
/// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service
/// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda.
/// </summary>
/// <typeparam name="TService">The type of the service to use</typeparam>
/// <param name="action">Lambda of the action to performwith the service</param>
[System.Diagnostics.DebuggerStepThrough]
public static void UsingProxy<TService>(Action<TService> action)
where TService : ICommunicationObject, IDisposable, new()
{
var service = new TService();
bool success = false;
try
{
action(service);
if (service.State != CommunicationState.Faulted)
{
service.Close();
success = true;
}
}
finally
{
if (!success)
{
service.Abort();
}
}
}
/// <summary>
/// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service
/// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda.
/// </summary>
/// <typeparam name="TIServiceContract">The type of the service contract to use</typeparam>
/// <param name="action">Action to perform with the client instance.</param>
/// <remarks>In the configuration, an endpoint with names that maches the <typeparamref name="TIServiceContract"/> name
/// must exists. Otherwise, use <see cref="UsingContract<TIServiceContract>(string endpointName, Action<TIServiceContract> action)"/>. </remarks>
[System.Diagnostics.DebuggerStepThrough]
public static void UsingContract<TIServiceContract>(Action<TIServiceContract> action)
{
UsingContract<TIServiceContract>(
typeof(TIServiceContract).Name,
action
);
}
/// <summary>
/// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service
/// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda.
/// </summary>
/// <typeparam name="TIServiceContract">The type of the service contract to use</typeparam>
/// <param name="action">Action to perform with the client instance.</param>
/// <param name="endpointName">Name of the endpoint to use</param>
[System.Diagnostics.DebuggerStepThrough]
public static void UsingContract<TIServiceContract>(
string endpointName,
Action<TIServiceContract> action)
{
var cf = new ChannelFactory<TIServiceContract>(endpointName);
var channel = cf.CreateChannel();
var clientChannel = (IClientChannel)channel;
bool success = false;
try
{
action(channel);
if (clientChannel.State != CommunicationState.Faulted)
{
clientChannel.Close();
success = true;
}
}
finally
{
if (!success) clientChannel.Abort();
}
}
}
}
Тогда вы можете просто сделать что-то вроде этого (в зависимости от того, есть ли у вас сервисная справка или контракты:
ServiceHelper.UsingContract<IFxCurveService>(svc=>
{
guid = svc.ReserveSnapshot(fxCurveKey);
DiscountFactorNew[] dfs = svc.GetDiscountFactors(guid, dates, from));
Assert.IsTrue(guid != null);
}),
Этот помощник обеспечивает правильное закрытие каналов без их утилизации. Тогда вы сможете увидеть фактическое исключение. Отредактируйте свое сообщение, когда найдете фактическое исключение.
(Возможно, ваша фабрика обслуживания уже использует эту технику. Если нет, не стесняйтесь обновлять ее, как мой класс).
[править] Вам все равно придется поиграть с конфигом. вот, вероятно, рабочий конфиг для вас:
contract="The.Correct.Namespace.IFxCurveService"
name="IFxCurveService" />