2010-03-17 9 views
3

J'ai un service Web WCF avec basicHTTPBinding, le côté serveur le mode de transfert est streamedRequest car le client nous enverra un gros fichier sous la forme d'un flux mémoire.WCF- Données volumineuses

Mais côté client quand j'utiliser le mode de transfert streamedRequest son me donner un ce errro « Le serveur distant a renvoyé une erreur: (400) Bad Request » Et quand je regarde pour tracer des informations, je vois ceci comme le message d'erreur Exception: Il y a un problème avec le XML qui a été reçu du réseau. Voir l'exception interne pour plus de détails.

InnerException: Le corps du message ne peut pas être lu car il est vide.

Je peux envoyer jusqu'à 5MB de données en utilisant le trasfermode comme tamponné, mais cela affectera les performances de mon service Web à long terme, si de nombreux clients tentent d'accéder au service en mode de transfert tamponné .

SmartConnect.Service1Client Serv = new SmartConnectClient.SmartConnect.Service1Client(); 
SmartConnect.OrderCertMailResponse OrderCert = new SmartConnectClient.SmartConnect.OrderCertMailResponse(); 
OrderCert.UserID = "abcd"; 
OrderCert.Password = "7a80f6623"; 
OrderCert.SoftwareKey = "90af1"; 
string applicationDirectory = @"\\inid\utty\Bran"; 
byte[] CertMail = File.ReadAllBytes(applicationDirectory + @"\5mb_test.zip"); 
MemoryStream str = new MemoryStream(CertMail); 

//OrderCert.Color = true; 
//OrderCert.Duplex = false;   
//OrderCert.FirstClass = true; 
//OrderCert.File = str; 
//OrderCert.ReturnAddress1 = "Test123"; 
//OrderCert.ReturnAddress2 = "Test123"; 
//OrderCert.ReturnAddress3 = "Test123"; 
//OrderCert.ReturnAddress4 = "Test123"; 
OrderCert.File = str; 

//string OrderNumber = ""; 
//string Password = OrderCert.Password; 
//int ReturnCode = 0; 
//string ReturnMessage = ""; 
//string SoftwareKey = OrderCert.SoftwareKey; 
//string UserID = OrderCert.UserID; 
//OrderCert.File = str; 

MemoryStream FileStr = str; 
Serv.OrderCertMail(OrderCert); 

// Serv.OrderCertMail(ref OrderNumber, ref Password, ref ReturnCode, ref ReturnMessage, ref SoftwareKey, ref UserID, ref FileStr); 
lblON.Text = OrderCert.OrderNumber; 

Serv.Close(); 


// My Web Service - Service Contract 
[OperationContract] 
OrderCertMailResponse OrderCertMail(OrderCertMailResponse OrderCertMail); 

[MessageContract] 
public class OrderCertMailResponse 
{ 
    string userID = ""; 
    string password = ""; 
    string softwareID = ""; 
    MemoryStream file = null; 
    //MemoryStream str = null; 

    [MessageHeader] 
    //[DataMember] 
    public string UserID 
    { 
     get { return userID; } 
     set { userID = value; } 
    } 

    [MessageHeader] 
    //[DataMember] 
    public string Password 
    { 
     get { return password; } 
     set { password = value; } 
    } 

    [MessageHeader] 
    //[DataMember] 
    public string SoftwareKey 
    { 
     get { return softwareID; } 
     set { softwareID = value; } 
    } 

    [MessageBodyMember] 
    // [DataMember] 
    public MemoryStream File 
    { 
     get { return file; } 
     set { file = value; } 
    } 

    [MessageHeader] 
    //[DataMember] 
    public string ReturnMessage; 

    [MessageHeader] 
    //[DataMember] 
    public int ReturnCode; 

    [MessageHeader] 
    public string OrderNumber; 
} 


