Let me first describe what my intention is, then go into my question.
I’m trying to build a system that communicates to a SOAP service where the SOAP request is somewhat unknown at runtime. Ultimately what I need to do is generate a SOAP request from unknown objects. I’ll be dynamically creating objects from scratch with the appropriate attributes and properties, then pass that to my service “request” method to be sent to the SOAP service. Here is the code I’ve been working with and then the error I’m receiving.
SOAP Client:
/// <summary>
/// GOSService proxy class
/// </summary>
[DebuggerStepThroughAttribute()]
[DesignerCategoryAttribute("code")]
[WebServiceBindingAttribute(Name = "ServiceSoapBinding", Namespace = "service.domain.com", ConformsTo = WsiProfiles.None)]
[SoapRpcService(RoutingStyle = SoapServiceRoutingStyle.RequestElement)]
public partial class TestService : SoapHttpClientProtocol
{
/// <summary>
/// Initializes a new instance of the TestService class.
/// </summary>
public TestService()
{
this.Url = "https://restsv01.domain.com/ServiceTest/services/TestService";
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(OnRemoteCertificateValidationCallback);
}
/// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication.
/// </summary>
/// <param name="sender">An object that contains state information for this validation.</param>
/// <param name="certificate">The certificate used to authenticate the remote party.</param>
/// <param name="chain">The chain of certificate authorities associated with the remote certificate.</param>
/// <param name="sslPolicyErrors">One or more errors associated with the remote certificate.</param>
/// <returns>A Boolean value that determines whether the specified certificate is accepted for authentication.</returns>
private bool OnRemoteCertificateValidationCallback(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
/// <summary>
///
/// </summary>
/// <param name="order"></param>
/// <returns></returns>
[SoapRpcMethodAttribute("", RequestNamespace = "service.domain.com", ResponseNamespace = "service.domain.com")]
[SampleSoap.LoggerSoapExtensionAttribute]
[return: SoapElementAttribute("requestReturn")]
public object request(object parm)
{
object[] results = this.Invoke("request", new object[] { parm });
return ((object)(results[0]));
}}
Test Model: (There won't be any pre-defined models, they will be dynamically generated. But for testing purposes, I'm using this model to test with)
[SerializableAttribute()]
[DebuggerStepThroughAttribute()]
[DesignerCategoryAttribute("code")]
[SoapTypeAttribute(Namespace = "http://entity.domain.com")]
public class ParentNode
{
private string nameField = "1";
[SoapElementAttribute(IsNullable = true)]
public string Name
{
get { return this.nameField; }
set { this.nameField = value; }
}
}
Test Call Code:
Services.Soap.Models.ParentNode parent = new Services.Soap.Models.ParentNode();
parent.Name = "John Doe";
Services.Soap.TestService service = new Services.Soap.TestService();
object resp = service.request(parent);
When I run this code, an error occurs at this line:
object[] results = this.Invoke("request", new object[] { parm });
This is the error:
The type Services.Soap.Models+ParentNode was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
Now, if I change the parameter of the service “request” method to a strong type, the request builds fine and is passed to the SOAP service, like so.
public object request(ParentNode parm)
I’ve tried probably 50 things to get this to work, including passing the Type as a parameter to the request method and creating a “dynamic” instance of the object to pass.
public object request(object parm, Type t)
{
dynamic converted = Convert.ChangeType(parm, t);
object[] results = this.Invoke("request", new object[] { converted });
return ((object)(results[0]));
}
This didn’t work because “converted” was still considered an object type.
I’ve also tried intercepting the soap envelope in the “GetWriterForMessage” method so I can build my own envelope, but I wasn’t able to make use of that.
So my question is, how can I get the SOAP request to build successfully with a parameter type of object? Is there maybe another approach I should take to make my architecture work correctly?