/// <summary>
/// Creates an <see cref="InterfaceContract"/> object by loading the contents in a specified
/// WSDL file.
/// </summary>
/// <param name="wsdlFileName">Path of the WSDL file to load the information from.</param>
/// <returns>An instance of <see cref="InterfaceContract"/> with the information loaded from the WSDL file.</returns>
/// <remarks>
/// This method first loads the content of the WSDL file to an instance of
/// <see cref="System.Web.Services.Description.ServiceDescription"/> class. Then it creates an
/// instance of <see cref="InterfaceContract"/> class by loading the data from that.
/// This method throws <see cref="WsdlLoadException"/> in case of a failure to load the WSDL file.
/// </remarks>
public static InterfaceContract GetInterfaceContract(string wsdlFileName)
{
// Try to load the service description from the specified file.
System.Web.Services.Description.ServiceDescription srvDesc = null;
try
{
srvDesc = System.Web.Services.Description.ServiceDescription.Read(
wsdlFileName);
}
catch (Exception ex)
{
throw new WsdlLoadException(
"Could not load service description from the specified file.",
ex);
}
// Validate the WSDL before proceeding.
bool isHttpBinding = false;
if (!ValidateWsdl(srvDesc, ref isHttpBinding))
{
throw new WsdlNotCompatibleForRoundTrippingException("Not a valid file for round tripping");
}
// Start building the simplified InterfaceContract object from the
// .Net Fx ServiceDescription we created.
InterfaceContract simpleContract = new InterfaceContract();
// Initialize the basic meta data.
simpleContract.ServiceNamespace = srvDesc.TargetNamespace;
simpleContract.ServiceDocumentation = srvDesc.Documentation;
// Try to get the service namespace from the service description.
simpleContract.ServiceName = srvDesc.Name;
// If it was not found in the service description. Then try to get it from the
// service. If it is not found their either, then try to get it from binding.
if (simpleContract.ServiceName == null || simpleContract.ServiceName == "")
{
if (srvDesc.Services.Count > 0 && srvDesc.Services[0].Name != null &&
srvDesc.Services[0].Name != "")
{
simpleContract.ServiceName = srvDesc.Services[0].Name;
}
else
{
simpleContract.ServiceName = srvDesc.Bindings[0].Name;
}
}
// Set the http binding property.
simpleContract.IsHttpBinding = isHttpBinding;
// Initialize the imports.
foreach (XmlSchema typeSchema in srvDesc.Types.Schemas)
{
foreach (XmlSchemaObject schemaObject in typeSchema.Includes)
{
XmlSchemaImport import = schemaObject as XmlSchemaImport;
if (import != null)
{
SchemaImport simpleImport = new SchemaImport();
simpleImport.SchemaNamespace = import.Namespace;
simpleImport.SchemaLocation = import.SchemaLocation;
simpleContract.Imports.Add(simpleImport);
}
}
}
// Initialize the types embedded to the WSDL.
simpleContract.SetTypes(GetSchemaElements(srvDesc.Types.Schemas, srvDesc.TargetNamespace));
// Initialize the operations and in/out messages.
PortType ptype = srvDesc.PortTypes[0];
if (ptype != null)
{
foreach (FxOperation op in ptype.Operations)
{
// Create the Operation.
Operation simpleOp = new Operation();
simpleOp.Name = op.Name;
simpleOp.Documentation = op.Documentation;
if (op.Faults != null)
{
foreach (OperationFault fault in op.Faults)
{
FxMessage faultMessage = srvDesc.Messages[fault.Message.Name];
if (faultMessage == null)
{
// WSDL modified.
string message = string.Format("Could not find the fault message '{0}'", fault.Message.Name);
throw new WsdlModifiedException(message);
}
MessagePart part = faultMessage.Parts[0];
if (part != null)
{
Message message = new Message();
message.Name = faultMessage.Name;
message.Element.ElementName = part.Element.Name;
message.Element.ElementNamespace = part.Element.Namespace;
message.Documentation = faultMessage.Documentation;
simpleOp.MessagesCollection.Add(message);
simpleOp.Faults.Add(message);
}
}
}
if (op.Messages.Input != null)
{
FxMessage inMessage = srvDesc.Messages[op.Messages.Input.Message.Name];
if (inMessage == null)
{
// WSDL modified.
throw new WsdlModifiedException("Could not find the message");
}
MessagePart part = inMessage.Parts[0];
if (part != null)
{
// Create the input message.
Message simpleInMessage = new Message();
simpleInMessage.Name = inMessage.Name;
simpleInMessage.Element.ElementName = part.Element.Name;
simpleInMessage.Element.ElementNamespace = part.Element.Namespace;
simpleInMessage.Documentation = inMessage.Documentation;
simpleOp.MessagesCollection.Add(simpleInMessage);
simpleOp.Input = simpleInMessage;
}
else
{
// WSDL is modified.
throw new WsdlModifiedException("Could not find the message part");
}
}
if (op.Messages.Output != null)
{
FxMessage outMessage = srvDesc.Messages[op.Messages.Output.Message.Name];
if (outMessage == null)
{
// WSDL is modified.
throw new WsdlModifiedException("Could not find the message");
}
MessagePart part = outMessage.Parts[0];
if (part != null)
{
// Create the output message.
Message simpleOutMessage = new Message();
simpleOutMessage.Name = outMessage.Name;
simpleOutMessage.Element.ElementName = part.Element.Name;
simpleOutMessage.Element.ElementNamespace = part.Element.Namespace;
simpleOutMessage.Documentation = outMessage.Documentation;
simpleOp.MessagesCollection.Add(simpleOutMessage);
simpleOp.Output = simpleOutMessage;
}
else
{
// WSDL is modified.
throw new WsdlModifiedException("Could not find the message part");
}
// Set the message direction.
simpleOp.Mep = Mep.RequestResponse;
}
else
{
simpleOp.Mep = Mep.OneWay;
}
// Finally add the Operation to Operations collection.
simpleContract.OperationsCollection.Add(simpleOp);
}
}
else
{
// WSDL is modified.
throw new WsdlModifiedException("Could not find the portType");
}
// Initialize the message headers and header messages.
System.Web.Services.Description.Binding binding1 = srvDesc.Bindings[0];
if (binding1 != null)
{
// Find the corresponding Operation in the InterfaceContract, for each OperationBinding
// in the binding1.Operations collection.
foreach (OperationBinding opBinding in binding1.Operations)
{
foreach (Operation simpleOp in simpleContract.OperationsCollection)
{
if (simpleOp.Name == opBinding.Name)
{
if (opBinding.Input != null)
{
// Enumerate the message headers for the input message.
foreach (ServiceDescriptionFormatExtension extension in opBinding.Input.Extensions)
{
SoapHeaderBinding inHeader = extension as SoapHeaderBinding;
if (inHeader != null)
{
// Create the in header and add it to the headers collection.
MessageHeader simpleInHeader = new MessageHeader();
FxMessage inHeaderMessage = srvDesc.Messages[inHeader.Message.Name];
if (inHeaderMessage == null)
{
// WSDL modified.
throw new WsdlModifiedException("Could not find the message");
}
simpleInHeader.Name = inHeaderMessage.Name;
simpleInHeader.Message = inHeaderMessage.Name;
simpleOp.MessagesCollection[0].HeadersCollection.Add(simpleInHeader);
// Create the in header message and put it to the Operation's messeages collection.
MessagePart part = inHeaderMessage.Parts[0];
if (part != null)
{
Message simpleInHeaderMessage = new Message();
simpleInHeaderMessage.Name = inHeaderMessage.Name;
simpleInHeaderMessage.Element.ElementName = part.Element.Name;
simpleInHeaderMessage.Element.ElementNamespace = part.Element.Namespace;
simpleOp.MessagesCollection.Add(simpleInHeaderMessage);
}
else
{
// WSDL is modified.
throw new WsdlModifiedException("Could not find the message part");
}
}
}
}
else
{
// WSDL modified.
throw new WsdlModifiedException("Could not find the operation binding");
}
if (simpleOp.Mep == Mep.RequestResponse && opBinding.Output != null)
{
// Enumerate the message headers for the output message.
foreach (ServiceDescriptionFormatExtension extension in opBinding.Output.Extensions)
{
SoapHeaderBinding outHeader = extension as SoapHeaderBinding;
if (outHeader != null)
{
// Create the in header and add it to the headers collection.
MessageHeader simpleOutHeader = new MessageHeader();
FxMessage outHeaderMessage = srvDesc.Messages[outHeader.Message.Name];
if (outHeaderMessage == null)
{
// WSDL is modified.
throw new WsdlModifiedException("Could not find the message");
}
simpleOutHeader.Name = outHeaderMessage.Name;
simpleOutHeader.Message = outHeaderMessage.Name;
simpleOp.MessagesCollection[1].HeadersCollection.Add(simpleOutHeader);
// Create the out header message and put it to the Operation's messeages collection.
MessagePart part = outHeaderMessage.Parts[0];
if (part != null)
{
Message simpleOutHeaderMessage = new Message();
simpleOutHeaderMessage.Name = outHeaderMessage.Name;
simpleOutHeaderMessage.Element.ElementName = part.Element.Name;
simpleOutHeaderMessage.Element.ElementNamespace = part.Element.Namespace;
simpleOp.MessagesCollection.Add(simpleOutHeaderMessage);
}
else
{
// WSDL is modified.
throw new WsdlModifiedException("Could not find the message part");
}
}
}
}
else if (simpleOp.Mep == Mep.RequestResponse)
{
// WSDL modified.
throw new WsdlModifiedException("Could not find the operation binding");
}
}
}
}
}
// Check for the "Generate service tags" option.
if (srvDesc.Services.Count == 1)
{
simpleContract.NeedsServiceElement = true;
}
// Turn on the SOAP 1.2 binding if available.
foreach (System.Web.Services.Description.Binding binding in srvDesc.Bindings)
{
if (binding.Extensions.Find(typeof(Soap12Binding)) != null)
{
simpleContract.Bindings |= InterfaceContract.SoapBindings.Soap12;
}
}
return simpleContract;
}