[ServiceBehavior(IncludeExceptionDetailInFaults = true)] 
public class Service1 : IService1 
{ 
    public OrderCertMailResponse OrderCertMail(OrderCertMailResponse OrderCertMail) 
    { 
     OrderService CertOrder = new OrderService(); 
     ClientUserInfo Info = new ClientUserInfo(); 
     ControlFileInfo Control = new ControlFileInfo(); 

     //Info.Password = "f2496623"; // hard coded password for development testing purposes 
     //Info.SoftwareKey = "6dbb71";  // hard coded software key this is a developement software key 
     //Info.UserName = "sdfs";  // hard coded UserID - for testing 
     Info.UserName = OrderCertMail.UserID.ToString(); 
     Info.Password = OrderCertMail.Password.ToString(); 
     Info.SoftwareKey = OrderCertMail.SoftwareKey.ToString(); 

     //Control.ReturnAddress1 = OrderCertMail.ReturnAddress1; 
     //Control.ReturnAddress2 = OrderCertMail.ReturnAddress2; 
     //Control.ReturnAddress3 = OrderCertMail.ReturnAddress3; 
     //Control.ReturnAddress4 = OrderCertMail.ReturnAddress4; 
     //Control.CertMailFirstClass = OrderCertMail.FirstClass; 
     //Control.CertMailColor = OrderCertMail.Color; 
     //Control.CertMailDuplex = OrderCertMail.Duplex; 

     //byte[] CertFile = new byte[0]; 
     //byte[] CertFile = null; 

     //string applicationDirectory = @"\\inid\utility\Bryan"; 
     // byte[] CertMailFile = File.ReadAllBytes(applicationDirectory + @"\3mb_test.zip"); 
     //MemoryStream str = new MemoryStream(CertMailFile); 
     OrderCertMailResponseClass OrderCertResponse = CertOrder.OrderCertmail(Info,Control,OrderCertMail.File); 
     OrderCertMail.ReturnMessage = OrderCertResponse.ReturnMessage.ToString(); 
     OrderCertMail.ReturnCode = Convert.ToInt32(OrderCertResponse.ReturnCode.ToString()); 
     OrderCertMail.OrderNumber = OrderCertResponse.OrderNumber;    

     return OrderCertMail; 
    } 

Voici mon nouveau contrat d'exploitation qui ne prend que flux de données en tant que paramètre

[OperationContract] 
SmartStream SendStream(MemoryStream DataStream); 

public SmartStream SendStream(MemoryStream DataStream) 
{ 
    OrderService CertOrder = new OrderService(); 
    ClientUserInfo Info = new ClientUserInfo(); 
    ControlFileInfo Control = new ControlFileInfo(); 
    MemoryStream serverStream = null; 

    Info.Password = "78f24dsfsdf96623";    
    Info.SoftwareKey = "dfs6dbb71";  
    Info.UserName = "ssfsdf";  

    using (serverStream = new MemoryStream(100)) 
    { 
     int count = 0; 
     const int buffLen = 4096; 
     byte[] buf = new byte[buffLen]; 

     while ((count = CertFile.Read(buf, 0, buffLen)) > 0) 
     { 
      serverStream.Write(buf, 0, count); 
     } 

     CertFile.Close(); 
     serverStream.Close(); 
     return null; 
    } 

Ma méthode client pour accéder

protected void Page_Load(object sender, EventArgs e) 
{ 
    SmartConnect.Service1Client Serv = new 
       SmartConnectClient.SmartConnect.Service1Client(); 
    string applicationDirectory = @"\\intrepid\utility\Bryan"; 
    byte[] CertMail = File.ReadAllBytes(applicationDirectory + @"\100mb_test.zip"); 
    MemoryStream str = new MemoryStream(CertMail); 

    SmartConnectClient.SmartConnect.SendStreamRequest request = 
     new SmartConnectClient.SmartConnect.SendStreamRequest(); 
    SmartConnectClient.SmartConnect.SmartStream SmartStr = 
     new SmartConnectClient.SmartConnect.SmartStream(); 
    request.DataStream = str; 

    SmartConnectClient.SmartConnect.SendStreamResponse response = Serv.SendStream(request); 
} 
+0

Pouvez-vous nous montrer le contrat de service et le code côté client que vous utilisez pour envoyer le fichier de 5 Mo? –

+0

@marc J'ai ajouté le code côté client. – Pinu

+0

@Marc - J'ai ajouté mon contrat de service, Information. Est-ce que ça va bien? Merci beaucoup pour votre aide. Appréciez-le. – Pinu

Répondre

1

@Marc - Merci beaucoup pour votre aide. Cela m'a aidé à résoudre de nombreux problèmes de mon service.

Le service Web a commencé à fonctionner lorsque je l'ai exécuté sur IIS local sur ma machine, il renvoyait toutes ces erreurs lorsque j'étais en cours d'exécution sur le serveur de développement Visual Studio. Je ne pouvais pas comprendre pourquoi il en est ainsi, pourquoi il ne fonctionnait pas sur le serveur de développement de Visual Studio.

3

Pinu, je pense toujours que vous êtes probablement ne pas faire le contrat de service juste pour le streaming WCF. Voir la MSDN docs on WCF Streaming - en particulier cette section sur les restrictions:

Restrictions on Streamed Transfers

Using the streamed transfer mode causes the run time to enforce additional restrictions.

Operations that occur across a streamed transport can have a contract with at most one input or output parameter. That parameter corresponds to the entire body of the message and must be a Message, a derived type of Stream, or an IXmlSerializable implementation. Having a return value for an operation is equivalent to having an output parameter.

De votre code affiché, je suis encore sous l'impression que vous essayez de mélanger les deux mises en mémoire tampon et les transferts écoutés.

Si vous voulez avoir réel streaming, votre contrat de service doit ressembler à quelque chose comme:

[ServiceContract(Namespace=".....")] 
interface IUploadFileService 
{ 
    [OperationContract] 
    UploadResponse UploadFile(Stream file); 
} 

C'est tout ce que vous pouvez avoir dans votre contrat de service pour cette méthode de service.

Jetez également un coup d'œil à de très bons articles de blog en streaming here et here.

Questions connexes