XmlSerialization with CLR

Hi,

I have created the CLR Trigger Project. In that Project i'm refering one external.dll which is also deployed in the same database. This external.dl uses one method to serialize the data and send it to the server through socket.(The connection for the socket is already established). For this to work i know i need to turn on the Generate serialization assembly from the Build of Project Properties. After i did this i have the external.xmlserializer.dll in my Bin/Debug folder. Then i
Created the 3 Assemblies as below:

//This is the Original name of the dlls

CREATEASSEMBLY CommonStructures
FROM'C:\Inetpub\wwwroot\Vinoth\CommonStructures\bin\Debug\CommonStructures.dll'
WITH PERMISSION_SET= UNSAFE

CREATEASSEMBLY CSXmlSerializers
FROM'C:\Inetpub\wwwroot\Vinoth\CommonStructures\bin\Debug\CommonStructures.XmlSerializers.dll'
WITH PERMISSION_SET= UNSAFE

CREATEASSEMBLY CLR
FROM'C:\Inetpub\wwwroot\Vinoth\CLR Trigger\CLRTrigger\bin\Debug\CLRTrigger.DLL'
WITH PERMISSION_SET= UNSAFE

//This is the main dll where i'm refereing the CommonStructures dll. When i insert any row in my table i'm getting the following error.

Error:-

Cannot load dynamically generated serialization assembly. In some hosting environments assembly load functionality is restricted, consider using pre-generated serializer. Please see inner exception for more information. at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, CompilerParameters parameters, Evidence evidence)
at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, CompilerParameters parameters, Assembly assembly, Hashtable assemblies)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, Type[] extraTypes)
at CommonStructures.CommonHelper.TCPForwardRequestPost(String uRL, Object obj) System.IO.FileLoadException: LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host.
at System.Reflection.Assembly.nLoadImage(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence evidence, StackCrawlMark& stackMark, Boolean fIntrospection)
at System.Reflection.Assembly.Load(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence securityEvidence)
at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames)
at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources)
at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, String[] sources)
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromSource(CompilerParameters options, String[] sources)
at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, CompilerParameters parameters, Evidence evidence).
I reffered this article alsohttp://blogs.msdn.com/sqlclr/archive/2005/07/25/Vineet.aspx

How can i solve this issue.If anybody knows the solution please let me know to solve it.

Thanks,
Vinoth

[4806 byte] By [Vinoth] at [2008-2-20]
# 1
I need some more context here. Which is the assembly that has the method to serialize the data? You need to generate the serialization assembly for that and register it in the database. Could you please try generating the serialization assembly (using sgen) for CLRTrigger and register that in the database as well?
If possible can you please share a sample code that reproduces the problem?
Which CTP of SQL Server are you using?

Thanks,
-Vineet.

VineetRao-Microsoft at 2007-9-9 > top of Msdn Tech,SQL Server,.NET Framework inside SQL Server...
# 2

Hi Vineet,

The following C# Code(CommonStructures nameSpace) Contains One method TCPForwardRequestPost. In this method i'm serializing the input type object(obj) and sending it to the server. In this method the control is coming upto the WriteLog("before typeof").The next line is XmlSerializer xs = new XmlSerializer(typeof(ArrayList),extraTypes);After that line i have written one writelog. The control is not coming to the next writelog. But its throwing the following exception.

WriteLog("before typeof");
XmlSerializer xs = new XmlSerializer(typeof(ArrayList),extraTypes);
WriteLog("going to serialize");

Error:
Cannot load dynamically generated serialization assembly. In some hosting environments assembly load functionality is restricted, consider using pre-generated serializer. Please see inner exception for more information.

at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, CompilerParameters parameters, Evidence evidence)
at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, CompilerParameters parameters, Assembly assembly, Hashtable assemblies)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace) at System.Xml.Serialization.XmlSerializer..ctor(Type type)


at CommmonStructures.CommonHelper.TCPForwardRequestPost(String uRL, Object obj) System.IO.FileLoadException: LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host. at System.Reflection.Assembly.nLoadImage(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence evidence, StackCrawlMark& stackMark, Boolean fIntrospection) at System.Reflection.Assembly.Load(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence securityEvidence) at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames) at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources) at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, String[] sources)
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromSource(CompilerParameters options, String[] sources)
at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, CompilerParameters parameters, Evidence evidence)

