sábado, 15 de janeiro de 2011

SOAP Extensions



Só para registrar que estou trabalhando numa solução, para resolver problemas no velho NET .1.1 de uma aplicação com SOAP Extension.

Tudo perfeito na sincronia com dados, compactação, o problema são algumas mensagens de 250MB que não conseguem ser serializadas. Overflow memory...

Sim o problema é a serialização e não o Memory Stream....

Quebrando a cabeça...

abaixo o codigo... da SOAP Extension...


using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Web.Services;
using System.Xml;
using ICSharpCode.SharpZipLib;
using System.Web.Services.Protocols;
using ICSharpCode.SharpZipLib.Zip;

namespace Lapuinka.WebServices
{
[AttributeUsage(AttributeTargets.Method)]
public class CompressionExtensionAttribute : SoapExtensionAttribute
{
// Fields
private int priority;

// Properties
public override Type ExtensionType
{
get
{
return typeof(CompressionExtension);
}
}

public override int Priority
{
get
{
return this.priority;
}
set
{
this.priority = value;
}
}
}



public class CompressionExtension : SoapExtension
{
// Fields
private bool _AtivaCompactacaoDescompactacao = false;
private bool _wsWriteEnvelope = false;
private Stream newStream;
private Stream oldStream;
private string tmpCompactacao = string.Empty;
private string tmpsoapEnvelopeIn = string.Empty;
private string tmpsoapEnvelopeOut = string.Empty;
private string tmpWriteEnvelope = string.Empty;

public string newFile = string.Empty;

// Methods
public override Stream ChainStream(Stream stream)
{
this.oldStream = stream;
newFile = setFileName(@"c:\soap\in\newFile");
this.newStream = new FileStream(newFile, FileMode.Create);
return this.newStream;
}

private void Copy(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}

public override object GetInitializer(Type t)
{
return typeof(CompressionExtension);
}

public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return attribute;
}

public override void Initialize(object initializer)
{
CompressionExtensionAttribute attribute = (CompressionExtensionAttribute)initializer;
}

private string MontaNomeArquivo(SoapMessage message, string preFixo)
{
string action = message.Action;
int startIndex = action.LastIndexOf("/") + 1;
action = action.Substring(startIndex, action.Length - startIndex).Replace(":", "_").Replace("/", "_").Replace("?", "_").Replace(" ", "_");
return (preFixo + "_" + action + "_" + Guid.NewGuid().ToString() + ".xml");
}

public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
case SoapMessageStage.AfterDeserialize:
return;

case SoapMessageStage.AfterSerialize:
if (this.AtivaCompactacaoDescompactacao)
{
this.Zip(message);
}
else
{
this.WriteOutput(message);
}
return;

case SoapMessageStage.BeforeDeserialize:
if (!this.AtivaCompactacaoDescompactacao)
{
this.WriteInput(message);
return;
}
this.Unzip(message);
return;
}
throw new Exception("invalid stage");
}

private byte[] Unzip(string stringToUnzip)
{
MemoryStream baseInputStream = new MemoryStream(Convert.FromBase64String(stringToUnzip));
MemoryStream stream2 = new MemoryStream();
ZipInputStream stream3 = new ZipInputStream(baseInputStream);
ZipEntry nextEntry = stream3.GetNextEntry();
byte[] buffer = new byte[0x800];
int count = 0x800;
while (true)
{
count = stream3.Read(buffer, 0, buffer.Length);
if (count > 0)
{
stream2.Write(buffer, 0, count);
}
else
{
return stream2.ToArray();
}
}
}

private void Unzip(SoapMessage message)
{
MemoryStream stream = new MemoryStream();
string str = this.MontaNomeArquivo(message, this.soapEnvelopeIn);
TextReader reader = new StreamReader(this.oldStream);
TextWriter writer = new StreamWriter(stream);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
stream = this.UnzipSoap(stream);
this.Copy(stream, this.newStream);
this.newStream.Position = 0L;
if (this.wsWriteEnvelope)
{
this.newStream.Position = 0L;
FileStream stream2 = new FileStream(str + ".xml", FileMode.Append, FileAccess.Write);
StreamWriter writer2 = new StreamWriter(stream2);
writer2.Flush();
this.newStream.Position = 0L;
this.Copy(this.newStream, stream2);
stream2.Close();
this.newStream.Position = 0L;
stream2 = new FileStream(str + ".zip", FileMode.Append, FileAccess.Write);
MemoryStream from = new MemoryStream();
writer2 = new StreamWriter(stream2);
this.newStream.Position = 0L;
from.Position = 0L;
from = this.ZipSoap(this.newStream);
writer2.Flush();
this.Copy(from, stream2);
stream2.Close();
}
this.newStream.Position = 0L;
}

public MemoryStream UnzipSoap(Stream streamToUnzip)
{
streamToUnzip.Position = 0L;
XmlTextReader reader = new XmlTextReader(streamToUnzip);
XmlDocument document = new XmlDocument();
document.Load(reader);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
for (XmlNode node = document.SelectSingleNode("//soap:Body", nsmgr).FirstChild.FirstChild; node != null; node = node.NextSibling)
{
if (node.InnerXml.Length > 0)
{
byte[] bytes = this.Unzip(node.InnerXml);
string str = Encoding.UTF8.GetString(bytes);
node.InnerXml = str;
}
}
MemoryStream outStream = new MemoryStream();
document.Save(outStream);
outStream.Position = 0L;
return outStream;
}

