Partial answer/hack to the question.

1) Manually change the generated proxy class for "outdata". (this is bad)

Replace:

[System.Xml.Serialization.SoapElementAttribute(Data Type="integer")]
public string outint;

With:
public int outint;


2) Change the perl service (this is ugly)

Replace:
return bless \%outdata;

With:
return SOAP::Data->name("outargs" =>
\SOAP::Data->value(SOAP::Data->name("outstr" => $outdata
{ 'outstr' }),
SOAP::Data->name("outint" => $outdata
{ 'outint' })));


This alters the output from:
<SOAP-ENV:Body>
<namesp1:complexArgsResponse xmlns:namesp1="sample_class">
<sample_class xsi:type="namesp2:sample_class">
<outstr xsi:type="xsd:string">string part</outstr>
<outint xsi:type="xsd:int">54321</outint>
</sample_class>
</namesp1:complexArgsResponse>
</SOAP-ENV:Body>

Note: "sample_class" instead of "outargs", and the extra namesp2:

to:
<SOAP-ENV:Body>
<namesp1:complexArgsResponse xmlns:namesp1="sample_class">
<outargs>
<outstr xsi:type="xsd:string">string part</outstr>
<outint xsi:type="xsd:int">54321</outint>
</outargs>
</namesp1:complexArgsResponse>
</SOAP-ENV:Body>

Now the .NET client is happy...

3) Note: The perl client still works.

*** Follow-up question (will clean up and post on a new thread):
Is there an easier way to get the desired output without the compound
SOAP::Data statements?