I'm using April CTP. My main CLRTrigger Project Contains the following Code for the CLRTrigger Method. In this CLRTrigger method i'm calling the CommonHelper.TCPForwardRequestPost method.For this to work First I deployed both CommonStructures.dll and CommonStructures.XMLSerializers.dll in to the database then in my CLRTrigger Project i added that(2 dll's) references to my project. Then build my project and then deployed my project.


CREATE ASSEMBLY CommonStructures
FROM 'C:\Inetpub\wwwroot\Vinoth\CLR Trigger\CommmonStructures\bin\Debug\CommmonStructures.dll'
WITH PERMISSION_SET = UNSAFE

CREATE ASSEMBLY CSXmlSerializers
FROM 'C:\Inetpub\wwwroot\Vinoth\CLR Trigger\CommmonStructures\bin\Debug\CommmonStructures.XmlSerializers.dll'
WITH PERMISSION_SET = UNSAFE

CREATE ASSEMBLY CLR
FROM 'C:\Inetpub\wwwroot\Vinoth\CLR Trigger\CLRTrigger\bin\Debug\CLRTrigger.DLL'
WITH PERMISSION_SET = UNSAFE

I tried Safe and External_Access also. No result.

Generating the Serializationa assembly i tried in both ways(sgen.exe and in Project Properties Generate Serialization assembly On also) No result.


public static void CLRTrigger()
{
Triggers objTriggers = new Triggers();
ArrayList objArrayList = new ArrayList();
try
{
objTriggers.Connection(true);
#region Get RURL and SiteURL
SqlTriggerContext sqlTrigger = SqlContext.TriggerContext;
SqlPipe sqlPipe = SqlContext.Pipe;
SqlCommand cmd = objTriggers.con.CreateCommand();
if (sqlTrigger.TriggerAction == TriggerAction.Insert || sqlTrigger.TriggerAction ==

TriggerAction.Update)
cmd.CommandText = "select DirName,LeafName from inserted";
else if (sqlTrigger.TriggerAction == TriggerAction.Delete)
cmd.CommandText = "select DirName,LeafName from Deleted";
cmd.Connection = objTriggers.con;
SqlDataReader sdr = cmd.ExecuteReader();
string DirName = "", LeafName = "", siteUrl = "", RURL = "";
while (sdr.Read())
{
DirName = sdr["DirName"].ToString();
LeafName = sdr["LeafName"].ToString();
}
objTriggers.WriteLog("DirName :" + DirName + " LeafName :" + LeafName + " Event :" +

sqlTrigger.TriggerAction.ToString());
sdr.Close();
cmd.CommandText = "select FullUrl from sites";
try
{
SqlDataReader objSdr = cmd.ExecuteReader();
while (objSdr.Read())
{
//siteUrl = objSdr["FullUrl"].ToString().Substring(0,

objSdr["FullUrl"].ToString().LastIndexOf("/"));
siteUrl = objSdr["FullUrl"].ToString();
}
objSdr.Close();
}
catch (Exception e)
{
objTriggers.WriteLog("<<<:" + e.Message);
}
RURL = siteUrl + DirName + "/" + LeafName;
string hostName = "192.168.1.10";
objTriggers.WriteLog(hostName + " " + siteUrl + DirName);
#endregion

switch (sqlTrigger.TriggerAction)
{
case TriggerAction.Insert:
#region Insert
if (LeafName.IndexOf(".") != -1 && LeafName != "OUID.txt" && LeafName != "")
{

objArrayList.Add("ParentUniqueID");
objTriggers.WriteLog(siteUrl + DirName);
objTriggers.WriteLog("RURL :" + siteUrl + DirName);
ArrayList ParentUniqueID =

(ArrayList)CommonHelper.TCPForwardRequestPost(hostName, objArrayList);
for (int i = 0; i < ParentUniqueID.Count; i++)
{
objTriggers.WriteLog("ParentUniqueID " +

ParentUniqueIDIdea.ToString());
}
if (ParentUniqueID != null && ParentUniqueID.Count > 0)
{
objArrayList.Clear();
objArrayList.Add("CheckParentGrain");
objArrayList.Add(siteUrl + DirName);
string ParentGrain =

(string)CommonHelper.TCPForwardRequestPost(hostName, objArrayList);
objTriggers.WriteLog("ParentGrain :" + ParentGrain);
byte[] content = objTriggers.GetFileContent(DirName, LeafName);
uint checkSum =

objTriggers.calculateCRC32(Encoding.Default.GetString(content));
objTriggers.WriteLog("checkSUm :" + checkSum);
objArrayList.Clear();
objArrayList.Add("SetID");
objArrayList.Add(RURL);
string FileUniqueID =

(string)CommonHelper.TCPForwardRequestPost(hostName, objArrayList);
objTriggers.WriteLog("File UID :" + FileUniqueID);
objTriggers.WriteLog("Type of Modification :" +

sqlTrigger.TriggerAction.ToString());

}
}
else if (LeafName != "OUID.txt" && LeafName != "")
{

objArrayList.Add("ParentUniqueID");
objArrayList.Add(siteUrl + DirName);
objTriggers.WriteLog("RURL :" + siteUrl + DirName);
ArrayList ParentUniqueID =

(ArrayList)CommonHelper.TCPForwardRequestPost(hostName, objArrayList);
for (int i = 0; i < ParentUniqueID.Count; i++)
{
objTriggers.WriteLog("ParentUniqueID " +

ParentUniqueIDIdea.ToString());
}
if (ParentUniqueID != null && ParentUniqueID.Count > 0)
{
objArrayList.Clear();
objArrayList.Add("CheckParentGrain");
objArrayList.Add(siteUrl + DirName);
string ParentGrain =

(string)CommonHelper.TCPForwardRequestPost(hostName, objArrayList);
objTriggers.WriteLog("ParentGrain :" + ParentGrain);
uint checkSum = objTriggers.calculateCRC32(LeafName);
objTriggers.WriteLog("checkSUm :" + checkSum);
objArrayList.Clear();
objArrayList.Add("SetID");
objArrayList.Add(RURL);
string FolderUniqueID =

(string)CommonHelper.TCPForwardRequestPost(hostName, objArrayList);
objTriggers.WriteLog("FolderUniqueID :" + FolderUniqueID);
objTriggers.WriteLog("Type of Modification :" +

sqlTrigger.TriggerAction.ToString());
}
}
break;
#endregion
}
objTriggers.Connection(false);
}
catch (Exception e)
{
objTriggers.WriteLog(e.Data + " " + e.Message + " " + e.Source + " " + e.StackTrace + " " + e.TargetSite);
}
}