public void WriteInput(SoapMessage message)
{
this.Copy(this.oldStream, this.newStream);
this.newStream.Position = 0L;
if (this.wsWriteEnvelope)
{
FileStream stream = new FileStream(this.MontaNomeArquivo(message, this.soapEnvelopeIn), FileMode.Append, FileAccess.Write);
new StreamWriter(stream).Flush();
this.Copy(this.newStream, stream);
stream.Close();
this.newStream.Position = 0L;
}
}

public void WriteOutput(SoapMessage message)
{
if (this.wsWriteEnvelope)
{
this.newStream.Position = 0L;
FileStream stream = new FileStream(this.MontaNomeArquivo(message, this.soapEnvelopeOut), FileMode.Append, FileAccess.Write);
new StreamWriter(stream).Flush();
this.newStream.Position = 0L;
this.Copy(this.newStream, stream);
stream.Close();
}
this.newStream.Position = 0L;
this.Copy(this.newStream, this.oldStream);
this.newStream.Position = 0L;
}

private byte[] Zip(string stringToZip)
{
byte[] bytes = Encoding.UTF8.GetBytes(stringToZip);
MemoryStream baseOutputStream = new MemoryStream();
ZipOutputStream stream2 = new ZipOutputStream(baseOutputStream);
ZipEntry entry = new ZipEntry("ZippedFile");
stream2.PutNextEntry(entry);
stream2.SetLevel(9);
stream2.Write(bytes, 0, bytes.Length);
stream2.Finish();
stream2.Close();
return baseOutputStream.ToArray();
}

private void Zip(SoapMessage message)
{
if (this.wsWriteEnvelope)
{
this.newStream.Position = 0L;
string str = this.MontaNomeArquivo(message, this.soapEnvelopeOut);
FileStream stream = new FileStream(str + ".xml", FileMode.Append, FileAccess.Write);
StreamWriter writer = new StreamWriter(stream);
writer.Flush();
this.newStream.Position = 0L;
this.Copy(this.newStream, stream);
stream.Close();
stream = new FileStream(str + ".zip", FileMode.Append, FileAccess.Write);
writer = new StreamWriter(stream);
this.newStream.Position = 0L;
MemoryStream from = new MemoryStream();
from = this.ZipSoap(this.newStream);
from.Position = 0L;
writer.Flush();
this.Copy(from, stream);
stream.Close();
}
this.newStream.Position = 0L;
this.newStream = this.ZipSoap(this.newStream);
this.Copy(this.newStream, this.oldStream);
}

public MemoryStream ZipSoap(Stream streamToZip)
{
streamToZip.Position = 0L;
XmlTextReader reader = new XmlTextReader(streamToZip);
XmlDocument document = new XmlDocument();
document.Load(reader);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
for (XmlNode node = document.SelectSingleNode("//soap:Body", nsmgr).FirstChild.FirstChild; node != null; node = node.NextSibling)
{
if (node.InnerXml.Length > 0)
{
byte[] inArray = this.Zip(node.InnerXml);
node.InnerXml = Convert.ToBase64String(inArray);
}
}
MemoryStream outStream = new MemoryStream();
document.Save(outStream);
outStream.Position = 0L;
return outStream;
}

// Properties
public bool AtivaCompactacaoDescompactacao
{
get
{
if (this.tmpCompactacao == string.Empty)
{

this.tmpCompactacao = System.Configuration.ConfigurationManager.AppSettings["wsZip"];
}
if ((this.tmpCompactacao == null) | (this.tmpCompactacao == string.Empty))
{
this._AtivaCompactacaoDescompactacao = false;
}
else
{
this._AtivaCompactacaoDescompactacao = Convert.ToBoolean(this.tmpCompactacao);
}
return this._AtivaCompactacaoDescompactacao;
}
}

public string soapEnvelopeIn
{
get
{
if (this.tmpsoapEnvelopeIn == string.Empty)
{
this.tmpsoapEnvelopeIn = System.Configuration.ConfigurationManager.AppSettings["soapEnvelopeIn"];
}
if ((this.tmpsoapEnvelopeIn == null) | (this.tmpsoapEnvelopeIn == string.Empty))
{
this.tmpsoapEnvelopeIn = @"c:\soapEnvelopeIn";
}
return this.tmpsoapEnvelopeIn;
}
}

public string soapEnvelopeOut
{
get
{
if (this.tmpsoapEnvelopeOut == string.Empty)
{
this.tmpsoapEnvelopeOut = System.Configuration.ConfigurationManager.AppSettings["soapEnvelopeOut"];
}
if ((this.tmpsoapEnvelopeOut == null) | (this.tmpsoapEnvelopeOut == string.Empty))
{
this.tmpsoapEnvelopeOut = @"c:\soapEnvelopeOut.xml";
}
return this.tmpsoapEnvelopeOut;
}
}

public bool wsWriteEnvelope
{
get
{
if (this.tmpWriteEnvelope == string.Empty)
{
this.tmpWriteEnvelope = System.Configuration.ConfigurationManager.AppSettings["wsWriteEnvelope"];
}
if ((this.tmpWriteEnvelope == null) | (this.tmpWriteEnvelope == string.Empty))
{
this._wsWriteEnvelope = false;
}
else
{
this._wsWriteEnvelope = Convert.ToBoolean(this.tmpWriteEnvelope);
}
return this._wsWriteEnvelope;
}
}
private string setFileName(string preFixo)
{
string action = string.Empty;
int startIndex = action.LastIndexOf("/") + 1;
action = action.Substring(startIndex, action.Length - startIndex).Replace(":", "_").Replace("/", "_").Replace("?", "_").Replace(" ", "_");
return (preFixo + "_" + action + "_" + Guid.NewGuid().ToString() + ".xml");
}

}



}
Postar um comentário