One of my recent project works is to integrate our CRM solution with a few data sources from different vendors, which requires me to develop an ETL component to download incremental update files from SFTP sites before processing them in our CRM application.
Since there is no support of SFTP in .NET framework itself, I have to look for alternative solution, so I ended up with the open source library called SharpSSH, which is pretty promising.
I was very happy that it worked with my first try on my local development VPC image which is on Windows Server 2003, 32-bit edition. But as soon as I promoted my ETL component to our UAT environment which is on Windows Server 2008 R2 (of course, 64-bit system), I ran into a "Bad Data" error when my component was trying to make connection to the SFTP site.
I did a little Google search, and found the solution here. I followed snowcoder's instructions, made a bunch of changes, and recompiled the library. Then everything worked for me on the 64-bit system.
Here are the download links, I hope that they could save you some time if you ever need this component (There were some errors in snowcode's original code he pasted there probably due to HTML formatting issue):
SharpSSH-1.1.1.13 Library (DLLs only)
SharpSSH-1.1.1.13 Source Code
[DISCLAIMER] I am by no means an expert on hardcore networking or cryptology programming (I have no intention to become one either at this moment), I am posting the recompiled library just for your convenience. All credit goes to Tamir Gal, snowcoder, and Mono Project. The license should stay as whatever it is originally.
[Further Note - Updated December 2011] There is another open source library in the community called SSH.NET, which you might want to check out. The library has got support for .NET 3.5, .NET 4.0, Windows Phone, Silverlight respectively. It looks very promising, and it has been actively maintained by the author.
Hope this helps!
Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts
Friday, November 26, 2010
Sunday, May 02, 2010
C#: A Simple Pseudo-Serializable Generic <string, string> Dictionary
Today I was trying to find an easy way to convert XML string to a C# generic <string, string> dictionary and the other way around. I wasn't able to find anything easy and simple enough, so I decided to write my own code to do the job.
I knew the first option would be XML Serializer, but there are a couple of issues that I don’t appreciate using it. First, I want to keep the xml file really simple, I don't like a full-blown XML file, as the more complex the XML file is, the easier people make mistakes when making changes to the XML file. Second, I want to be able to customize the dictionary root node's name, item node's name, and also key/value attribute's name, which doesn't seem to be viable using XML serializer. Lastly, C# generic dictionary is not serializable out-of-box, so it has to be custom serialization code like this one.
To be more specific, what I want is actually very simple, I want my code to convert the following XML string to a C# generic dictionary, and other way around the other time.
Hope this helps.
I knew the first option would be XML Serializer, but there are a couple of issues that I don’t appreciate using it. First, I want to keep the xml file really simple, I don't like a full-blown XML file, as the more complex the XML file is, the easier people make mistakes when making changes to the XML file. Second, I want to be able to customize the dictionary root node's name, item node's name, and also key/value attribute's name, which doesn't seem to be viable using XML serializer. Lastly, C# generic dictionary is not serializable out-of-box, so it has to be custom serialization code like this one.
To be more specific, what I want is actually very simple, I want my code to convert the following XML string to a C# generic dictionary, and other way around the other time.
<settings> <setting key="setting1" value="value1" /> <setting key="setting2" value="value2" /> </settings>Here is the class that I implemented based on C# Dictionary class.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
public class SimpleDictionary : Dictionary<string, string>
{
/**
* A Simple pseudo-serializable generic <string, string> dictionary
* @author Daniel Cai, http://danielcai.blogspot.com/
*/
private readonly string xsdMarkup = @"
<xs:schema id='dictionary' xmlns='' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
<xs:element name='{0}'>
<xs:complexType>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element name='{1}'>
<xs:complexType>
<xs:attribute name='{2}' type='xs:string' />
<xs:attribute name='{3}' type='xs:string' />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>";
private string _rootNodeName;
private string _itemNodeName;
private string _keyAttributeName;
private string _valueAttributeName;
public SimpleDictionary()
: this("dictionary", "item", "key", "value")
{
}
public SimpleDictionary(string rootNodeName, string itemNodeName, string keyAttributeName, string valueAttributeName)
{
_rootNodeName = rootNodeName;
_itemNodeName = itemNodeName;
_keyAttributeName = keyAttributeName;
_valueAttributeName = valueAttributeName;
xsdMarkup = string.Format(xsdMarkup, rootNodeName, itemNodeName, keyAttributeName, valueAttributeName);
}
public void FromXml(string xml)
{
Clear();
XDocument xdoc = XDocument.Parse(xml);
ValidateXml(xdoc);
var dictionaryItemQuery = from element in xdoc.Root.Elements()
where
element.Name == _itemNodeName &&
element.Attributes().Count() == 2 &&
element.FirstAttribute.Name == _keyAttributeName &&
element.LastAttribute.Name == _valueAttributeName
select element;
foreach (XElement keyValuePair in dictionaryItemQuery)
{
Add(keyValuePair.Attribute(_keyAttributeName).Value,
keyValuePair.Attribute(_valueAttributeName).Value);
}
}
public string ToXml()
{
XElement xElement = new XElement(_rootNodeName,
from key in this.Keys
select new XElement(_itemNodeName,
new XAttribute(_keyAttributeName, key),
new XAttribute(_valueAttributeName, this[key]))
);
return xElement.ToString();
}
private void ValidateXml(XDocument xdoc)
{
bool isValid = true;
string errorMessage = string.Empty;
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", XmlReader.Create(new StringReader(xsdMarkup)));
xdoc.Validate(schemas, (sender, e) =>
{
errorMessage = string.Format("Validation error: {0}", e.Message);
isValid = false;
}, true);
if (!isValid)
{
throw new XmlSchemaValidationException(errorMessage);
}
}
}
To convert a XML string into a generic <string, string> dictionary, you can write your code as below:SimpleDictionary simpleDictionary = new SimpleDictionary("settings", "setting", "key", "value");
simpleDictionary.FromXml(@"
<settings>
<setting key='key1' value='value1' />
<setting key='key2' value='value2' />
</settings>");
// Your dictionary is now ready for use.
To convert a <string, string> dictionary into XML string, the code should be something like this: SimpleDictionary simpleDictionary = new SimpleDictionary();
simpleDictionary.Add("key1", "value1");
simpleDictionary.Add("key2", "value2");
string xml = simpleDictionary.ToXml();
Console.WriteLine(xml);
/* Output:
<dictionary>
<item key='key1' value='value1' />
<item key='key2' value='value2' />
</dictionary>"
*/
It's worth noting that the class has two constructors, the default one will use a default set of names (dictionary as the root node name, item as the dictionary item node name, key as the item's key attribute name, and value as the item's value attribute name). If you want the nodes and attributes to be called differently, you may call the other constructor by providing specific names. Hope this helps.
Labels:
C#,
Generics,
LINQ,
Serialization,
XML
Subscribe to:
Posts (Atom)