February 2008 - Posts

I've built a wrapper application that abstracts Salesforce.com integration with our CRM, and came across a bit of an obscure bug yesterday.

The issue came up when assigning a .NET DateTime value to a DateTime field in the generated SFDC proxy:

 

SFDCObject__c _sfdcObject = new SFDCObject__c();
_sfdcObject.Created_Date__c = DateTime.Now;
_sfdcObject.Created_Date__cSpecified = true;

 

When assigning the .NET DateTime value to the _sfdcObject.Created_Date__c member, an error is thrown:

 

ex = {"'2008-02-20' is not a valid value for the type xsd:dateTime"}

 

A bit of digging brought up this thread on the Salesforce.com developer discussion boards.  It turns out that the culprit is actually a bug in .NET 2.0 (quote is from the discussion thread):

If a schema contains both “xsd:date” with nillable=true and “xsd:dateTime” with nillable=true, we will import either both as “date” or both as “dateTime”. In your case, both probably get imported as “date”, hence the time component cases a failure. This is a known bug and there is a hotfix available (KB 925272), available by calling PSS.

The hotfix would need to be installed on all servers and dev machines, which seems like a non-optimal solution, so I went with the workaround of hand-modifying the WSDL to replace all instances of "xsd:date" with "xsd:dateTime".  This worked for me because my application only needs to work with SFDC objects that are defined as "xsd:dateTime".  If you have an app that needs to work with both xsd:date and xsd:dateTime typed fields, you will most likely need to install the hotfix from Microsoft, or move your solution to .NET 3.0 or 3.5.

Posted by gstarbuck | with no comments

One of the primary reasons I am writing this blog is to give back to the community -- technical blogs and message board archives have saved my bacon many times, so my plan is, whenever I spend an hour or two figuring something out and I wasn't able to find any concise resources about it, I'll write a post on it so that the next person may stumble across it and save some time.

Yesterday I was working on calling cmd.exe from within .NET, and had to piece together a few things from various places.  Here is the code I ended up with.  I've added comments to explain the reason for each line of code -- hopefully someone will find this helpful.

 

using System;
using System.Diagnostics;

namespace Utilities
{
    public class Command
    {
        public static string ExecuteCmd(string arguments)
        {
            // Create the Process Info object with the overloaded constructor
            // This takes in two parameters, the program to start and the
            // command line arguments.
            // The arguments parm is prefixed with "@" to eliminate the need
            // to escape special characters (i.e. backslashes) in the
            // arguments string and has "/C" prior to the command to tell
            // the process to execute the command quickly without feedback.
            ProcessStartInfo _info =
                new ProcessStartInfo("cmd", @"/C " + arguments);

            // The following commands are needed to redirect the
            // standard output.  This means that it will be redirected
            // to the Process.StandardOutput StreamReader.
            _info.RedirectStandardOutput = true;

            // Set UseShellExecute to false.  This tells the process to run
            // as a child of the invoking program, instead of on its own.
            // This allows us to intercept and redirect the standard output.
            _info.UseShellExecute = false;

            // Set CreateNoWindow to true, to supress the creation of
            // a new window
            _info.CreateNoWindow = true;

            // Create a process, assign its ProcessStartInfo and start it
            Process _p = new Process();
            _p.StartInfo = _info;
            _p.Start();

            // Capture the results in a string
            string _processResults = _p.StandardOutput.ReadToEnd();

            // Close the process to release system resources
            _p.Close();

            // Return the output stream to the caller
            return _processResults;
        }
    }
}

 

Posted by gstarbuck | 12 comment(s)
More Posts