У меня есть проект (бэкэнд), в котором он получает вызов на уровне сервиса, но он также выполняет вызовы другого API на бизнес-уровне.
Я добавил поведение к этим вызовам, поэтому мне не нужно вносить изменения в несколько мест в моем коде.
My Behaviour.config (импорт - ExternalDependencyBehavior):
<?xml version="1.0" encoding="utf-8"?>
<behaviors>
<endpointBehaviors>
<!-- SPECIFIC BEHAVIOR EXTENSION FOR JSON URL DESERIALIZER-->
<behavior name="ServiceRESTBehavior">
<ConverterWebHttpBehaviourExtension />
</behavior>
<behavior name="ServiceSOAPBehavior" />
<behavior name="ExternalDependencyBehavior">
<ExternalClientBehavior/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="DefaultBehaviour">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Мой код: (один метод на бизнес-уровне, который вызывает другой внешний API)
protected virtual Vendor.Sinacofi.SinacofiService.RespuestaSNPV1201 RequestToVendor(VendorWebService vendor, string clientFiscalId, BasicSearchCriterion criteria)
{
Vendor.Sinacofi.SinacofiService.RespuestaSNPV1201 result = new Vendor.Sinacofi.SinacofiService.RespuestaSNPV1201();
string errorLogProvider = null;
try
{
using (Vendor.Sinacofi.SinacofiService.SNPV1201SoapClient client = new Vendor.Sinacofi.SinacofiService.SNPV1201SoapClient())
{
/*Credentials*/
result = client.ConsultaRutificacion(
client.ClientCredentials.HttpDigest.ClientCredential.UserName,
client.ClientCredentials.HttpDigest.ClientCredential.Password,
clientFiscalId,
criteria.Value
);
}
return result;
}
catch (AxrException)
{
throw;
}
catch (FaultException fex)
{
this.logProvider.WriteInErrorMode(GetType().Name, MethodBase.GetCurrentMethod().Name, fex);
throw this.exceptionProvider.Create(ErrorCode.---------, ExceptionType.BUSINESS, fex);
}
catch (Exception ex)
{
this.logProvider.WriteInErrorMode(GetType().Name, MethodBase.GetCurrentMethod().Name, ex);
throw this.exceptionProvider.Create(ErrorCode.-------------, ExceptionType.BUSINESS, ex);
}
}
В итоге:
Когда я приеду на звонок:
"Client.ConsultaRutification"
Мое поведение выполняется, я добавляю код (2 файла):
using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace SIPE.Search.Helpers
{
/// <summary>
/// Implements methods that can be used to extend run-time behavior for an endpoint in either a client application.
/// </summary>
public class ExternalClientBehavior : BehaviorExtensionElement
{
protected override object CreateBehavior()
{
return new ExternalClientBehaviorClass();
}
public override Type BehaviorType
{
get
{
return typeof(ExternalClientBehaviorClass);
}
}
/// <summary>
/// JSON REST[GET] Converter Behavior
/// </summary>
private class ExternalClientBehaviorClass : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
ExternalClientMessageInspector clientInspector = new ExternalClientMessageInspector(endpoint);
clientRuntime.MessageInspectors.Add(clientInspector);
foreach (ClientOperation op in clientRuntime.Operations)
{
op.ParameterInspectors.Add(clientInspector);
}
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new ExternalClientMessageInspector(endpoint));
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
}
}
И файл два:
namespace SIPE.Search.Helpers
{
/// <summary>
/// Intercepts send requests.
/// </summary>
public class ExternalClientMessageInspector : IClientMessageInspector, IParameterInspector, IErrorHandler
{
private ServiceEndpoint Endpoint { get; set; }
Dictionary<string, object> inputsParam;
public ExternalClientMessageInspector(ServiceEndpoint endpoint)
{
//empty
}
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
((Dictionary<string, string>)(System.Web.HttpContext.Current.Items[operationName])).Add("OutputParam", JsonConvert.SerializeObject(returnValue));
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
//code not necessary
}
public object BeforeCall(string operationName, object[] inputs)
{
// code not neccesary
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
Message copy = buffer.CreateMessage(); // Create a copy to work with
request = buffer.CreateMessage(); // Restore the original message
return copy.GetReaderAtBodyContents().Name;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
// no implement
}
public bool HandleError(Exception error)
{
// no implement
return true;
}
public void NotifyError()
{
}
}
}
Мне нужно иметь возможность фиксировать ошибки (например, 404 и другие) моих вызовов в моем поведении.
Я попытался добавить несколько интерфейсов, но безуспешно
Ошибка фиксируется перехватом метода RequestToVendor, который находится на бизнес-уровне.
Но мне нужно уметь это запечатлеть в своем поведении.
спасибо