How can I directly craft the XML content that goes into a fault detail?

Getting control over the detail element doesn't have to mean crafting the fault message yourself. While WCF requires that the fault detail be serializable using a data contract, remember that DataContractSerializer treats XmlElement as a special primitive type. This allows you to construct arbitrary content using XmlElement when your content can be represented as a rooted document. Due to the automatic conversion process of FaultException to a fault message, you don't need to construct a data contract to act as a wrapper.

Here's a sample that builds some content in an XmlElement and uses it to construct a fault. I made the method return a Message so that I could look at the response more easily but you can use any contract you want.

[ServiceContract]
public interface IMyService
{
[OperationContract]
Message Fail();
}

public class MyService : IMyService
{
public Message Fail()
{
XmlDocument document = new XmlDocument();
XmlElement root = document.CreateElement("tag");
root.SetAttribute("attributeName", "value");
XmlElement subtag = document.CreateElement("moretags");
subtag.InnerText = "blah";
root.AppendChild(subtag);
throw new FaultException<XmlElement>(root);
}
}

public class Program
{
static void Main(string[] args)
{
string address = "http://localhost:8000/";
BasicHttpBinding binding = new BasicHttpBinding();
ServiceHost host = new ServiceHost(typeof(MyService), new Uri(address));
host.AddServiceEndpoint(typeof(IMyService), binding, "");
host.Open();
ChannelFactory<IMyService> factory = new ChannelFactory<IMyService>(binding);
IMyService proxy = factory.CreateChannel(new EndpointAddress(address));
Message response = proxy.Fail();
Console.WriteLine(response.ToString());
Console.ReadLine();
host.Close();
}
}

That code produces a fault message that looks like the following.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="en-US">The creator of this fault did not specify a Reason.</faultstring>
<detail>
<tag attributeName="value">
<moretags>blah</moretags>
</tag>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>

Depending on how much hand-crafting you want, XmlDocument lets you simplify the process even further. For example, you could generate the same message from simple XML completely put together by hand.

XmlDocument document = new XmlDocument();
document.LoadXml("<tag attributeName=\"value\"><moretags>blah</moretags></tag>");
throw new FaultException<XmlElement>(document.FirstChild as XmlElement);

Next time: DataMember Best Practices