Showing posts with label CSharp. Show all posts
Showing posts with label CSharp. Show all posts

Thursday, May 28, 2009

Empty Actions when mocking Java Web Service

I get the
System.InvalidOperationException: The operations methodX and methodY have the same action ().  Every operation must have a unique action value”, when trying to mock a Java Web Service with Rhino Mocks in CSharp.

The WSDL-file that was downloaded from the Java Web Service declared an empty soap action for each exported operation.
For example:

<operation name="aMethod">
  <soap:operation soapAction="" /> 
  <input>
   <soap:body use="literal" /> 
  </input>
  <output>
   <soap:body use="literal" /> 
  </output>
  <fault name="MyWebServiceException">
   <soap:fault name="MyWebServiceException" use="literal" /> 
  </fault>
</operation>

WCF uses the action to dispatch an incoming message to the correct method, see Action Property. Each method must have a unique action value.

I solved it by downloading the WSDL-file and remove all soap action declarations:

<soap:operation soapAction="" />

I ran the svcutil.exe on the changed WSDL-file.
WCF then creates unique action values in the service interface file, and the service can be mocked (as I described in Mocking WCF service).

Friday, May 15, 2009

Creating disconnected ADO Recordset in C#

I had some problems to create a disconnected ADO Recordset in C#. Finally I get it right.

public static Recordset CreateDisconnectedRecordset()
{
    // Create new recordset
    var rs = new Recordset();

    // Add some updatable fields
    rs.Fields.Append("name", DataTypeEnum.adVarChar, 20, FieldAttributeEnum.adFldUpdatable, Missing.Value);
    rs.Fields.Append("country", DataTypeEnum.adVarChar, 20, FieldAttributeEnum.adFldUpdatable, Missing.Value);

    // Open recordset
    rs.Open(Missing.Value, Missing.Value, CursorTypeEnum.adOpenUnspecified, LockTypeEnum.adLockUnspecified, 0);

    // Add data
    rs.AddNew(Missing.Value, Missing.Value);
    rs.Fields["name"].Value = "Anders";
    rs.Fields["country"].Value = "Sweden";
    rs.Update(Missing.Value, Missing.Value);

    return rs;
}

Monday, February 9, 2009

Convert ADO Stream and Recordset to XML

When working with older applications, i.e. pre-.NET, its helpful with functions that converts ADO Streams and Recordset to XML and vice versa. Especially when older applications should be migrated or communicate with .NET applications and its prefered to rewrite as little as possible. Another approach would be to use JSON.

Anyway, here are a couple of converting functions that are useful.

Recordset <-> XML
/// <summary>
/// Convert XML to recordset
/// </summary>
/// <param name="sXML"></param>
/// <returns>Recordset</returns>
public static Recordset recordsetFromXML(string sXML)
{
    if (string.IsNullOrEmpty(sXML))
    {
        // Nothing to convert
        return null;
    }

    // Open an ADO Stream
    var oStream = new Stream();
    oStream.Open(Missing.Value, ConnectModeEnum.adModeUnknown,
                 StreamOpenOptionsEnum.adOpenStreamUnspecified,
                 "", "");

    // Load the XML string into stream
    oStream.WriteText(sXML, StreamWriteEnum.adWriteChar);
    oStream.Position = 0;

    // Create empty recordset
    var oRecordset = new Recordset();

    // Read the XML stream
    oRecordset.Open(oStream, Missing.Value,
                    CursorTypeEnum.adOpenUnspecified,
                    LockTypeEnum.adLockUnspecified, 0);
    oStream.Close();

    //Return the recordset
    return oRecordset;
}

/// <summary>
/// Convert recordset to XML
/// </summary>
/// <param name="oRecordset"></param>
/// <returns>String</returns>
public static string recordsetToXML(Recordset oRecordset)
{
    string xmlString = "";

    if (oRecordset != null)
    {
        // Load recordset into stream
        var oStream = new Stream();
        oRecordset.Save(oStream, PersistFormatEnum.adPersistXML);

        // Get the XML
        xmlString = oStream.ReadText(oStream.Size);
    }

    return xmlString;
}
Stream <-> XML
/// <summary>
/// Convert XML to stream
/// </summary>
/// <param name="sXML"></param>
/// <returns>Stream</returns>
public static Stream streamFromXML(string sXML)
{
    // Load XML into XmlDocument
    var oXML = new XmlDocument();
    oXML.InnerXml = sXML;

    // Get the STREAM element
    var aNode = oXML.GetElementsByTagName("STREAM")[0];

    // Create a binary stream
    var oStream = new Stream();
    oStream.Type = StreamTypeEnum.adTypeBinary;
    oStream.Open(Missing.Value, ConnectModeEnum.adModeUnknown,
                 StreamOpenOptionsEnum.adOpenStreamUnspecified,
                 "", "");

    // Load XML
    oStream.Write(Convert.FromBase64String(aNode.InnerXml));
    oStream.Position = 0;

    return oStream;
}

/// <summary>
/// Convert stream to XML
/// </summary>
/// <param name="oStream"></param>
/// <returns>String</returns>
public static string streamToXML(Stream oStream)
{
    // Create XmlDocument
    var oXML = new XmlDocument();
    oXML.AppendChild(oXML.CreateProcessingInstruction("xml", "version='1.0'"));

    // Add STREAM element to hold the binary data
    XmlElement oElem = oXML.CreateElement("STREAM");

    // Define type of value
    XmlAttribute dt = oXML.CreateAttribute("dt", "dt", "urn:schemas-microsoft-com:datatypes");
    dt.Value = "bin.base64";
    oElem.SetAttributeNode(dt);

    // Convert stream data to string
    oElem.InnerXml = Convert.ToBase64String((byte[])oStream.Read(-1));
    oXML.AppendChild(oElem);

    // Return Xml
    return oXML.InnerXml;
}