This is the Code for CommonStructures.dll where i'm referring the TCPForwardRequesPost in my CLRTrigger Project.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
using System.Net;
using System.Net.Sockets;
using System.Xml.Serialization;
using System.Threading;
using System.Collections;
using System.IO;

namespace CommmonStructures
{
public enum TypeOfChange { UNDEFINED = -1, MODIFIED, DELETED, CREATED }
[XmlInclude(typeof(ChangedObject)), XmlInclude(typeof(ResourceURL))]
public class TransclusionUpdates
{
public ArrayList changedObjectsAL;
public ResourceURL[] urls;
public TransclusionUpdates()
{
this.changedObjectsAL = null;
this.urls = null;
}
public TransclusionUpdates(ArrayList changedObjectsAL, ResourceURL[] urls)
{
this.changedObjectsAL = changedObjectsAL;
this.urls = urls;
}
}

[XmlInclude(typeof(DiffNode))]
public class TransclusionDifferences
{
public string srcRID;
public ArrayList diffNodesAL;
public TransclusionDifferences()
{
this.diffNodesAL = null;
}

public TransclusionDifferences(string srcRID, ArrayList diffNodesAL)
{
this.srcRID = srcRID;
this.diffNodesAL = diffNodesAL;
}
}
public class ChangedObject
{
public string resTID;
public string resGUID;
public string srcTID;
public string srcRID;
public uint checkSum;
public TypeOfChange typeOfChange;
public ArrayList contentAL;
public bool isVisited;
public ChangedObject()
{
this.contentAL = null;
this.isVisited = false;
}
public ChangedObject(string resTID, string resGUID, string srcTID, string srcRID, uint checkSum, TypeOfChange typeOfChange,

ArrayList contentAL, bool isVisited)
{
this.resTID = resTID;
this.resGUID = resGUID;
this.srcTID = srcTID;
this.srcRID = srcRID;
this.checkSum = checkSum;
this.typeOfChange = typeOfChange;
this.contentAL = contentAL;
this.isVisited = isVisited;
}
}
public class ResourceURL
{
public string rID;
public string rURL;
public ResourceURL()
{
this.rURL = null;
}
public ResourceURL(string rID, string rURL)
{
this.rID = rID;
this.rURL = rURL;
}
}
public class DiffNode
{
public string uniqueID;
public uint checkSum;
public TypeOfChange typeOfChange;
public ArrayList ancestorsAL;
public string grainUID;
public DiffNode()
{
this.uniqueID = null;
this.checkSum = 0;
this.ancestorsAL = null;
this.grainUID = null;
}
public DiffNode(string uniqID, uint checkSum, TypeOfChange typeOfChange, ArrayList ancestorsAL, string grainUID)
{
this.uniqueID = uniqID;
this.checkSum = checkSum;
this.typeOfChange = typeOfChange;
this.ancestorsAL = ancestorsAL;
this.grainUID = grainUID;
}
}

public class CommonHelper
{
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
private static object response = null;
private static void Connect(EndPoint remoteEP, Socket client)
{
client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
connectDone.Set();
}
catch (Exception e)
{}
}

private static void Send(Socket client, byte[] sendData)
{
client.BeginSend(sendData, 0, sendData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
sendDone.Set();
}
catch (Exception e)
{}
}
private static void Receive(Socket client)
{
try
{
StateObject state = new StateObject();
state.receiveSocket = client;
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
receiveDone.WaitOne();
}
catch (Exception e)
{}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.receiveSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallbac(ReceiveCallback), state);
}
else
{
if (state.buffer.Length > 1)
{
XmlSerializer xs = new XmlSerializer(typeof(ArrayList));
MemoryStream stream = new MemoryStream(state.buffer);
response = ((ArrayList)xs.Deserialize(stream))[0];
}
receiveDone.Set();
}
}
catch (Exception e)
{}
}
private static Type[] extraTypes = { typeof(DiffNode), typeof(ChangedObject), typeof(TransclusionUpdates),

typeof(TransclusionDifferences) };

