I have a basic web service that parses XML sent from a client. The web service works fine but I was asked to remove elements from the WSDL file generated by the web service. Is it even possible to do this?
Here are the first lines from the WSDL file:
<wsdl:definitions targetNamespace="localhost">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="localhost">
<s:element name="HTTPWebService">
<s:complexType/>
</s:element>
<s:element name="HTTPWebServiceResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="HTTPWebServiceResult">
<s:complexType mixed="true">
<s:sequence>
<s:any/>
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="HTTPWebServiceSoapIn">
<wsdl:part name="parameters" element="tns:HTTPWebService"/>
</wsdl:message>
Is it possible to remove the lines <s:element name="HTTPWebServiceResponse"> and it's contents, and <s:element name="HTTPWebServiceResponse">?
WSDL is a system generated xml file and editing its content may cause unexpected behavior and may not be load during introspecting. You cannot edit those lines without understanding what functionality these elements do.
Related
I am adding a Service Reference to a Third-Party-ASMX Webservice in my VS2015 or VS2017 Project (Net 4.6.1).
I do this with the normal Userinterface in Visual Studio (Rightclick --> Add new Service Reference). I use the default settings and everything seems to work except that i am not happy with the generated classes.
According to the WSDL i am expecting to use the methods like this:
ServiceSoapClient ssc = new ServiceSoapClient();
object response = ssc.getEmployees("xxx", "yyy", "zzz");
But what i get is classes that i have to use like this:
ServiceSoapClient ssc = new ServiceSoapClient();
getEmployeesResponse response = ssc.getEmployees(
new getEmployeesRequest
{
Body = new getEmployeesRequestBody { Division = "xxx", Username = "yyy", Password = "zzz" }
});
Every Method needs one Request-Parameter, which itself has a Body-Element. The Body-Element has all the necessary Parameters.
The Method is defined like that when opened in the browser:
<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>
<getEmployees xmlns="xxx">
<division>string</division>
<Username>string</Username>
<Password>string</Password>
</getEmployees>
</soap:Body>
</soap:Envelope>
That is the information for this Method in the WSDL:
<s:element name="getEmployees">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="division" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="Username" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="Password" type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="getEmployeesResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="getEmployeesResult" type="tns:XMLResponse"/>
</s:sequence>
</s:complexType>
</s:element>
<wsdl:operation name="getEmployees">
<wsdl:input message="tns:getEmployeesSoapIn"/>
<wsdl:output message="tns:getEmployeesSoapOut"/>
</wsdl:operation>
<wsdl:operation name="getEmployees">
<soap:operation soapAction="http://xxx/getEmployees" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
Why do i not get a method with the three parameters of type string? Am i even able to control this on client-side or is there a common mistake?
When i provide the Webservices by myself or use other services i never had this problem before.
I found the reason. In the settings of the "Service Reference" you have to activate "Generate assynchronous operations".
If in the WSDL definition of one of my web methods, I have something like this:
<s:complexType name="ExampleType">
<s:sequence>
<s:element name="Element1" type="s:string" maxOccurs="1" minOccurs="0"/>
<s:element name="Element2" type="s:string" maxOccurs="1" minOccurs="0"/>
<s:element name="Element3" type="s:string" maxOccurs="1" minOccurs="0"/>
</s:sequence>
</s:complexType>
Is it possible to change the order that these elements are returned to the client?
Method being called is something like this:
public static IList<ExampleType> WebMethod(string number)
{
IList<ExampleType> listOfExampleType = GetExampleType();
return listOfExampleType;
}
As I am new to WSDL, WCF and SOAP, I have no real clue how I should structure the WSDL.
My problem right now is that when a user logs in using their username//password, the server should respond with data owned by the user. Lets say the data that wants to be sent back are:
MatterID
MatterTitle
MatterText
MatterDate
The problem is that each user can own more than 1 matter and my problem is that I have no idea how to parse more than the first Matter that the server send as response. My WSDL is structured something like this:
IN:
username
password
OUT:
int MatterID
str MatterTitle
str MatterText
int MatterDate
Am I doing it wrong? Should I respond with a list instead containing all the data? Or is there a way to loop through a response?
If you have an array of data to return, you better define a list in the WSDL (the types section) like so:
<wsdl:types>
<s:schema xmlns:s="http://www.w3.org/2001/XMLSchema" targetNamespace="http://localhost/SampleService" elementFormDefault="unqualified" attributeFormDefault="unqualified">
<s:complexType name="MatterItemType"> <!-- List Item -->
<s:sequence>
<s:element name="MatterID" type="s:integer" minOccurs="1" maxOccurs="1"/>
<s:element name="MatterTitle" type="s:string" minOccurs="1" maxOccurs="1"/>
<s:element name="MatterText" type="s:string" minOccurs="1" maxOccurs="1"/>
<s:element name="MatterDate" type="s:integer" minOccurs="1" maxOccurs="1"/>
</s:sequence>
</s:complexType>
<s:complexType name="MatterListType"> <!-- List -->
<s:sequence>
<s:element name="MatterItem" type="tns:MatterItemType" minOccurs="0" maxOccurs="unbounded"/>
</s:sequence>
</s:complexType>
<!-- Request and Response -->
<s:element name="SampleRequest">
<s:complexType>
<s:sequence>
<s:element name="username" type="s:string" minOccurs="1" maxOccurs="1"/>
<s:element name="password" type="s:string" minOccurs="1" maxOccurs="1"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="SampleResponse">
<s:complexType>
<s:sequence>
<s:element name="MatterList" type="tns:MatterListType" minOccurs="1" maxOccurs="1"/>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
The Response always contains a MatterList element which is of MatterListType. The MatterListType contains from 0 to N MatterItem items defined in the MatterItemType.
The response will be structured something like this (not including SOAP envelope, namespaces, etc, just for illustration of the structure):
<SampleResponse>
<MatterList>
<MatterItem>
<MatterID>1</MatterID>
<MatterTitle>Title1</MatterTitle>
<MatterText>Text1</MatterText>
<MatterDate>1</MatterDate>
</MatterItem>
<MatterItem>
<MatterID>2</MatterID>
<MatterTitle>Title2</MatterTitle>
<MatterText>Text2</MatterText>
<MatterDate>2</MatterDate>
</MatterItem>
</MatterList>
</SampleResponse>
Let me know if you need more help in the comments.
I ran into a strange problem using a C# webservice client to call a ASP.NET 2.0 webservice.
The service is a simple product search and returns an array of products matching a search term - see the relevant part of the WSDL file below.
My C# client is simply generated by adding a web reference in VS2010 (non-WCF) and for comparison I'm using an Axis 1.4 Java client.
Using the same search paramaters in both the C# and the Java client the call returns 50 products but in the C# client the result array has length 1 while the Java client shows up the correct 50 elements.
I am looking for suggestions how to locate the problem - I've tried the following:
Compare the XML returned by the webservice using a TCP/IP monitor: The XML looks identical C# vs. Java and contains the 50 products
Compare HTTP parameters using netcat: C# defaults to HTTP 1.1 while Axis 1.4 uses HTTP 1.0, but changing the C# client to use HTTP 1.0 as well does no change anything
Try SOAP 1.2 instead of SOAP 1.1: No effect
Try HttpGetProtocol, HttpPostProtocol instead of Soap
Any suggestions are highly appreciated.
EDIT: Full WSDL and generated code (Reference.cs) can be found here:
http://timmay.dk/Reference.txt
http://timmay.dk/Wsdl.txt
Simplified WSDL part:
<s:element name="Search">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="SearchTerm" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="StartFrom" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="NumberToBeReturned" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="SearchResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="SearchResult" type="tns:SearchResult" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="SearchResult">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Products" type="tns:ArrayOfResponseProduct" />
</s:sequence>
</s:complexType>
<s:complexType name="ArrayOfResponseProduct">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="ResponseProduct" nillable="true" type="tns:ResponseProduct" />
</s:sequence>
</s:complexType>
<s:complexType name="ResponseProduct">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Fields" type="tns:ArrayOfResponseField" />
</s:sequence>
<s:attribute name="id" type="s:string" />
</s:complexType>
From the WSDL I gather that the maxOccurs is 1. So it seems that you should receive indeed only one SearchResult. However, that result itself should contain an object of type ArrayOfReponseProduct, which contains an unbounded amount of `ResponseProduct items. Maybe you are not looking deep enough?
Have you tried to check inside the debugger with the variable inspectors (Local, Auto, Immediate etc)? Is the object typed, or untyped, in which case you may need to cast it first to see the contents?
It turned out that the culprit was the type of the return values - Response field
< s:complexType name="ResponseField">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Value">
<s:complexType>
<s:sequence>
<s:element ref="s:schema" />
<s:any />
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
This was pr default converted to a System.Data.DataSet - changing this to a simple string solved the problem. It seems that the unmarshalling failed in this case.
We have some XSDs in our project that define types that use attributes, as well as elements, to specify property values, e.g.:
<Instrument name="blah">
</Instrument>
I use these XSDs to define a schema used by a WSDL, but when I run it through schemagen, the generated code is unwrapped. For example:
public interface InstrumentService
{
// CODEGEN: Parameter 'GetInstrumentResponse' requires additional schema information that cannot be captured using the parameter mode. The specific attribute is 'System.Xml.Serialization.XmlElementAttribute'.
GetInstrumentResponse GetInstrument(GetInstrumentRequest request);
}
(the GetInstrumentRequest and GetInstrumentResponse should be unwrapped to the parameters and return value only).
The reason for this is that the data contract serializer doesn't support complex types with attributes, but I did read somewhere that if you use document/literal, rather than document/literal wrapped to define the WSDL, schemagen will fall back to an XmlSerializer implementation, that does support attributes. So far, my attempts to get this to work have failed:
// CODEGEN: Generating message contract since the operation GetInstrument is neither RPC nor document wrapped.
So, is this assumption about document/literal faulty? Is there any way to generate unwrapped interface code from a WSDL that defines complex types with attributes?
Here's the modified document/literal WSDL I am using:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
targetNamespace="http://tempuri.org/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:tns="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xs:schema targetNamespace="http://tempuri.org/">
<xs:complexType name="testComplexType">
<xs:sequence/>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
<xs:element name="input" type="tns:testComplexType"/>
</xs:schema>
</wsdl:types>
<wsdl:message name="GetInstrumentIn">
<wsdl:part element="tns:input" name="input"/>
</wsdl:message>
<wsdl:message name="GetInstrumentOut"/>
<wsdl:portType name="InstrumentService">
<wsdl:operation name="GetInstrument">
<wsdl:input message="tns:GetInstrumentIn"/>
<wsdl:output message="tns:GetInstrumentOut"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="InstrumentService" type="tns:InstrumentService">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="GetInstrument">
<soap:operation soapAction="GetInstrument" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="InstrumentService">
<wsdl:port binding="tns:InstrumentService" name="InstrumentService"/>
</wsdl:service>
</wsdl:definitions>
apologies for answering my own question. It seems that just removing the nillable="true" statement from the operation response type, in th document/literal/wrapped WSDL types schema does the trick - no need to drop to document/literal.
<wsdl:types>
<xs:schema elementFormDefault="qualified" targetNamespace="http://com.barcap.cbts.core.messaging.rpc/">
<xs:element name="GetInstrument">
<xs:complexType/>
</xs:element>
<xs:element name="GetInstrumentResponse">
<xs:complexType>
<xs:sequence>
<!-- nillable="true" removed -->
<xs:element maxOccurs="1" minOccurs="0"
name="GetInstrumentResponse" type="tns:Instrument"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Instrument">
<xs:sequence/>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:schema>
</wsdl:types>