Here's what my WCF service should be returning. When I command PaymentData out of ResponseModel and add other DataMembers in that class it works.
[DataContract]
public class ResponseModel
{
[DataMember]
public PaymentData PaymentData { get; set; }
}
Here's the PaymentData class:
[DataContract]
public class PaymentData
{
[DataMember]
public PaymentType PaymentType { get; set; }
[DataMember]
public string CardNumber { get; set; }
[DataMember]
public DateTime ExpirationDate { get; set; }
/// <summary>
/// If true, then the CardNumber property will contain the token
/// </summary>
[DataMember]
public bool IsCardNumberTokenized { get; set; }
/// <summary>
/// Number on back of credit cards. This value CANNOT be stored anywhere
/// </summary>
[DataMember]
public string CardSecurityValue { get; set; }
[DataMember]
public CardSecurityPresence CardSecurityPresence { get; set; }
}
... and the enums defined in the PaymentData class
[DataContract(Name = "CardSecurityPresenceEnum")]
public enum CardSecurityPresence
{
[EnumMember(Value = "1")]
IsPresent = 1,
[EnumMember(Value = "2")]
Illegible = 2,
[EnumMember(Value = "9")]
NoCodeOnCard = 9,
[EnumMember(Value = " ")]
NotSent
}
[DataContract(Name = "PaymentTypeEnum")]
public enum PaymentType
{
[EnumMember]
Visa = CMPWSApiService.TransactionMop.VI,
[EnumMember]
MasterCard = CMPWSApiService.TransactionMop.MC,
[EnumMember]
AmericanExpress = CMPWSApiService.TransactionMop.AX,
[EnumMember]
Discover = CMPWSApiService.TransactionMop.DI,
[EnumMember]
PayPal = CMPWSApiService.TransactionMop.PP,
[EnumMember]
BillMeLater = CMPWSApiService.TransactionMop.BL
}
Does the serialization not like that my variable names have the same names as their classes?
Here's the error from the WCFTest Client:
An error occurred while receiving the HTTP response to
[service url omitted]. This
could be due to the service endpoint binding not using the HTTP
protocol. This could also be due to an HTTP request context being
aborted by the server (possibly due to the service shutting down). See
server logs for more details.
Server stack trace: at
System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException
webException, HttpWebRequest request, HttpAbortReason abortReason)
at
System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan
timeout) at
System.ServiceModel.Channels.RequestChannel.Request(Message message,
TimeSpan timeout) at
System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message
message, TimeSpan timeout) at
System.ServiceModel.Channels.ServiceChannel.Call(String action,
Boolean oneway, ProxyOperationRuntime operation, Object[] ins,
Object[] outs, TimeSpan timeout) at
System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage
methodCall, ProxyOperationRuntime operation) at
System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage
message)
Exception rethrown at [0]: at
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage
reqMsg, IMessage retMsg) at
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
msgData, Int32 type) at ICreditCardService.TestAuth() at
CreditCardServiceClient.TestAuth()
Inner Exception: The underlying connection was closed: An unexpected
error occurred on a receive. at
System.Net.HttpWebRequest.GetResponse() at
System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan
timeout)
Inner Exception: Unable to read data from the transport connection: An
existing connection was forcibly closed by the remote host. at
System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset,
Int32 size) at System.Net.PooledStream.Read(Byte[] buffer, Int32
offset, Int32 size) at
System.Net.Connection.SyncRead(HttpWebRequest request, Boolean
userRetrievedStream, Boolean probeRead)
Inner Exception: An existing connection was forcibly closed by the
remote host at System.Net.Sockets.Socket.Receive(Byte[] buffer,
Int32 offset, Int32 size, SocketFlags socketFlags) at
System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset,
Int32 size)
In CardSecurityPresenceEnum I had a enum member called NotSent that was not initialized to a value. For some reason that was hanging things up.
Related
I have a Service and the releated interface under namespace called "WCFService":
[ServiceContract]
public interface IBook
{
[OperationContract]
[WebInvoke(Method="GET"
,ResponseFormat=WebMessageFormat.Json
,BodyStyle=WebMessageBodyStyle.Wrapped
,UriTemplate="/?bookID={bookID}")]
Book Get(int bookID);
}
//========================================================
public Book Get(int bookID)
{
return bookList.Where(p => p.BookID == bookID).FirstOrDefault();
}
And the Book DataModel is under another namespace called "WCFModel":
[DataContract]
public class Book
{
[DataMember]
public int BookID { get; set; }
[DataMember]
public string BookName { get; set; }
[DataMember]
public decimal BookPrice { get; set; }
[DataMember]
public string BookPublish { get; set; }
}
After set the config file, I got the service run ok.
Then I planned to consume it in client side. I added a windows form application to the project and added reference to the WCFModel book datamodel, I used below code to extract the data:
string serviceURL = "http://localhost:15020/BookService.svc/?bookID=" + txtBookID.Text.Trim();
var request = WebRequest.Create(serviceURL);
var response = request.GetResponse();
DataContractSerializer serializer = new DataContractSerializer(typeof(WCFModel.Book));
var bookObj = serializer.ReadObject(response.GetResponseStream());
But the result was, VS thrown me an exception at the ReadObject below:
Error when deserializing the WCFModel.Book type, Data at the root level is invalid.
stack trace below:
在 System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
在 System.Xml.XmlUTF8TextReader.Read()
在 System.Xml.XmlBaseReader.IsStartElement()
在 System.Xml.XmlBaseReader.IsStartElement(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
在 System.Runtime.Serialization.XmlReaderDelegator.IsStartElement(XmlDictionaryString localname, XmlDictionaryString ns)
在 System.Runtime.Serialization.XmlObjectSerializer.IsRootElement(XmlReaderDelegator reader, DataContract contract, XmlDictionaryString name, XmlDictionaryString ns)
在 System.Runtime.Serialization.DataContractSerializer.InternalIsStartObject(XmlReaderDelegator reader)
在 System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
在 System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
I don't know why, After searching a lot, I still can't get the point. Anyone can give me some reference? thx.
I hope this may work for you!
Try implementing this!
WebClient proxy = new WebClient();
string serviceURL =
string.Format("http://localhost:15020/BookService.svc/?bookID=" + txtBookID.Text.Trim().ToString());
byte[] data = proxy.DownloadData(serviceURL);
Stream stream = new MemoryStream(data);
DataContractJsonSerializer obj =
new DataContractJsonSerializer(typeof(Book));
Book book = obj.ReadObject(stream) as Book;
Console.WriteLine("Book ID : " + book.BookID);
Console.WriteLine("Book Name : " + book.BookName);
Console.WriteLine("Book ID : " + book.BookPrice);
Console.WriteLine("Book ID : " + book.BookPublish);
See this link
EDIT: Change BodyStyle=WebMessageBodyStyle.Wrapped to BodyStyle=WebMessageBodyStyle.Bare.
I try to implement an Asynchronous Service Operation (http://msdn.microsoft.com/en-us/library/ms731177.aspx) with masstransit request/response.
[ServiceContract]
public interface IService1
{
[OperationContractAttribute(AsyncPattern = true)]
IAsyncResult BeginMyOperation(string data, AsyncCallback callback, object asyncState);
string EndMyOperation(IAsyncResult result);
}
public class Service1 : IService1
{
private string _answer;
public IAsyncResult BeginMyOperation(string data, AsyncCallback callback, object asyncState)
{
return Bus.Instance.BeginPublishRequest(
new MyRequestMessage { Data = data }, callback, asyncState, cfg =>
{
cfg.Handle<MyResponseMessage>(c => _answer = c.Answer);
cfg.SetTimeout(5.Seconds());
});
}
public string EndMyOperation(IAsyncResult result)
{
Bus.Instance.EndPublishRequest<MyResponseMessage>(result);
return _answer;
}
}
But EndPublishRequest throws an Exception "The argument is not an IRequest". Am I doing something wrong?
Yeah, the exception message needs to be a bit better, if you look at the signature though:
public static bool EndPublishRequest<TRequest>(this IServiceBus bus, IAsyncResult asyncResult)
it becomes apparent that the request message type is the required type arg here.
in my following application, i generate a List of the class 'JobManager'.
List<JobManager>
The access to the database and filling my list is working perfect. It seems there is a problem for returning such list to my client.
In detail,my code looks like this
IService Class
OperationContract(Name = "ReadJobQueue")]
[FaultContract(typeof(FaultException))]
List<JobManager> AccessManager(List<string> status,string process, string dtFrom, string dtTo);
Service : IService
public List<JobManager> AccessManager(List<string> status, string process, string dtFrom, string dtTo)
{
//return 'new List<JobManager>()' does work, without any data being filled.
return new JobBuilder(status, process, dtFrom, dtTo);
}
[DataContract]
public class JobManager
{
List<JobManager> _jobManagerchildren = new List<JobManager>();
[DataMember(IsRequired = true, Order = 0)]
public string Description { get; set; }
[DataMember]
public List<JobManager> JobManagerChildren
{
get { return _jobManagerchildren; }
internal set { _jobManagerchildren = value; }
}
}
internal class JobBuilder : List<JobManager>
{
public JobBuilder(List<string> status, string process, string dtFrom, string dtTo)
: base()
{
DataTable dt = new Database().AccessJobQueue(status, process, dtFrom, dtTo);
foreach (DataRow row in dt.Rows)
{
Add(new JobManager { Description = row[1].ToString(), JobManagerChildren = JobDetail(row[0].ToString()) });
}
}
...
}
Have i missed something for my JobManager class?
edit error code / exception
System.Net.Sockets.SocketException:
An existing connection was been closed by the remotehost
bei System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size
, SocketFlags socketFlags)
bei System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int
32 offset, Int32 size, TimeSpan timeout, Boolean closing)
--- Ende der internen Ausnahmestapelüberwachung ---
bei System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int
32 offset, Int32 size, TimeSpan timeout, Boolean closing)
bei System.ServiceModel.Channels.SocketConnection.Read(Byte[] buffer, Int32 o
ffset, Int32 size, TimeSpan timeout)
bei System.ServiceModel.Channels.DelegatingConnection.Read(Byte[] buffer, Int
32 offset, Int32 size, TimeSpan timeout)
bei System.ServiceModel.Channels.ConnectionStream.Read(Byte[] buffer, Int32 o
ffset, Int32 count)
bei System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32
count)
bei System.Net.Security.NegotiateStream.StartFrameHeader(Byte[] buffer, Int32
offset, Int32 count, AsyncProtocolRequest asyncRequest)
bei System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offs
et, Int32 count, AsyncProtocolRequest asyncRequest)
--- Ende der internen Ausnahmestapelüberwachung ---
bei System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offs
et, Int32 count, AsyncProtocolRequest asyncRequest)
bei System.Net.Security.NegotiateStream.Read(Byte[] buffer, Int32 offset, Int
32 count)
bei System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 o
ffset, Int32 size, TimeSpan timeout)
--- Ende der internen Ausnahmestapelüberwachung ---
Server stack trace:
bei System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 o
ffset, Int32 size, TimeSpan timeout)
bei System.ServiceModel.Channels.SessionConnectionReader.Receive(TimeSpan tim
eout)
bei System.ServiceModel.Channels.SynchronizedMessageSource.Receive(TimeSpan t
imeout)
bei System.ServiceModel.Channels.FramingDuplexSessionChannel.Receive(TimeSpan
timeout)
bei System.ServiceModel.Channels.FramingDuplexSessionChannel.TryReceive(TimeS
pan timeout, Message& message)
bei System.ServiceModel.Dispatcher.DuplexChannelBinder.Request(Message messag
e, TimeSpan timeout)
bei System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean o
neway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan ti
meout)
bei System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCal
lMessage methodCall, ProxyOperationRuntime operation)
bei System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
bei System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage re
qMsg, IMessage retMsg)
bei System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgD
ata, Int32 type)
bei WcfSys.Shared.IService.AccessManager(List`1 status, String process, S
tring dtFrom, String dtTo)
bei WcfSys.Server.Program.Main() in WcfSys.Ser
ver\Program.cs:Zeile 66.
Actually, what you're sending back to the client is a List<JobManager>, but actually it's a derived class. So there are two ways of fixing this:
Copy all entries from JobBuilder to a new List<JobManager> and return that new list
Make JobBuilder a DataContract, too.
As - by OOP principles - it is know that the object you're returning is a JobBuilder, the runtime tries to serialize the JobBuilder instance. This, however, is not a know type for WCF communication.
Well im trying to setup a net.tcp connection with SSL encryption
I have the following classes
Wcf Interface:
[ServiceContract()]
public interface IServer
{
[OperationContract]
void Send(string message);
}
Server:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
class Server : IServer
{
readonly ServiceHost host;
public Server()
{
host = new ServiceHost(this);
host.AddServiceEndpoint(typeof(IServer), Program.GetBinding(), string.Format("net.tcp://localhost:{0}/", 1010));
host.Credentials.ServiceCertificate.Certificate = Program.LoadCert();
host.Open();
}
public void Send(string message)
{
Console.WriteLine(message);
}
}
Program (Client/Server):
class Program
{
static ChannelFactory<IServer> channelFactory;
static IServer server;
static RemoteCertificateValidationCallback callback = null;
public const int MaxMessageSize = 1024 * 1024 * 2;
public static Binding GetBinding()
{
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Message.ClientCredentialType = MessageCredentialType.None;
binding.ReaderQuotas.MaxArrayLength = MaxMessageSize;
binding.ReaderQuotas.MaxBytesPerRead = MaxMessageSize;
binding.MaxBufferSize = MaxMessageSize;
binding.MaxReceivedMessageSize = MaxMessageSize;
binding.MaxBufferPoolSize = binding.MaxBufferSize * 10;
binding.TransactionFlow = false;
binding.ReliableSession.Enabled = false;
binding.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
return binding;
}
public static X509Certificate2 LoadCert()
{
X509Certificate2 cert = new X509Certificate2();
cert.Import(#"Test2.pfx", "Test", X509KeyStorageFlags.DefaultKeySet);
return cert;
}
static void Main(string[] args)
{
try
{
callback = new RemoteCertificateValidationCallback(ValidateCertificate);
ServicePointManager.ServerCertificateValidationCallback += callback;
Console.WriteLine("[C]lient or [S]erver?");
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.Key == ConsoleKey.S)
{
StartServer();
}
else if (key.Key == ConsoleKey.C)
{
StartClient();
}
}
finally
{
if (callback != null)
ServicePointManager.ServerCertificateValidationCallback -= callback;
}
}
private static void StartClient()
{
Console.WriteLine("Starting client mode!");
Console.Write("Host:");
string host = Console.ReadLine();
channelFactory = new ChannelFactory<IServer>(GetBinding());
server = channelFactory.CreateChannel(new EndpointAddress(string.Format("net.tcp://{0}:{1}/", host, 1010)));
while (true)
{
Console.Write("Message:");
server.Send(Console.ReadLine());
}
}
private static void StartServer()
{
Console.WriteLine("Starting server mode!");
Server server = new Server();
Console.ReadKey();
GC.KeepAlive(server);
}
public static bool ValidateCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
Console.WriteLine("ValidateCertificate");
return true;
}
}
This works fine when both the server and client are run on the same computer (but ValidateCertificate is never called like it should be).
But if i run them on separate computers i get the following exception on the client:
Description: The process was terminated due to an unhandled exception.
Exception Info:
System.ServiceModel.Security.SecurityNegotiationException Stack:
Server stack trace: at
System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream
stream, SecurityMessageProperty& remoteSecurity) at
System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorBase.InitiateUpgrade(Stream
stream) at
System.ServiceModel.Channels.ConnectionUpgradeHelper.InitiateUpgrade(StreamUpgradeInitiator
upgradeInitiator, IConnection& connection, ClientFramingDecoder
decoder, IDefaultCommunicationTimeouts defaultTimeouts, TimeoutHelper&
timeoutHelper) at
System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreamble(IConnection
connection, ArraySegment`1 preamble, TimeoutHelper& timeoutHelper)
at
System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.DuplexConnectionPoolHelper.AcceptPooledConnection(IConnection
connection, TimeoutHelper& timeoutHelper) at
System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan
timeout) at
System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan
timeout) at
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan
timeout) at
System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan
timeout) at
System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel
channel, TimeSpan timeout) at
System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan
timeout, CallOnceManager cascade) at
System.ServiceModel.Channels.ServiceChannel.Call(String action,
Boolean oneway, ProxyOperationRuntime operation, Object[] ins,
Object[] outs, TimeSpan timeout) at
System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage
methodCall, ProxyOperationRuntime operation) at
System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage
message) at
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(System.Runtime.Remoting.Messaging.IMessage,
System.Runtime.Remoting.Messaging.IMessage) at
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData
ByRef, Int32) at
WcfChatTest.Client.Program+IServer.Send(System.String) at
WcfChatTest.Client.Program.StartClient() at
WcfChatTest.Client.Program.Main(System.String[])
What did i configure wrong, and why does it call "WindowsStreamSecurityUpgradeProvider" when i provided it a certificate?
Or if some one else got a great example how to get transport encryption on net.tcp without the client and server being in the same domain?
I solved the problem on the line
server = channelFactory.CreateChannel(new EndpointAddress(string.Format("net.tcp://{0}:{1}/", host, 1010)));
i had to add a addittional parameter that i created with the following code
EndpointIdentity.CreateX509CertificateIdentity(certificate)
I use the IClientMessageInspector and it's method BeforeSendRequest, to inspect the request messages. The thing is that some of request messages has members, which members are of type object (in the real scenario thre may be in example string or some other value, which is specified in the KnownType attribute):
[DataContract(Namespace = "")]
[KnownType(typeof(SomeValueDTO))]
public class CenDTO
{
[DataMember]
public string Uri { get; set; }
[DataMember]
public object Value { get; set; }
}
Notice, that in this project the namespaces are not defined anywhere. So on the "BeforeSendRequest" I got exception. And looks like this interface uses not the same DataContractSerializer as in the real service, which hasn't such serialization errors or smth like that.
The error:
The empty string '' is not a valid name.
at System.Xml.XmlTextWriter.LookupPrefix(String ns)
at System.Xml.XmlDictionaryWriter.XmlWrappedWriter.LookupPrefix(String namespaceUri)
at System.Xml.XmlDictionaryWriter.XmlWrappedWriter.WriteXmlnsAttribute(String prefix, String namespaceUri)
at System.Xml.XmlDictionaryWriter.WriteXmlnsAttribute(String prefix, XmlDictionaryString namespaceUri)
at System.Runtime.Serialization.XmlWriterDelegator.WriteXmlnsAttribute(XmlDictionaryString ns)
at System.Runtime.Serialization.XmlWriterDelegator.WriteAttributeQualifiedName(String attrPrefix, XmlDictionaryString attrName, XmlDictionaryString attrNs, XmlDictionaryString name, XmlDictionaryString ns)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteTypeInfo(XmlWriterDelegator writer, XmlDictionaryString dataContractName, XmlDictionaryString dataContractNamespace)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteTypeInfo(XmlWriterDelegator writer, DataContract contract, DataContract declaredContract)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteCenDTOToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )
at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(XmlDictionaryWriter writer, PartInfo part, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameters(XmlDictionaryWriter writer, PartInfo[] parts, Object[] parameters)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BodyWriterMessage.OnBodyToString(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.ToString(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.ToString()
at CID.TopicAnalyst.CIA.Test.Utils.MessageInspector.BeforeSendRequest(Message& request, IClientChannel channel) in D:\git\...\MessageInspector.cs:line 25
at System.ServiceModel.Dispatcher.ImmutableClientRuntime.BeforeSendRequest(ProxyRpc& rpc)
Implementation of "BeforeSendRequest"(The crash is on the .ToString() ):
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
if(request.Headers.Count > 0)
{
request.Headers.RemoveAt(0);
}
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();
var message = buffer.CreateMessage().ToString();
var resultFile = ConfigurationManager.AppSettings.GetValues("requestFile").First();
_serializer.Write(resultFile, message);
return null;
}
The testing itself is a separate solution, which uses the service's reference.
On the service imnplmentation the operation looks like this:
[ServiceContract]
public interface ISoapService
{
[OperationContract]
SomeListResponseMessage GetSomeList(SomeListRequestMessage request);
}
[MessageContract]
public class SomeListRequestMessage : BaseRequestMessage
{
...
[MessageBodyMember]
public CenDTO Cen { get; set; }
...
}
[DataContract(Namespace = "")]
[KnownType(typeof(SemValueDTO))]
public class CenDTO
{
...
[DataMember]
public object Value { get; set; }
}
Some code of the Testing Solution:
static class Program
{
static void Main(string[] args)
{
while(true)
{
var client = new SoapServiceClient("BasicHttpBinding_ISoapService");
client.Endpoint.Behaviors.Add(new InspectorBehavior());
var soapService = client.ChannelFactory.CreateChannel();
var co = new CooRequestCreator(soapService);
co.CreateAndWriteRequests();
Console.WriteLine("Press y to repeat");
var str = Console.ReadLine();
if(str != "y") break;
}
}
Constructing the request message before calling the service:
class CooRequestCreator : BaseRequestCreator<SomeListRequestMessage>
{
SemValueDTO _semaValue = new SemValueDTO
{
Key = "fb",
Label = "Guild",
Type = "org"
};
public CooRequestCreator(ISoapService soapService) : base(soapService)
{
}
protected override SomeListRequestMessage CreateMinRequest()
{
return new SomeListRequestMessage
{
Cen =
new CenDTO
{
Value = _semaValue,
},
MaxCount = 5
};
}
Maybe someone can has the same experience and can help with that?