Tengo el mismo problema que se enumera en el siguiente hilo.Error "Este mensaje no admite la operación porque se ha leído"
WSDL first WCF server where client does not send SOAPAction
I realizado los pasos que se enumeran en el mismo hilo (también se muestra a continuación)
1) Descarga los ejemplos Microsoft WCF. Añadir los siguientes archivos a su proyecto de WF_WCF_Samples \ WCF \ extensibilidad \ interoperabilidad \ RouteByBody \ CS \ servicio
DispatchByBodyOperationSelector.cs
DispatchByBodyBehaviorAttribute.cs
2) Añadir los siguientes atributos a la interfaz (al lado de su ServiceContract)
XmlSerializerFormat
DispatchByBodyBehavior
3) Añadir lo siguiente a su interfaz de servicio
[OperationContract(Action = "")]
public void DoNothing()
{
}
4) Para mi servicio, WrapperName y Wrappernamespace son nulos para todos los mensajes. Tenía que ir a DispatchByBodyBehaviorAttribute y editar ApplyDispatchBehavior() para agregar las siguientes líneas para comprobar esto:
if (qname.IsEmpty) {
qname = new XmlQualifiedName(operationDescription.Messages[0].Body.Parts[0].Name, operationDescription.Messages[0].Body.Parts[0].Namespace);
}
Ahora, estoy recibiendo un mensaje de error "Este mensaje no puede soportar la operación, ya que se ha leído". Activé el trazado y capté el trazado de la pila (abajo). Si alguien tiene alguna idea sobre cómo se puede resolver esto, le agradecería si pudiera publicar algunos comentarios. ¡Gracias por cualquier ayuda!
at System.ServiceModel.Channels.Message.GetReaderAtBodyContents()
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
at System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.Runtime.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
at System.Runtime.InputQueue`1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult result)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
class DispatchByBodyElementOperationSelector : IDispatchOperationSelector
{
Dictionary<XmlQualifiedName, string> dispatchDictionary;
public DispatchByBodyElementOperationSelector(Dictionary<XmlQualifiedName, string> dispatchDictionary)
{
this.dispatchDictionary = dispatchDictionary;
}
#region IDispatchOperationSelector Members
private Message CreateMessageCopy(Message message, XmlDictionaryReader body)
{
//Message copy = Message.CreateMessage(message.Version, message.Headers.Action, body);
//copy.Headers.CopyHeaderFrom(message, 0);
//copy.Properties.CopyProperties(message.Properties);
//return copy;
MessageBuffer buffer = message.CreateBufferedCopy(Int32.MaxValue);
Message copy = buffer.CreateMessage();
buffer.Close();
copy.Headers.CopyHeaderFrom(message, 0);
copy.Properties.CopyProperties(message.Properties);
return copy;
}
public string SelectOperation(ref System.ServiceModel.Channels.Message message)
{
XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents();
XmlQualifiedName lookupQName = new XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI);
message = CreateMessageCopy(message,bodyReader);
if (dispatchDictionary.ContainsKey(lookupQName))
{
return dispatchDictionary[lookupQName];
}
else
{
return null;
}
}
#endregion
}
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface)]
sealed class DispatchByBodyBehaviorAttribute : Attribute, IContractBehavior
{
#region IContractBehavior Members
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
// no binding parameters need to be set here
return;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
// this is a dispatch-side behavior which doesn't require
// any action on the client
return;
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
{
// We iterate over the operation descriptions in the contract and
// record the QName of the request body child element and corresponding operation name
// to the dictionary to be used for dispatch
Dictionary<XmlQualifiedName,string> dispatchDictionary = new Dictionary<XmlQualifiedName,string>();
foreach(OperationDescription operationDescription in contractDescription.Operations)
{
XmlQualifiedName qname =
new XmlQualifiedName(operationDescription.Messages[0].Body.WrapperName, operationDescription.Messages[0].Body.WrapperNamespace);
if (qname.IsEmpty)
{
qname = new XmlQualifiedName(operationDescription.Messages[0].Body.Parts[0].Name, operationDescription.Messages[0].Body.Parts[0].Namespace);
}
dispatchDictionary.Add(qname, operationDescription.Name);
}
// Lastly, we create and assign and instance of our operation selector that
// gets the dispatch dictionary we've just created.
dispatchRuntime.OperationSelector =
new DispatchByBodyElementOperationSelector(dispatchDictionary);
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
//
}
#endregion
}
Gracias por publicar el código. En mi caso, estoy reutilizando las clases de la descarga de Muestras WCF. Traté de poner el código de MessageBuffer en el método CreateMessageCopy como a continuación, pero no funcionó para mí. – Jyina
He editado mi pregunta original y publicado las dos clases que estoy reutilizando de muestras de WCF. Comenté el código existente en CreateMessageCopy() y traté de crear el mensaje usando MessageBuffer. Cuando ejecuto mi cliente, está fallando en la línea. MessageBuffer buffer = message.CreateBufferedCopy (Int32.MaxValue); – Jyina
Parece que el mensaje ya se ha leído antes de que llegue a esta línea. No estoy seguro de dónde debería poner el código de MessageBuffer. ¿Algunas ideas? ¡Gracias! – Jyina