I found this service host here at SO (http://stackoverflow.com/questions/5801128/flat-wsdl-for-wcf-4-service) and I have used it to pin point a property of a class that I want to be nillable=false instead of the default true. I managed to do that but now need to implement some logic to automate this feature.
Host:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Xml.Schema;
using ServiceDescription = System.Web.Services.Description.ServiceDescription;
namespace Thinktecture.ServiceModel.Extensions.Description {
public class FlatWsdl : IWsdlExportExtension, IEndpointBehavior {
public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context) {}
public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context) {
XmlSchemaSet schemaSet = exporter.GeneratedXmlSchemas;
ProcessNillable(schemaSet);
...
...
}
private static void WalkTheParticle(XmlSchemaParticle particle)
{
if (particle is XmlSchemaElement) {
XmlSchemaElement elem = particle as XmlSchemaElement;
Console.WriteLine(elem.Name);
if (elem != null && String.Compare(elem.Name, "name", false) == 0)
{
elem.IsNillable = false; //This works!
Console.WriteLine("Bazinga!");
}
if (elem.RefName.IsEmpty) {
XmlSchemaType type = (XmlSchemaType)elem.ElementSchemaType;
if (type is XmlSchemaComplexType) {
XmlSchemaComplexType ct = type as XmlSchemaComplexType;
if (ct.QualifiedName.IsEmpty) {
WalkTheParticle(ct.ContentTypeParticle);
}
}
}
}
else if (particle is XmlSchemaGroupBase)
//xs:all, xs:choice, xs:sequence
{
XmlSchemaGroupBase baseParticle = particle as XmlSchemaGroupBase;
foreach (XmlSchemaParticle subParticle in baseParticle.Items)
{
WalkTheParticle(subParticle);
}
}
}
private static void AddImportedSchemas(XmlSchema schema, XmlSchemaSet schemaSet, List<XmlSchema> importsList) { ... }
private static void RemoveXsdImports(XmlSchema schema) { ... }
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) {}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) {}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) {}
public void Validate(ServiceEndpoint endpoint) {}
}
}
Now, it works in the sample project and I need to put this in the actual project with around 80 contracts and each complex enough to have many properties. Some are required and some are not. I need to figure out how I can automate the cancellation of nillable=true for the required ones. I was hoping the putting the [DataMember(IsRequired=True)]
would help me locate the property in the WalkTheParticle()
method above. However, once inside the method, there is no real thing I can relate to make this work except the element's name and it will be a real headache to maintain a list of properties to mark as non-nillable. I'm looking for a better solution.