public static object TCPForwardRequestPost(string uRL, object obj)

{

try

{

IPAddress localAddress = IPAddress.Parse(uRL);

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

IPEndPoint remoteEndPoint = new IPEndPoint(localAddress, 56789);

WriteLog("Connecting!! ");

Connect(remoteEndPoint, socket);

WriteLog("Connected");

MemoryStream mStream = new MemoryStream();

WriteLog("before typeof");

XmlSerializer xs = new XmlSerializer(typeof(ArrayList),extraTypes);

WriteLog("going to serialize");

xs.Serialize(mStream, obj);

WriteLog("serialized the content");

byte[] sendData = mStream.GetBuffer();

WriteLog("DataLength :" + sendData.Length.ToString());

Send(socket, sendData);

WriteLog("Successfully Send..");

Receive(socket);

socket.Close();

return response;

}

catch (Exception e)

{

WriteLog(e.Message + " " + e.StackTrace + " " + e.InnerException);

return null;

}

}

private static void WriteLog(string str)

{

try

{

StreamWriter writer = new StreamWriter(@"C:\Inetpub\wwwroot\Listenerlog.txt", true);

writer.WriteLine(str);

writer.Close();

}

catch (Exception e)

{

WriteLog(e.Message);

}

}

}
public class StateObject
{
public Socket receiveSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
}
}
[/code]
Vinnet i have given my entire code. How can i proceed further. Guide me in this regard.

Thanks,
Vinoth

Vinoth at 2007-9-9 > top of Msdn Tech,SQL Server,.NET Framework inside SQL Server...
# 3

The reason you cannot use sgen to pre-generate serializer for ArrayList is that it means that you have to run sgen.exe on mscorlib.dll, and this will fail because you do not have Microsoft key to sign the generated assembly.
The pre-generated serializer for ArrayList has to be named mscorlib.XmlSerializers and signed with Microsoft key, which makes it Framework assembly
The workaround here is to wrap the ArrayList in some other type, it is going to be user assembly and you can choose any key you want to sign it, or not sign it at all. E.g.:

public class ArrayListWrapper
{
public ArrayList arrayList = new ArrayList();
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder();
foreach(object arrayListItem in arrayList)
{
stringBuilder.AppendLine((string)arrayListItem);
}
return stringBuilder.ToString();
}
public void Add(object obj)
{
arrayList.Add(obj);
}
}

Another solution is:

1. Use sgen to generate serializer for ArrayList only with /kepp switch:

sgen mscorlib.dll /t:System.Collections.ArrayList /k /out:.

2. Compile generated source into an assembly

3. in the user code instead of using

new XmlSerializer(typeof(ArrayList));

use

new ArrayListSerializer(); // typed serializer from the assembly in #2

Please let me know if that works.

Thanks,
-Vineet.

VineetRao-Microsoft at 2007-9-9 > top of Msdn Tech,SQL Server,.NET Framework inside SQL Server...
# 4
Yes Vineet,

Now its Working fine. Thanks for ur help.

Thanks,
Vinoth

Vinoth at 2007-9-9 > top of Msdn Tech,SQL Server,.NET Framework inside SQL Server...

SQL Server

Site Classified