I'm writing a C# web service client in Visual Studio 2008 with a Java web service endpoint. I have no control over the endpoint and the SOAP messages that it sends back.
I created an auto-generated proxy client from the web service WSDL using the "Add Service Reference" option in Visual Studio. When I send my request I get a valid SOAP message back, which contains something like this:
<java:a_field xmlns:java="java:com.whatever">Value1</java:a_field>
<java:different_field xmlns:java="java:com.whatever">Value2</java:different_field>
However, it does not actually parse those two values, and all of the values after that are null. After debugging, I found that this code in the auto-generated Reference.cs was the problem:
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=30)]
public string different_field {
get {
return this.different_fieldField;
}
set {
this.different_fieldField = value;
this.RaisePropertyChanged("different_field");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=31)]
public string a_field {
get {
return this.a_fieldField;
}
set {
this.a_fieldField = value;
this.RaisePropertyChanged("a_field");
}
}
These two fields are out of order, so it doesn't serialize them properly, and the rest of the fields are not serialized at all. The WSDL itself declares the fields in the same order that the proxy class is expecting them in, it's just the actual response that changes the order. I can work around this by manually swapping the two Order= values, but that would be a huge pain to maintain given that the WSDLs change frequently and there are 100s of fields that need to be checked for this kind of error. Is there any better way for me to be able to ignore this ordering mismatch and still use the auto-generated web service proxy?
Having dealt with something similar, and knowing that it's a giant pain, I would suggest creating your own "fake" WSDL that reflects what is actually returned from the web service instead of what is specified. The issue appears to relate more to an inaccurate XSD that is part of the WSDL. It seems that some of the Java web service frameworks do not follow the order (or other specifications) strictly by default, and your third-party web service provider may not have the knowledge, resources, or motivation to fix the problem.
It is better still, as a matter of best practice, not to import the WSDL at all as a service reference, instead creating the interfaces and service proxies by hand and the configuration either manually or with the WCF Service Configuration Editor. There are a number of resources on how to do this -- Google is your friend.
Related
I'm new to Web Services from C#, but have worked C# for years, just never needed to use Web Services. Due to privacy issues, I can't disclose actual URL, but there is a test server and a production server where the web services are identical in all other respects, and the services were written / managed by another entity.
https://LiveSite.SomeDomain.com/FolderInWebSite/TestWebServiceSoapHTTP
and
https://TestSite.SomeDomain.com/FolderInWebSite/TestWebServiceSoapHTTP
Do I need to create two separate web references to the project and create different instances of them to go, or can I via some property just change which URL version it is sending data to.
Additionally, not being familiar working web services, I see the classes as Visual Studio imported. I can create instances of the classes and set the applicable properties (int, dates, strings, string[] arrays, etc). But not seeing how to actually say ... Go send it now. and then getting the response back.
I've done this from an older application with another language and was doing direct with HTTP and SOAP where I was able to make my own connection to the URL, build the body of the SOAP message, then send it.
Just use the "Url" property.
var myProxy = new MyProxy();
myProxy.Url = "http://foo.com/myservice";
Edit for second part of the question:
There should be a method for each action exposed the API that you can call. For example if the API exposes a MyAction that takes a string, the code generator should have generated a method that you can use like so:
myProxy.MyAction("hello");
The ONLY argument I can see for SOAP WCF over REST (json) wcf is the fact that once my service is created I can add a a reference in visual studio and I get a load of strongly typed classes ready for me and a client class that I can call all my webmethod through. It even sets up the web.config as far as I remember.
However when I expose a REST (json) service I still get a WSDL. So Im wondering is there still a way to build my references automatically?
Not using WCF tools. Unlike with SOAP (which has an established protocol for describing services - WSDL), REST doesn't. WADL is one such protocol, but it isn't too widespread and WCF does not support it. You still get a WSDL, because WCF will describe everything it can from the service. However, the WSDL won't have a <wsdl:port> element, which would describe the REST endpoint, which is why you get the WSDL, but cannot generate a reference to it.
The post at http://blogs.msdn.com/b/carlosfigueira/archive/2012/03/26/mixing-add-service-reference-and-wcf-web-http-a-k-a-rest-endpoint-does-not-work.aspx has a lot more info on this issue.
Very old question, newer answer.
today using openapi (swagger) I can achieve this by using swagger inspector doing samples i can document my rest services as well as create a spec yml/json file allowing for validations and acceptance criteria as well as automated clients for java,python,c#,ruby,javascript and others I'm sure
I would like top elaborate:
Although it is true you cannot get a WSDL add service reference with a JSON REST WCF service, what I do is create two met data hooks:
is the operations returning JSON
is a single XML op returning a class wrapper which includes all the service classes I allow, I call it Discover:
i.e.
public class Discover
{
public Manager Manager {get;}
public Employee Emp {get;}
....
}
[OperationContract]
public Discover DiscoverDTOs()
You can, indirectly. While the client generated by Visual Studio won't work, that client implements an interface, also generated, that you can use like this:
WebChannelFactory<IService> factory = new WebChannelFactory<IService>(new Uri(endpointAddress));
IService proxy = factory.CreateChannel();
int result = proxy.Operation(1, 2, 3);
WebChannelFactory has another overload which accepts a WebHttpBinding, you can configure based on the service configuration, or you can make this configuration manually in your app.config file.
There is a web service written with WCF that I'm adding as reference. Proxy class generator works flawlessly when I add it to as service reference but it generates a slightly different class when I add it as web reference using service.svc?WSDL. Here's are the differences:
//service reference
public partial class TestServicesClient : ... // correct class name
{
public int TestMethod(string serviceID, int dealID) // correct method signature
{ ... }
}
//web reference
public partial class TestServices: ... //different class name
{
public void TestMethod(string serviceID, int dealID, bool dealIDSpecified, out int TestMethodResult, out bool TestMethodResultSpecified) // different method signature
{ ... }
}
I tried using wsdl.exe for generating web reference class, didn't help.
What is wrong here?
Nothing is wrong here. Service Reference is the "new" way to use a WCF Service, it removes overhead such as the "Specified"-parameter, "Result"-parameter and "Result Specificed"-parameter.
You can still use other properties/methods to check if a parameter is specified or if there is a result. But before WCF, it changed the method signature.
You use a Service Reference and a Web Reference a bit different and that's just the way it is.
Here's some additional reading:
Difference between web reference and service reference?
The Difference Between “Add Web Reference” and “Add Service Reference”
And to quote from a reply to "What is the difference between WCF service and web service"
WCF "web services" are part of a much
broader spectrum of remote
communication enabled through WCF. You
will get a much higher degree of
flexibility and portability doing
things in WCF than through traditional
ASMX because WCF is designed, from the
ground up, to summarize all of the
different distributed programming
infrastructures offered by MS. An
endpoint in WCF can be communicated
with just as easily over SOAP/XML as
it can over TCP/binary and to change
this medium is simply a configuration
file mod. In theory this reduces the
amount of new code needed when porting
or changing business needs, targets,
etc.
ASMX is older than WCF, and anything
ASMX can do so can WCF (and more).
Basically you can see WCF as trying to
logically group together all the
different ways of getting two apps to
communicate in the world of MS; ASMX
was just one of these many ways and so
is now grouped under the WCF umbrella
of capabilities.
There are few difference between the service reference and web reference. WCF serializes using datacontract serializer. So add XmlSerializeFormat attribute to the serivcecontract and then add web reference. Your extra parameters will be removed. But then its like using wcf like web service only. One more retriction is that you need to use web bindings only like http.
I have a class with a Property :
[DataMember]
public bool MyProp { get; internal set;}
I notice that when the proxy is generated. The property is still settable even though I have marked it internal ( I thought that it won't be generated at all ).
Is there a way to achieve what I'm trying? I'd like to be able to set the property from the service side. But not allow the client side to be able to set the property.
A [DataMember] on a WCF contract is just a data field on a data contract - an XML schema. The .NET setter and getter visibility modifier are irrelevant when dealing with WCF messages, really.
If your field has a [DataMember] attribute, it will be part of the XML schema of your data contract - and the client cannot know that it has an "internal" setter on the server side - it's just part of the XSD data contract.
.NET and WCF are two very distinct and separate worlds - when your client calls a WCF service, it's a SOAP-based message passing only - there's no .NET based object interaction! You're not reaching out from your client to the server to call a method on an object on the server side - in which case maybe a .NET visibility specifier would come into play. Your client creates a messages and sends that to the server, which then reassembles the (server-side) object from that message - heck, there's even a SMTP (e-mail!) based transport for WCF!
The only thing the two sides share are contracts - service/operation contracts for your service methods, and XML schema based data contracts for your data being passed around. There' no concept of .NET based visibility specifications in XML schema.
As with Service Contracts, access modifiers on DataContracts/DataMembers do not play any role and are in essence meaningless :(
Without a get and set, you cannot serialize and deserialize over a WCF hop.
You could implement what you are trying to do in the logic of your service.
I have two websites, both using .Net framework 3.5. One website is hosting a soap web service and the other is referencing this service.
I'm having some unexpected happenings with my web method signatures. I have a simple method in my web service with a signature such as:
[WebMethod]
public string[] HelloWorld()
{
return new[] { "Hello World" };
}
But when I reference this web service using the 'Add Service Reference' feature in VS2008, with configuration set to "Always generate message contracts" (although when i check the 'reuse types in referenced assemblies', i seem to have the same issue), the signature seems to be changed by the auto generated proxy objects to the following:
HelloWorldResponse HelloWorld(HelloWorldRequest request)
I've tried to look this up on the net, but having trouble finding something that will simply explain to me why this is happening, and whether I can/should try to work around it?
I also have this question:
How does one determine whether they should choose the service reference configuration option to "reuse types in referenced assemblies" and "always generated message contracts"?
The message-contracts option might have this effect; the purpose here being to allow fine-grained control over the underlying request. Ultimately, what you are sending (behind the scenes) is a request payload.
The reuse-types option is more typically used with objects (not things like string[]) - and means that if you have a 100% matching Customer (say) class locally, it can re-use that for the web-service rather than generating a proxy type.
Additionally, note that you aren't actually consuming a WCF service ([WebMethod] is the older web-service style). As such you may have better results with a "Web Reference"; when adding the service, hit "Advanced", then "Add Web Reference...". This uses the older UI and wsdl.exe to generate code intended for [WebMethod] (asmx), rather than WCF (svc).
Of course, rather than hosting a [WebMethod], you could (since the server is also 3.5) host a WCF service; this may make things easier.
A final point of WCF; if you really want the same contract at client and server, you can use either assembly or class sharing to use the very same types at both end. This is not supported for [WebMethod], though.