I have been searching the web for the last 2-3 days and remain unable to figure this one out - so now I come to you guys in the hopes that you know a solution.
I am trying to make a mocked SOAP service for a client and have made a SOAP service in visual studio. The following is the code for the SOAP action that needs to be mocked.
[WebService(Namespace = "http://mynamespace.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class MyServiceStub1 : System.Web.Services.WebService, MyServiceBindingSoap
{
[WebMethod]
[SoapDocumentMethod(Action = "http://mynamespace.com/MySoapAction",
ParameterStyle = SoapParameterStyle.Bare)]
[return: System.Xml.Serialization.XmlElementAttribute("SomeWrapperXML")]
public MyActualResponseType MyServiceRequest(
[XmlElement(ElementName = "MyRequestName")] MyServiceRequestType myServiceRequest)
{
return new MyActualResponseType();
}
And I get the following response
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SomeWrapperXML">
<MyActualResponseType>
</MyActualResponseType>
</SomeWrapperXML>
</soap:Body>
</soap:Envelope>
However, my clients expect the response to look like this
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<MyActualResponseType>
</MyActualResponseType>
</soap:Body>
</soap:Envelope>
And since I cannot change the code on my clients side, I have to fix this from my side. Is there any way I can avoid getting the XML tag "SomeWrapperXML" in my response?
Setting XmlElementAttribute("") did not help and avoiding it altogether will just make it default to something else.
I have also looked at the MSDN post for altering the SOAP message, but that solution seems a bit hacky.
I ended up changing the return type of my mocked service to a field in the original return type.
In my example I needed to return the type MyActualResponseType according to the code generated by svcutil. However MyActualResponseType only contained one field/getter for a type MyActualResponse. I changed my SOAP method to this:
[WebMethod]
[SoapDocumentMethod(Action = "http://mynamespace.com/MySoapAction",
ParameterStyle = SoapParameterStyle.Bare)]
[return: System.Xml.Serialization.XmlElementAttribute("MyActualResponseType")]
public MyActualResponse MyServiceRequest(
[XmlElement(ElementName = "MyRequestName")] MyServiceRequestType myServiceRequest)
{
return new MyActualResponse();
}
Notice the [return: which makes it look like it is actually returning the type MyActualResponseType.
This solution still feels like a bit of hack, but it seems to work fine for my needs.
Related
I am creating a web service to receive data from another source which will have the following format when the request is made.
The SOAP request for the call has been provided (see below) so I need to accept the data in this format. It is also going into an existing set of web services which can not be updated at this time. They are written in C# using the older style WSDL Web Service.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetDepartmentData xmlns="webservice.localhost/">
<ID>123</ID>
<Name>John Smith</Name>
<Departments>
<DepartmentID>1</DepartmentID>
<DepartmentID>2</DepartmentID>
<DepartmentID>4</DepartmentID>
</Departments>
<Phone>0123456789</Phone>
</GetDepartmentData>
</soap:Body>
</soap:Envelope>
I need to take this request then extract all the data and send into a SQL stored procedure for processing.
Everything is pretty straight forward apart from the 'Departments' section as I am unsure of the correct data type to use and how best to handle this as all the other web service just have single non-complex data types.
The code for the method is as follows:
[WebMethod]
public string GetDepartmentData(int ID, string Name, ???? Departments, string Phone)
{
// Do something with the input here
}
My plan is to convert the Departments into either a XML data type which I can send into SQL and then split into a table or create a delimited string from the DepartmentID values and then split that in SQL. Not sure yet but that will be the easier part.
The problem I am having is I am unsure of the best way to create the method to handle the SOAP request I am being sent.
Thanks.
I'm trying to update some WSE code to use WCF, and I'm running into trouble with one service in particular. When I generated my proxy class from the WSDL, it creates methods with no parameters or return type. The parameters were easy enough to fix -- saved the autogenerated References.cs file as a new file, added the parameter to both the generated interface and generated client, and it works. Using Fiddler, I can see that the traffic is as expected.
What I'm finding very vexing is that WCF seems to be just throwing away the response payload. I can see it coming back over the wire, but it seems to just vanish somewhere in the deep dark crevices of WCF. No errors or warnings, just gone.
I'm kind of at my wits end here. I'd really appreciate any suggestions on how to figure out where the response is going.
The method in the client (this used to return void; I've set it to object[] in hopes I could get something that I could cast):
public object[] getAddress(string user) {
return base.Channel.getAddress(user);
}
The method in the interface:
[System.ServiceModel.OperationContractAttribute(Action = "https://xxxxxx/Address#getAddress", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)]
object[] getAddress(string user);
The raw XML response (redacted) looks something like this:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getAddressResponse xmlns="https://xxxxx/Address">
<ArrayOfAddress arrayType="xsd:Address[3]" soapenc:arrayType="xsd:anyType[3]" xsi:type="Array">
<Address>
<street xsi:type="xsd:string">3rd</street>
</Address>
<Address>
<street xsi:type="xsd:string">1st</street>
</Address>
<Address>
<street xsi:type="xsd:string">2nd</street>
</Address>
</ArrayOfAddress>
</getAddressResponse>
</soap:Body>
Thanks in advance!
EDIT: I was unable to get this resolved, and there are only a few methods on this service, so I ended up just manually interacting with the service using WebClient, bypassing WCF.
Returning object[] isn't going to give you something you can cast. WCF on the client needs to know the possible concrete types to deserialize the response. I'd expect an exception though.
To fix this you should go ahead and create the Address data contract class.
Im trying to setup a connect listener. I am currently using a C# WCF Service that Im hosting on Azure. Im able to hit my service method but the response from docusign is null every time. In the logs, the envelope status xml has values but it is just not sent or not deserialized correctly. Im not sure what I am doing wrong and there doesnt seem to be any solid examples of a SOAP implementation anywhere. Can anyone help? The WSDL can be viewed here http://docusignconnectservice.azurewebsites.net/Service.svc?wsdl
Service Implentation
public string DocuSignConnectUpdate(DocuSignAPI.DocuSignEnvelopeInformation envelopeInformation)
{
string envelopeId = "";
if (envelopeInformation == null) return "Envelope is null";
else return envelopeInformation.EnvelopeStatus.EnvelopeID;
}
Service Contract
[ServiceContract(Namespace = "http://www.docusign.net/API/3.0")]
public interface IService
{
[OperationContract]
[XmlSerializerFormatAttribute]
string DocuSignConnectUpdate(DocuSignAPI.DocuSignEnvelopeInformation envelopeInformation);
[OperationContract]
string HelloWorld(string inputString);
DocuSign log entry
10/6/2014 1:30:12 AM Envelope Data:<?xml version="1.0" encoding="utf-8"?><DocuSignEnvelopeInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.docusign.net/API/3.0"><EnvelopeStatus><RecipientStatuses><RecipientStatus><Type>Signer</Type><Email>email</Email><UserName>Username</UserName><RoutingOrder>1</RoutingOrder><Sent>2014-10-05T17:49:36.58</Sent><DeclineReason xsi:nil="true" /><Status>Sent</Status><RecipientIPAddress /><CustomFields /><AccountStatus>Active</AccountStatus><RecipientId>2a10b0ab-63f1-4df9-9258-36b97b5db120</RecipientId></RecipientStatus></RecipientStatuses><TimeGenerated>2014-10-05T18:30:09.644588</TimeGenerated><EnvelopeID>6d7692e6-3f5c-4889-914f-942b2bd83447</EnvelopeID><Subject> Signature Request on Document</Subject><UserName>Username</UserName><Email>email</Email><Status>Sent</Status><Created>2014-10-05T17:49:35.503</Created> <Sent>2014-10-05T17:49:36.613</Sent><ACStatus>Original</ACStatus><ACStatusDate>2014-10-05T17:49:35.503</ACStatusDate><ACHolder></ACHolder><ACHolderEmail></ACHolderEmail><ACHolderLocation>DocuSign</ACHolderLocation><SigningLocation>Online</SigningLocation><SenderIPAddress>ip </SenderIPAddress><EnvelopePDFHash /><CustomFields /><AutoNavigation>true</AutoNavigation><EnvelopeIdStamping>true</EnvelopeIdStamping><AuthoritativeCopy>false</AuthoritativeCopy><DocumentStatuses><DocumentStatus><ID>1</ID><Name>F_1040.pdf</Name><TemplateName /><Sequence>1</Sequence></DocumentStatus></DocumentStatuses></EnvelopeStatus></DocuSignEnvelopeInformation>
10/6/2014 1:30:12 AM Response: <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><DocuSignConnectUpdateResponse xmlns="http://www.docusign.net/API/3.0"><DocuSignConnectUpdateResult>Envelope is null</DocuSignConnectUpdateResult></DocuSignConnectUpdateResponse></s:Body> </s:Envelope>
I think there is problem with your classes for mapping of XML.
You can configure your classes with XML response you have with online tools like http://xmltocsharp.azurewebsites.net/ and use XMLSerializer to parse that XML into object .
I have created a solution.
Added the WSDL file.
This keeps on popping following error "Length Required".
I tried with the above code in the post (, but seems that is not working.
Where do we specify the Operation name here?
-- Anand
Before getting it to work in java c# .net etc you need to get the SOAP xml correct.
The operation name is added as a tag in the soap body element.
Say for example your operation name is createMyOTRSTicket as specified in OTRS UI Web Service.
The SOAP request sent should look something like this like this:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<createMyOTRSTicket xmlns="WS">
<UserLogin>MyUserName</UserLogin>
<Password>MyPassword</Password>
<Queue>'some queue name'</Queue>
<State>'some state name'</State>
<Priority>1</Priority>
<!-- ...etc.. -->
<Article>
<Subject>some subject</Subject>
<Body>some body</Body>
<ContentType>text/plain; charset=utf8</ContentType>
</Article>
</createMyOTRSTicket >
</soap:Body>
</soap:Envelope>
See the API for what elements are require and which are optional for TicketCreate here
The Soap Message should be sent to /nph-genericinterface.pl/Webservice/CreateTicketWS where CreateTicketWS is the name of the Web Service.
Also note that the attribute xmlns="WS" refers to the Namespace you specify in "Network Transport" config also locatred in the GenericInterface Web Service Management.
I hope this helps you. Sorry it might be a bit confusing for someone new to SOAP and OTRS.
I'm having some problems with one webservice that i'm working with. I generated a proxy class with wsdl.exe that comes with .net framework. But that webservice return a header that isnt not mapped by the wsdl. I must map the header sop because it contains some properties that i have to read and work with. how can i read the soap's header collection?
Ex.:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header xmlns="http://xml.amadeus.com/ws/2009/01/WBS_Session-2.0.xsd">
<Session>
<SessionId>545784545</SessionId>
<SequenceNumber>1</SequenceNumber>
<SecurityToken>asd7a87sda89sd45as4d5a4</SecurityToken>
</Session>
</soap:Header>
<soap:Body>
<TAM_Altea_Seguranca_AutenticarRS xmlns="http://xml.amadeus.com/2009/04/TAM/TAM_Altea_Seguranca_AutenticarRS_2.0">
<statusDoProcesso>
<codigoDoStatus>P</codigoDoStatus>
</statusDoProcesso>
</TAM_Altea_Seguranca_AutenticarRS>
</soap:Body>
</soap:Envelope>
I need to read the SOAP:HEADER -> Session.
Have you tried this?
source: Handle SOAP Headers Required by an XML Web Service Client
public class MyWebService
{
public SoapUnknownHeader[] unknownHeaders;
[WebMethod]
[SoapHeader("unknownHeaders")]
public string MyWebMethod()
{
foreach (SoapUnknownHeader header in unknownHeaders)
{
// process headers
}
// handle request
}
}
See this page for detailed instructions on defining custom SOAP headers. There only seem to be VB.net code examples, but it should be easy enough to translate the principles in C#.