c# - explained - WCF: uso de la transmisión con contratos de mensajes
wcf soap service web config (3)
Intento usar la transmisión WCF con Contratos de mensajes, porque necesito parámetros adicionales al lado de la transmisión en sí.
Básicamente estoy creando un servicio de carga y descarga de archivos, con alguna lógica adicional en la parte superior.
Desafortunadamente, cuando intento acceder al servicio desde el navegador para verificar que todo esté bien, aparece el siguiente error:
Error del servidor en la aplicación ''/''. La operación ''UploadFile'' en el contrato ''IFileTransferService'' usa un MessageContract que tiene encabezados SOAP. Los encabezados SOAP no son compatibles con None MessageVersion.
Desafortunadamente, buscar en Google no arrojó ningún resultado significativo que me haya ayudado. ¿Pueden ayudarme? Aquí los detalles del servicio (he eliminado la parte de descarga por razones de espacio).
[ServiceContract(Namespace = "http://www.acme.org/2009/04")]
public interface IFileTransferService
{
[OperationContract(Action = "UploadFile")]
void UploadFile(FileUploadMessage request);
}
[MessageContract]
public class FileUploadMessage
{
[MessageHeader(MustUnderstand = true)]
public FileMetaData Metadata { get; set; }
[MessageBodyMember(Order = 1)]
public Stream FileByteStream { get; set; }
}
[DataContract(Namespace = "http://schemas.acme.org/2009/04")]
public class FileMetaData
{
[DataMember(Name="FileType", Order=0, IsRequired=true)]
public FileTypeEnum fileType;
[DataMember(Name="localFilename", Order=1, IsRequired=false)]
public string localFileName;
[DataMember(Name = "remoteFilename", Order = 2, IsRequired = false)]
public string remoteFileName;
}
He intentado utilizar tanto basichttpbinding como un enlace customhttp con efecto no positivo:
<customBinding>
<binding name="customHttpBindingStream">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport transferMode="Streamed" maxReceivedMessageSize="2147483647"/>
</binding>
</customBinding>
ACTUALIZACIÓN : al leer la documentación en línea, parece que la transmisión con MessageContracts debería ser posible. Consulte, por ejemplo, a MSDN ( datos grandes y transmisión continua ):
Modelo de programación para transferencias por streaming
El modelo de programación para la transmisión es sencillo. Para recibir datos transmitidos, especifique un contrato de operación que tenga un solo parámetro de entrada con tipo de secuencia. Para devolver datos transmitidos, devuelve una referencia de transmisión. [...] Esta regla se aplica de manera similar a los contratos de mensajes. Como se muestra en el siguiente contrato de mensaje, puede tener solo un único miembro de cuerpo en su contrato de mensaje que sea una transmisión. Si desea comunicar información adicional con la transmisión, esta información debe estar en encabezados de mensaje. El cuerpo del mensaje está reservado exclusivamente para el contenido de la transmisión.
[MessageContract]
public class UploadStreamMessage
{
[MessageHeader]
public string appRef;
[MessageBodyMember]
public Stream data;
}
También he visto entradas de blog de personas que realizan servicios de carga y descarga de archivos muy similares a lo que estoy tratando de armar (por ejemplo, here ).
ACTUALIZACIÓN 2 He intentado crear una pequeña consola y autohospedar el servicio con un basicHttpBinding y allí funciona como un encanto. Estoy empezando a creer que el problema podría ser el alojamiento en IIS. ¿Alguna idea?
ACTUALIZAR 3 Ver mi propia respuesta.
¿Necesita la transmisión (es decir, la transferencia de cantidades de datos en masa) tanto en la solicitud como en la respuesta? ¿O solo en la respuesta (típicamente: descargar un archivo o un gran conjunto de datos)?
Si solo necesita la respuesta, intente configurar el modo de transferencia como "StreamedResponse":
<customBinding>
<binding name="customHttpBindingStream">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport transferMode="StreamedResponse"
maxReceivedMessageSize="2147483647"/>
</binding>
</customBinding>
La configuración "Transmitida por Internet" se transmitirá en ambos sentidos: se transmitirá la solicitud que va al servidor, así como la respuesta del servidor. La mayoría de las veces, ese no es el escenario ideal.
Bagazo
Finalmente descubrí cuál era el error: no tenía nada que ver con las versiones de Soap, las transmisiones, etc. Simplemente desvirtué el nombre de mi propio servicio (!), Utilizando FileTransfer
lugar de FileTransferService
.
Al final basicHttpBinding estaba perfectamente bien, no tuve que recurrir a un enlace personalizado.
Versión original (mala):
<service
behaviorConfiguration="serviceBehavior"
name="Acme.Service.FileTransfer">
<endpoint address=""
name="basicHttpStream"
binding="basicHttpBinding"
bindingConfiguration="httpLargeMessageStream"
contract="Acme.Service.IFileTransferService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
Nueva versión (fija):
<service
behaviorConfiguration="serviceBehavior"
name="Acme.Service.FileTransferService">
<endpoint address=""
name="basicHttpStream"
binding="basicHttpBinding"
bindingConfiguration="httpLargeMessageStream"
contract="Acme.Service.IFileTransferService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
Aún así, no puedo decir que el mensaje de error haya sido útil para entender lo que estaba sucediendo aquí ...
Si está interesado en todo el servicio, puede encontrar más detalles en mi blog en el siguiente enlace: Transferencia de archivos con WCF
Recibí el error después de usar la plantilla ''WCF Data Service'' para generar el archivo svc en lugar de la plantilla ''WCF Service''. Al corregir el archivo host del servicio, se solucionó el problema.