Friday, December 21, 2007

Custom Soap Fault

Here's some code to Build a custom soap exception so you don't return a standard Exception from a web service. I'm sure there are better ways to do this these days, but I've been using this for 4 years.

#region BuildSoapFault
///
/// Build a custom soap error message
///

/// The string to add to the message
/// A Soap Exception
///
private SoapException BuildSoapFault(string message)
{
// Build the detail element of the SOAP fault.
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
System.Xml.XmlNode node = doc.CreateNode(XmlNodeType.Element,
SoapException.DetailElementName.Name,SoapException.DetailElementName.Namespace);
// Build specific details for the SoapException.
// Add first child of detail XML element.
System.Xml.XmlNode details =
doc.CreateNode(XmlNodeType.Element, "mySpecialInfo1",
"http://tempuri.org/");
System.Xml.XmlNode detailsChild =
doc.CreateNode(XmlNodeType.Element, "childOfSpecialInfo",
"http://tempuri.org/");
details.AppendChild(detailsChild);
// Add second child of detail XML element with an attribute.
System.Xml.XmlNode details2 = doc.CreateNode(XmlNodeType.Element, "mySpecialInfo2",
"http://tempuri.org/");
XmlAttribute attr = doc.CreateAttribute("t", "attrName",
"http://tempuri.org/");
attr.Value = "attrValue";
details2.Attributes.Append(attr);
// Append the two child elements to the detail node.
node.AppendChild(details);
node.AppendChild(details2);
SoapException se = new SoapException(message,
SoapException.ServerFaultCode,
Context.Request.Url.AbsoluteUri ,
node);
return se;
}
#endregion

Monday, December 17, 2007

More frequent updates

This is my penance post.

I will update this blog more frequently.
I will update this blog more frequently.
I will update this blog more frequently.
I will update this blog more frequently.
I will update this blog more frequently.
I will update this blog more frequently.
I will update this blog more frequently.
I will update this blog more frequently.
I will update this blog more frequently.
I will update this blog more frequently.

Okay, I cheated. I love cut and paste.

Closing Connections in a WCF Broker Proxy

The followinde is pretty standard WCF code. The critical step is the using statement. Failure to do this step will hang the server once you have reached your max connections, and will result in bizarre behavior.


public ATCFlightPlan GetATCFlightPlan(int fltsegid)
{
ATCFlightPlan atcFlightPlan = null;
//Create connection to FlightPlanService
WSHttpBinding httpBind = new WSHttpBinding();
ChannelFactory flightPlanProcessServiceFactory = new ChannelFactory(httpBind, primaryEndpoint);
IFlightPlanProcessManager flightPlanProcessManagerClient = flightPlanProcessServiceFactory.CreateChannel();

using (flightPlanProcessManagerClient as IDisposable)
{
try
{
atcFlightPlan = flightPlanProcessManagerClient.GetATCFlightPlan(fltsegid);
}
catch (FaultException ex)
{
EventLog.WriteEntry("FlightPlanBroker", "Fault Exception thrown from Primary FlightPlanSvc: " + ex.ToString());
throw;
}
catch (Exception ex)
{
EventLog.WriteEntry("FlightPlanBroker", "Error communicating with Primary FlightPlanSvc: " + ex.ToString());

ChannelFactory backupFlightPlanProcessServiceFactory = new ChannelFactory(httpBind, backupEndpoint);
IFlightPlanProcessManager backupFlightPlanProcessManagerClient = backupFlightPlanProcessServiceFactory.CreateChannel();

using (backupFlightPlanProcessManagerClient as IDisposable)
{
try
{
atcFlightPlan = backupFlightPlanProcessManagerClient.GetATCFlightPlan(fltsegid);
FailOverEndpoints();
}
catch (FaultException innEx)
{
EventLog.WriteEntry("FlightPlanBroker", "Fault Exception thrown from Backup FlightPlanSvc: " + innEx.ToString());
throw;
}
catch (Exception innEx)
{
EventLog.WriteEntry("FlightPlanBroker", "Error communicating with backup FlightPlanSvc: " + innEx.ToString());
throw;
}
}
}
}
return atcFlightPlan;
}

Tuesday, September 11, 2007

Getting Started with SQL Server

