I have a simple WCF service but when I try to open it in the browser I get this error:
Composition proxy target must implement at least one interface
Markup code
<%# ServiceHost Language="C#" Debug="true" Service="Mvm.SATWeb.ServicesLiquidez.Service.WSRiesgoLiquidez" Factory="Spring.ServiceModel.Activation.ServiceHostFactory" CodeBehind="WSRiesgoLiquidez.svc.cs" %>
IWSRiesgoLiquidez.cs
namespace Mvm.SATWeb.ServicesLiquidez.Service
{
// NOTE: If you change the interface name "IWSEnvioTerceros" here, you must also update the reference to "IWSEnvioTerceros" in Web.config.
[ServiceContract]
interface IWSRiesgoLiquidez
{
[OperationContract]
ResultadoOperacionLiquidez consultaIngresosEgresosPuntosDeAtencion(string USUARIO, string CLAVE, string CODIGORED, string FECHA, string HORAINICIAL, string HORAFINAL);
[OperationContract]
ResultadoOperacionLiquidez consultaValorRealPuntoDeAtencion(string USUARIO, string CLAVE, string CODIGORED, string CODIGOPUNTOATENCION);
[OperationContract]
ResultadoOperacionLiquidez consultaValorRealPorPuntosDeatencion(string USUARIO, string CLAVE, string CODIGORED);
}
}
The implementation: WSRiesgoLiquidez.cs
namespace Mvm.SATWeb.ServicesLiquidez.Service
{
public class WSRiesgoLiquidez : IWSRiesgoLiquidez
{
public ResultadoOperacionLiquidez consultaIngresosEgresosPuntosDeAtencion(string USUARIO, string CLAVE, string CODIGORED, string FECHA, string HORAINICIAL, string HORAFINAL)
{
ResultadoOperacionLiquidez respuesta = new ResultadoOperacionLiquidez();
IServicioMaestros ServicioMaestros = SATWebServiceLocator<IServicioMaestros>.ObtenerServicio();
try
{
using (var riesLiq = new Mvm.SATWeb.ServicesLiquidez.Comun.BusinessDelegate.RiesgoLiqBD())
{
// respuesta.Retorno = riesLiq.consultaIngresosEgresosPuntosDeAtencion(HORAINICIAL, HORAFINAL);
//EnvioTO objLiq = riesLiq.consultaIngresosEgresosPuntosDeAtencion(HORAINICIAL, HORAFINAL);
respuesta = riesLiq.consultaIngresosEgresosPuntosDeAtencion(HORAINICIAL, HORAFINAL);
respuesta.EjecucionExitosa = true;
}
}
catch (Exception ex)
{
respuesta.EjecucionExitosa = false;
respuesta.MensajeValidacion = RemoveLocalizationString(ex.Message);
}
return respuesta;
}
public ResultadoOperacionLiquidez consultaValorRealPuntoDeAtencion(string USUARIO, string CLAVE, string CODIGORED, string CODIGOPUNTOATENCION)
{
ResultadoOperacionLiquidez respuesta = new ResultadoOperacionLiquidez();
return respuesta;
}
public ResultadoOperacionLiquidez consultaValorRealPorPuntosDeatencion(string USUARIO, string CLAVE, string CODIGORED)
{
ResultadoOperacionLiquidez respuesta = new ResultadoOperacionLiquidez();
return respuesta;
}
private string RemoveLocalizationString(string p)
{
string strMensaje = String.Empty;
strMensaje = p.Replace("[", "").Replace(", es-CO]", "");
return strMensaje;
}
}
}
Then in my web.config I have:
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<!-- ConfiguraciĆ³n de spring con los servicios Web -->
<spring>
<context>
Servicios de seguridad, logging, multilenguaje, etc.
<resource uri="~/Servicios/Infraestructura.config" />
La declaracion de los servicios de negocio (Los BO)
<resource uri="~/Servicios/ServiciosNegocio.config" />
</context>
</spring>
On ServiciosNegocios.config I have
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
<description>Declaracion de objetos de negocio</description>
<!--Objetos de negocio - Seguridad-->
<object id="SATWebSeguridadTarget" type="Mvm.SATWeb.Core.Seguridad.Modelo.Negocio.ServicioSeguridad, Mvm.SATWeb.Core">
</object>
<!--Proxy - Seguridad-->
<object id="SATWebSeguridadService"
type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="target">
<ref object="SATWebSeguridadTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>MethodInterceptor</value>
</list>
</property>
</object>
<object id="Mvm.SATWeb.ServicesLiquidez.Service.WSRiesgoLiquidezTarget"
type="Mvm.SATWeb.ServicesLiquidez.Service.WSRiesgoLiquidez, Mvm.SATWeb.ServicesLiquidez">
</object>
<object id="Mvm.SATWeb.ServicesLiquidez.Service.WSRiesgoLiquidez"
type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="target">
<ref object="Mvm.SATWeb.ServicesLiquidez.Service.WSRiesgoLiquidezTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>MethodInterceptor</value>
</list>
</property>
</object>
</objects>
And Infraestructure.config
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
<description>Declaracion e integracion de servicios de infraestructura.</description>
<!-- AOP Advices -->
<object id="MethodInterceptor" type="Mvm.SATWeb.Core.Comun.AOP.MethodInterceptor, Mvm.SATWeb.Core" />
<!-- Servicio SIDUtil -->
<object id="UtilService" type="Mvm.SATWeb.ServicesLiquidez.Comun.Helpers.SATWebUtil, Mvm.SATWeb.ServicesLiquidez">
</object>
<!-- configuracion de mensajes -->
<object id="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core">
<property name="ResourceManagers">
<list>
<value>Resources.Mensajes, App_GlobalResources</value>
</list>
</property>
</object>
<object id="LocalizacionLenguajeService"
type="Mvm.Localizacion.Lenguaje.ClientAPI.LenguajeServiceSpringResx, Mvm.Localizacion.Lenguaje.ClientAPI">
</object>
</objects>
The detailed error is this:
Composition proxy target must implement at least one interface.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.ArgumentException: Composition proxy target
must implement at least one interface.
Source Error:
An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of
the exception can be identified using the exception stack trace below.
Stack Trace:
[ArgumentException: Composition proxy target must implement at least
one interface.]
Spring.Proxy.CompositionProxyTypeBuilder.BuildProxyType() +125
Spring.ServiceModel.Support.ServiceProxyTypeBuilder.BuildProxyType()
+41 Spring.ServiceModel.SpringServiceHost.CreateServiceType(String serviceName, IApplicationContext applicationContext) +173
Spring.ServiceModel.SpringServiceHost..ctor(String serviceName,
IApplicationContext applicationContext, Uri[] baseAddresses) +43
Spring.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(String
reference, Uri[] baseAddresses) +141
System.ServiceModel.HostingManager.CreateService(String
normalizedVirtualPath) +693
System.ServiceModel.HostingManager.ActivateService(String
normalizedVirtualPath) +42
System.ServiceModel.HostingManager.EnsureServiceAvailable(String
normalizedVirtualPath) +479
Related
My application is running on a Windows server in the intra net. Application URL is like this: win_serv/APP_DIR/. And webserwice.asmx URL is a "win_serv/APP_DIR/webservice.asmx"
Public application URL is like this: app.domain.com (APP_DOMAIN) and public Webservice.asmx URL is like this APP_DOMAIN/webservice.asmx.
In this configuration auto generated discovery XML (APP_DOMAIN/webservice.asmx?disco) is like this:
<?xml version="1.0" encoding="utf-8"?>
<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/">
<contractRef ref="http://APP_DOMAIN/APP_DIR/webservice.asmx?wsdl" docRef="http://APP_DOMAIN/APP_DIR/webservice.asmx" xmlns="http://schemas.xmlsoap.org/disco/scl/" />
<soap address="http://APP_DOMAIN/APP_DIR/webservice.asmx" xmlns:q1="http://NAMESPACE/" binding="q1:WebServiceSoap" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
<soap address="http://APP_DOMAIN/APP_DIR/webservice.asmx" xmlns:q2="http://NAMESPACE/" binding="q2:WebServiceSoap12" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
</discovery>
So I used class SoapExtensionReflector:
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
foreach (Service service in description.Services)
{
foreach (Port port in service.Ports)
{
foreach (ServiceDescriptionFormatExtension extension in port.Extensions)
{
SoapAddressBinding binding = extension as SoapAddressBinding;
if (null != binding)
{
binding.Location = ConfigurationManager.AppSettings["SoapAddress"]; //http://APP_DOMAIN/webservice.asmx
}
}
}
}
}
But this solution fixes only soap address is valid (http://APP_DOMAIN/webservice.asmx). WSDL URL is still invalid (http://APP_DOMAIN/APP_DIR/webservice.asmx?wsdl). Discovery looks like this:
<?xml version="1.0" encoding="utf-8"?>
<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/">
<contractRef ref="http://APP_DOMAIN/APP_DIR/webservice.asmx?wsdl" docRef="http://APP_DOMAIN/APP_DIR/webservice.asmx" xmlns="http://schemas.xmlsoap.org/disco/scl/" />
<soap address="http://APP_DOMAIN/webservice.asmx" xmlns:q1="http://NAMESPACE/" binding="q1:WebServiceSoap" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
<soap address="http://APP_DOMAIN/webservice.asmx" xmlns:q2="http://NAMESPACE/" binding="q2:WebServiceSoap12" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
</discovery>
How to fix wsdl URL?
p.s. sorry for my english
New to programming and getting this error.
I have no idea Please Help.
this is my save button click and my configuration file.
private void save_Click(object sender, EventArgs e)
{
Details d =new Details();
d.Firstname = firstname.Text;
Configuration cfg=new Configuration();
cfg.Configure("NHibernate.xml");
ISessionFactory sessionfactory = cfg.BuildSessionFactory();
ISession session = sessionfactory.OpenSession();
ITransaction tx = session.BeginTransaction();
session.Save(d);
tx.Commit();
}
My Configuration File Nhibernate.xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler,NHibernate"/>
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">
NHibernate.Connection.DriverConnectionProvider
</property>
<property name="dialect">
NHibernate.Dialect.MySQLDialect,Nhibernate
</property>
<property name="connection.connection_string_name">
Server=localhost;Database=mohit;User ID=root;Password=root
</property>
<mapping assembly="TestNhibernate"/>
</session-factory>
</hibernate-configuration>
</configuration>
please help
You can use either this name="connection.connection_string":
<session-factory>
...
<property name="connection.connection_string">
Server=localhost;Database=mohit;User ID=root;Password=root
</property>
Or the name="connection.connection_string_name" with the <connectionStrings> configuration:
// another web.config section "<connectionStrings>"
<connectionStrings>
<add name="MyName"
connectionString="Server=localhost;Database=mohit;User ID=root;Password=root" />
</connectionStrings>
// here we reference the name defined in the other section
<session-factory>
...
<property name="connection.connection_string_name">MyName</property>
when i run the application i get "No persister for Test.Student" Error
I am new in Nhibernate Mapping ,i can't figure this out
How can i solve ?? plz help
NHibernate Configuration part
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">
NHibernate.Connection.DriverConnectionProvider
</property>
<property name="connection.driver_class">
NHibernate.Driver.SqlClientDriver
</property>
<property name="connection.connection_string">
Server=(local);database=Student;Integrated Security=SSPI;
</property>
<property name="dialect">
NHibernate.Dialect.MsSql2005Dialect
</property>
<!--<property name="proxyfactory.factory_class">
NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernates
</property>-->
<property name="show_sql">
false
</property>
</session-factory>
Main Program
program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
namespace Test
{
class Program
{
static void Main(string[] args)
{
ISessionFactory factor = new Configuration().Configure().BuildSessionFactory();
if(factor!=null){
Console.WriteLine("Configured");
}
else{
Console.WriteLine("Not Configured");
}
Student std = new Student { Fname = "James", Lname = "Bond", Address = "32 Baker Street", Institution = "MIT" };
using (ISession session = factor.OpenSession())
{
using (ITransaction transaction= session.BeginTransaction())
{
try
{
session.Save(std);
transaction.Commit();
session.Close();
}
catch(Exception e)
{
Console.WriteLine("ERROR :" + e);
}
}
}
}
//protected ISessionFactory factory;
protected void execute_query()
{
}
}
}
Mapping part
Student.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="Test.Student" table="Info" lazy="true">
<id name="Id" type="int" column="Id">
<generator class="native" />
</id>
<property name="Fname" column ="Fname"/>
<property name="Lname" column="Lname"/>
<property name="Address" column="Address"/>
<property name="Institution" column="Institution"/>
<!-- We don't have to specify a column name if its the same
as the variable name -->
You need to add mapping assembly name in your app.config file as described here.
<property name="show_sql">false</property>
<mapping assembly="Test"/> <!-- Here -->
</session-factory>
Also make sure to mark the XML file as Embedded Resource if haven't.
I'm trying to log the requests and responses (the raw XML SOAP envelope) between a console application developed by me and a specific third party remote SOAP web service to database for audit purposes, and I can't find a way to do it.
Ideally what I'd like to do is getting the request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:SayHello>
<tem:name>Albireo</tem:name>
</tem:SayHello>
</soapenv:Body>
</soapenv:Envelope>
and the response
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<SayHelloResponse xmlns="http://tempuri.org/">
<SayHelloResult>Hello, Albireo.</SayHelloResult>
</SayHelloResponse>
</s:Body>
</s:Envelope>
and save them in the database.
So far every tutorial on the net I found boils down to two approaches, the SoapExtension method and the tracing method.
The SoapExtension method
The SoapExtension method is based on the SOAP Message Modification Using SOAP Extensions guide, in this method you create a class inheriting from SoapExtension and hook it in the application's configuration, the class' ProcessMessage method will allow you to intercept the SOAP messages.
This is an example of the class inherited from SoapExtension:
namespace Playground.Client
{
using System;
using System.Web.Services.Protocols;
public class SoapLogger : SoapExtension
{
public override object GetInitializer(System.Type serviceType)
{
throw new NotImplementedException();
}
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
throw new NotImplementedException();
}
public override void Initialize(object initializer)
{
throw new NotImplementedException();
}
public override void ProcessMessage(SoapMessage message)
{
throw new NotImplementedException();
}
}
}
And this is how it is wired in the configuration:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IGreeterService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8080/greeter"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IGreeterService"
contract="Services.IGreeterService"
name="BasicHttpBinding_IGreeterService" />
</client>
</system.serviceModel>
<system.web>
<webServices>
<soapExtensionTypes>
<add group="0"
priority="1"
type="Playground.Client.SoapLogger" />
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
The problem with this method is it seems to work only for web applications, trying to implement it in a console application yield no result.
The tracing method
The tracing method is based upon the Configuring Message Logging guide, in this method you enable .NET's tracing for every SOAP/WCF communication in the application and dump the log somewhere (more information on the configuration can be found in Recommended Settings for Tracing and Message Logging).
This is an example of the tracing configuration:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5" />
</startup>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
propagateActivity="true"
switchValue="Verbose, ActivityTracing">
<listeners>
<add initializeData="ServiceModel.svclog"
name="ServiceModel"
type="System.Diagnostics.XmlWriterTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add initializeData="MessageLogging.svclog"
name="MessageLogging"
type="System.Diagnostics.XmlWriterTraceListener" />
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IGreeterService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8080/greeter"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IGreeterService"
contract="Services.IGreeterService"
name="BasicHttpBinding_IGreeterService" />
</client>
<diagnostics>
<endToEndTracing activityTracing="true"
messageFlowTracing="true"
propagateActivity="true" />
<messageLogging logEntireMessage="true"
logKnownPii="true"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true" />
</diagnostics>
</system.serviceModel>
</configuration>
The content of ServiceModel.svclog and MessageLogging.svclog can be found in a GitHub's Gist as it's too big to fit here.
The problem with this method is it logs every SOAP/WCF message in the application and it seems the generated logs are not really useful, they contains loads of informations and I can't understand if and how filter only what I'm interested in, the only practical way to read them seems to be Microsoft's Service Trace Viewer.
I've tried to add a custom TraceListener too:
namespace Playground.Client
{
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Linq;
public class CustomTraceListener : TraceListener
{
public override void Write(string message)
{
File.AppendAllLines("CustomTraceListener.txt", new[] { message });
}
public override void WriteLine(string message)
{
message = this.FormatXml(message);
File.AppendAllLines("CustomTraceListener.txt", new[] { message });
}
private string FormatXml(string message)
{
using (var stringWriter = new StringWriter())
{
var xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Encoding = Encoding.UTF8;
xmlWriterSettings.Indent = true;
xmlWriterSettings.OmitXmlDeclaration = true;
using (var xmlTextWriter = XmlWriter.Create(stringWriter, xmlWriterSettings))
{
XDocument.Parse(message).Save(xmlTextWriter);
}
return Convert.ToString(stringWriter);
}
}
}
}
But even though it allows me to intercept the messages, it doesn't save any metadata:
<MessageLogTraceRecord Time="2013-07-16T10:50:04.5396082+02:00" Source="ServiceLevelSendRequest" Type="System.ServiceModel.Channels.BodyWriterMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<HttpRequest>
<Method>POST</Method>
<QueryString></QueryString>
<WebHeaders>
<VsDebuggerCausalityData>uIDPo4bOsuSXlSVEkmfof4AP2psAAAAAlEIoNto3KEWKgCnIGryjp9f3wbRlp+ROhY9Oy6bed/cACQAA</VsDebuggerCausalityData>
</WebHeaders>
</HttpRequest>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IGreeterService/SayHello</Action>
<ActivityId CorrelationId="964a7c4f-3b18-4b5d-8085-e00ae03b58d1" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">80101cc1-dfb5-4c8e-8d19-ec848ab69100</ActivityId>
</s:Header>
<s:Body>
<SayHello xmlns="http://tempuri.org/">
<name>Albireo</name>
</SayHello>
</s:Body>
</s:Envelope>
</MessageLogTraceRecord>
<MessageLogTraceRecord Time="2013-07-16T10:50:04.6176897+02:00" Source="TransportSend" Type="System.ServiceModel.Channels.BodyWriterMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<Addressing>
<Action>http://tempuri.org/IGreeterService/SayHello</Action>
<To>http://localhost:8080/greeter</To>
</Addressing>
<HttpRequest>
<Method>POST</Method>
<QueryString></QueryString>
<WebHeaders>
<VsDebuggerCausalityData>uIDPo4bOsuSXlSVEkmfof4AP2psAAAAAlEIoNto3KEWKgCnIGryjp9f3wbRlp+ROhY9Oy6bed/cACQAA</VsDebuggerCausalityData>
</WebHeaders>
</HttpRequest>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ActivityId CorrelationId="964a7c4f-3b18-4b5d-8085-e00ae03b58d1" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">80101cc1-dfb5-4c8e-8d19-ec848ab69100</ActivityId>
</s:Header>
<s:Body>
<SayHello xmlns="http://tempuri.org/">
<name>Albireo</name>
</SayHello>
</s:Body>
</s:Envelope>
</MessageLogTraceRecord>
With this information it's impossible to rebuild the request/response flow as all the messages are mixed together.
Compare them to the *.svclog generated by the native XmlWriterTraceListener:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2013-07-16T08:50:04.6176897Z" />
<Source Name="System.ServiceModel.MessageLogging" />
<Correlation ActivityID="{80101cc1-dfb5-4c8e-8d19-ec848ab69100}" />
<Execution ProcessName="Playground.Client" ProcessID="4348" ThreadID="1" />
<Channel />
<Computer>ESP-DEV-9</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<MessageLogTraceRecord Time="2013-07-16T10:50:04.6176897+02:00" Source="TransportSend" Type="System.ServiceModel.Channels.BodyWriterMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<Addressing>
<Action>http://tempuri.org/IGreeterService/SayHello</Action>
<To>http://localhost:8080/greeter</To>
</Addressing>
<HttpRequest>
<Method>POST</Method>
<QueryString></QueryString>
<WebHeaders>
<VsDebuggerCausalityData>uIDPo4bOsuSXlSVEkmfof4AP2psAAAAAlEIoNto3KEWKgCnIGryjp9f3wbRlp+ROhY9Oy6bed/cACQAA</VsDebuggerCausalityData>
</WebHeaders>
</HttpRequest>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ActivityId CorrelationId="964a7c4f-3b18-4b5d-8085-e00ae03b58d1" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">80101cc1-dfb5-4c8e-8d19-ec848ab69100</ActivityId>
</s:Header>
<s:Body>
<SayHello xmlns="http://tempuri.org/">
<name>Albireo</name>
</SayHello>
</s:Body>
</s:Envelope>
</MessageLogTraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2013-07-16T08:50:04.6957712Z" />
<Source Name="System.ServiceModel.MessageLogging" />
<Correlation ActivityID="{80101cc1-dfb5-4c8e-8d19-ec848ab69100}" />
<Execution ProcessName="Playground.Client" ProcessID="4348" ThreadID="1" />
<Channel />
<Computer>ESP-DEV-9</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<MessageLogTraceRecord Time="2013-07-16T10:50:04.6801549+02:00" Source="TransportReceive" Type="System.ServiceModel.Channels.BufferedMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<HttpResponse>
<StatusCode>OK</StatusCode>
<StatusDescription>OK</StatusDescription>
<WebHeaders>
<Content-Length>207</Content-Length>
<Content-Type>text/xml; charset=utf-8</Content-Type>
<Date>Tue, 16 Jul 2013 08:50:04 GMT</Date>
<Server>Microsoft-HTTPAPI/2.0</Server>
</WebHeaders>
</HttpResponse>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header></s:Header>
<s:Body>
<SayHelloResponse xmlns="http://tempuri.org/">
<SayHelloResult>Hello, Albireo.</SayHelloResult>
</SayHelloResponse>
</s:Body>
</s:Envelope>
</MessageLogTraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
Here the <Correlation ActivityID="{80101cc1-dfb5-4c8e-8d19-ec848ab69100}" /> tag establishes a relation between each request and response, allowing a developer to rebuild the whole session.
Is there a way to accomplish what I'm trying to do?
If the service is registered as a WCF web-service (not as an old-school ASMX web-service) it's possible to do it through IClientMessageInspector and IEndpointBehavior.
First you have to create a class inheriting from IClientMessageInspector that will handle the logging of both the requests and the replies.
namespace Playground.Sandbox
{
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
public class MyClientMessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(
ref Message request,
IClientChannel channel)
{
// TODO: log the request.
// If you return something here, it will be available in the
// correlationState parameter when AfterReceiveReply is called.
return null;
}
public void AfterReceiveReply(
ref Message reply,
object correlationState)
{
// TODO: log the reply.
// If you returned something in BeforeSendRequest
// it will be available in the correlationState parameter.
}
}
}
Then you have to create a class inheriting from IEndpointBehavior that will register the inspector in the client.
namespace Playground.Sandbox
{
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
public class MyEndpointBehavior : IEndpointBehavior
{
public void Validate(
ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(
ServiceEndpoint endpoint,
BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(
ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{
}
public void ApplyClientBehavior(
ServiceEndpoint endpoint,
ClientRuntime clientRuntime)
{
var myClientMessageInspector = new MyClientMessageInspector();
clientRuntime.ClientMessageInspectors.Add(myClientMessageInspector);
}
}
}
Then when you want to use the behavior you can manually register it before using the service.
namespace Playground.Sandbox
{
public static class Program
{
public static void Main()
{
using (var client = new MyWcfClient())
{
var myEndpointBehavior = new MyEndpointBehavior();
client.Endpoint.Behaviors.Add(myEndpointBehavior);
// TODO: your things with the client.
}
}
}
}
If you don't want to register the behavior manually or you need it to be always active, you can register it in the configuration file.
First you need to create a class inheriting from BehaviorExtensionElement, this class will tell the .NET Framework which behavior will be applied and will create the instance when needed.
namespace Playground.Sandbox
{
using System;
using System.ServiceModel.Configuration;
public class MyBehaviorExtensionElement : BehaviorExtensionElement
{
protected override object CreateBehavior()
{
var myEndpointBehavior = new MyEndpointBehavior();
return myEndpointBehavior;
}
public override Type BehaviorType
{
get
{
return typeof(MyEndpointBehavior);
}
}
}
}
Then you need to register the BehaviorExtensionElement in the configuration file (only the relevant part of the configuration file are shown).
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime sku=".NETFramework,Version=v4.5"
version="v4.0" />
</startup>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="withMyBehaviorExtensionElement">
<myBehaviorExtensionElement />
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="..."
behaviorConfiguration="withMyBehaviorExtensionElement"
binding="..."
bindingConfiguration="..."
contract="..."
name="..." />
</client>
<extensions>
<behaviorExtensions>
<add name="myBehaviorExtensionElement"
type="Playground.Sandbox.MyBehaviorExtensionElement, Playground.Sandbox" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
</configuration>
Now you can use the service without manually registering the behavior each time:
namespace Playground.Sandbox
{
public static class Program
{
public static void Main()
{
using (var client = new MyWcfService())
{
// TODO: your things with the client.
}
}
}
}
You can find a guide on how to do this in the MSDN's Message Inspectors article.
It looks like all of my mappings are compiling correctly, I'm able to validly get a session from session factory. However, when I try to ISession.SaveOrUpdate(obj); I get this. Can anyone please help point me in the right direction?
private Configuration configuration;
protected Configuration Configuration {
get
{
configuration = configuration ?? GetNewConfiguration();
return configuration;
}
}
protected ISession GetNewSession() {
var sessionFactory = Configuration.BuildSessionFactory();
var session = sessionFactory.OpenSession();
return session;
}
[TestMethod] public void
TestSessionSave() {
var company = new Company();
company.Name = "Test Company 1";
DateTime savedAt = DateTime.Now;
using (var session = GetNewSession())
{
try
{
session.SaveOrUpdate(company);
}
catch (Exception e)
{
throw e;
}
}
Assert.IsTrue((company.CreationDate != null && company.CreationDate > savedAt), "Company was saved, creation date was set."); }
For those that might be interested, here is my mapping for this class:
<!-- Company -->
<class name="MyNamespace.Company,MyLibrary" table="Companies">
<id name="Id" column="Id">
<generator class="native" />
</id>
<property name="ExternalId" column="GUID" generated="insert" />
<property name="Name" column="Name" type="string" />
<property name="CreationDate" column="CreationDate" generated="insert" />
<property name="UpdatedDate" column="UpdatedDate" generated="always" />
</class>
<!-- End Company -->
Finally, here is my config -- I'm just connecting to a SQL Server CE instance for this for testing purposes.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="">
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlServerCeDriver</property>
<property name="connection.connection_string">Data Source="D:\Build\MyProject\Source\MyProject.UnitTests\MyProject.TestDatabase.sdf"</property>
<property name="dialect">NHibernate.Dialect.MsSqlCeDialect</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
</session-factory>
</hibernate-configuration>
Thanks!
It might be a problem retrieving the identity value.
Are you sure Id is declared as identity in the DB? That's what you're telling NHibernate when declaring <generator class="native" />.
If this is a new database, it would also be useful to use a client-side generator, like guid.comb or hilo.
One more thing about your code. This:
catch (Exception e)
{
throw e;
}
Is harmful, because all it does is swallow the stack trace, with might provide additional debugging information.