After many years of trying to work SQLServer into my daily life, I've finally got a project that I can use it. Of course, I still need to attach back to the Informix database where most of my data resides. The following code snippet allows SQLServer to pass a preformatted query through to Informix as a Linked Server.


USE [Dispatch]
GO
/****** Object: StoredProcedure [dbo].[ExecOpenQuery] Script Date: 09/11/2007 08:47:54 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ExecOpenQuery] (
@TSQL varchar(8000)
)
AS
SET NOCOUNT ON

-- Build OpenQuery command
DECLARE @OpenQuery varchar(4000)
SET @OpenQuery = 'SELECT * FROM OPENQUERY(IfxVisops, '''

-- Display Dynamic SQL
print @OpenQuery + @TSQL

-- Execute SQL
exec(@OpenQuery + @TSQL)

RETURN

Tuesday, August 28, 2007

Debugging WCF Services

Here's a link to a some very useful information on debugging WCF Services

Tuesday, August 21, 2007

Javascript to stop Editing of a Textbox

Here's a quick bit of Javascript to stop someone from entering data into a text box. Why would you need this when you can use a label or a read only text box?

1. The label is not a control you can get the .text from with code behind.
2. The read only text box will always return String.Empty when referenced with the code behind

Warning, that this code does not stop the delete key from being hit.



//Do not allow user to enter data into Fleet Type
function FleetKeyPress()
{
window.event.keyCode = 0;
}

and

{{ asp:textbox onkeypress="javascript:FleetKeyPress();" id="txtFleetType" cssclass="txtbox" columns="8" runat="server" }}

Monday, August 20, 2007

MIDL_USER_ALLOCATE and strcpy_s

I recently converted one of our very critical applications from Visual Studio 2003 to Visual Studio 2005. The application is RPC based and written in C++. In doing the conversion, I inadvertantly introduced a bug (is there any other way to introduce a bug?).

The original code looked like the following

*szResponse = (unsigned char *) midl_user_allocate(sizeof(unsigned char *) * (strlen(szTempResp)+1));
strcpy((char *)*szResponse, szTempResp);

After my conversion, the code looked like the following

*szResponse = (unsigned char *) midl_user_allocate(sizeof(unsigned char *) * (strlen(szTempResp)+1));
strcpy_s((char *)*szResponse, sizeof(szResponse)-1, szTempResp);


What it should have looked like is the following (I hope)

*szResponse = (unsigned char *) midl_user_allocate(sizeof(unsigned char *) * (strlen(szTempResp)+1));
memset(*szResponse, '\0', sizeof(unsigned char *) * (strlen(szTempResp)+1));
strcpy_s((char *)*szResponse, sizeof(unsigned char *) * strlen(szTempResp), szTempResp);


The problem was with the sizeof command. The szResponse variable is just a pointer, and therefore only a long is allocated, not a array of longs.

This one had me baffled for a couple of months, mainly because it would never show up in debug mode on my PC, but hit at random intervals in production under release mode. To compound the problem, the try catch block the code was in was missing a catch (...) clause, which meant the error fell through to the application instead of the thread handler, and caused a fatal error in the application.

Just another reason to convert to managed code!

Sunday, August 19, 2007

Current Projects

My current projects involve a lot of old projects, that is, bringing old code up to new standards, bringing them in-line with the new build process and making sure we actually have the code for all the old programs. It's not as easy as it sounds, but it is pretty valuable to the organization, though it's a hard sell to the business customers and to management.

Most of the old code I work on is in C++, though some is a simple upgrade from C# in .NET Framework 1.1 to C# in .NET Framework 2.0. In some places, we have converted code from C++ to C# with the C++ doing a COM Callable Wrapper call to the C#. This has proven to not be the most easy way to do things, nor the most reliable, and we spend a lot of time trying to debug the interface. In my view, the shorter the amount of time you can can spend supporting that dual code environments, the better.

Welcome!

Welcome to DevScape, my journal of my exploits through the world of Software Engineering. Here, I hope to keep both a record of the projects I've worked on, the tricks and tips that I've used to solve problems, and a list of websites which I find essential to getting work done.

My focus, as of now, is .NET and C#. I'll also have stuff on C++, Informix, Accurev, CruiseControl.NET and the plethora of other languages and tools I use on the job. If you find any any 'Good God, that's wrong!' stuff out here, let me know.