Im attempting to interact with another company's web service via WSDL.
I've imported it into VS2010 as a service reference, I can make request just fine. The problem is, the return types are strings (of xml). Now I'm fairly new to the WSDL deal, but from what I've read there should be return types in the contract and then the service reference would auto-magically generate classes for me.
How do I remedy this?
I suppose I could map the strings of XML, if so, can someone please
show me a nice example? As I have tried with no avail.
Could I tell the web service to use a return type that I specify?
Or, do i have the wrong idea about WSDL? And if so, could someone please explain inconsistencies in my understanding?
Your basic idea is correct, having a service wsdl should define the return and input objects to the service operations. The service provider might have a valid reason for just returning you strings or maybe he just didn´t know better.
For you the WSDL is the final frontier, unless your business partner is able to provide a new one you cannot change the service interface, so you have to deal with the XML strings.
Check out XMLDocument, it offers the Load() method accepting a string. If it fails, chances are you´re missing an XSD or you dont have a valid/wellformed xml document contained inside the string. In both cases it´s your business partner who has to correct the error or provide further information.
Related
I've been doing quite a bit a learning over the past couple of days and I believe I've come to a conclusion. I would like to ask if my current understanding is correct, as I've had a very difficult time getting a "straight" answer to my specific problem based on Google searches.
I have a C# class library (.dll) with some classes that are used across multiple projects, including customClass (namespace myDLL).
I have a C# web service. One of the web service functions has an "out customClass [] myCustomClass" array argument.
I have a C# web service client. I want to be able to use customClass in the client. Here is a list of questions:
1) Is it true that the customClass array that is returned to the web service client is NOT the same type as an array of type myDLL.customClass (even though it is intuitive to assume that it would be)?
2) Is there any easy way to cast/convert the customClass array in the web service client to the type myDLL.customClass? I'd prefer to not have to write supporting code or manually edit reference.cs. It is my belief that there is NOT such an easy method of conversion, although it can be done with supporting conversion code.
3) It is my belief that the output of web services is meant to be only data (in general). To expect that a client will get class behavior along with data "easily/natively" when using the web service WSDL is not an expectation supported by the web service/web service client model. Is this belief generally correct?
I appreciate any help. If anyone has an nice, straightforward links about this topic, I wouldn't be surprised I've already read it, but I will definitely be all eyes :).
Thanks,
Richard
I'm writing a web service and have passed an object which is showing up as
<OfferDetail>
<OfferID>long</OfferID>
<InterestID>long</InterestID>
<RangeValue>string</RangeValue>
<Score>string</Score>
<Importance>string</Importance>
<Range>string</Range>
<ImportanceByOtherUser>string</ImportanceByOtherUser>
<RangeByOtherUser>string</RangeByOtherUser>
</OfferDetail>
in the web service placeholder but i don't want the
<ImportanceByOtherUser>string</ImportanceByOtherUser>
<RangeByOtherUser>string</RangeByOtherUser>
to be there is the place holders.
Note: i can't remove them from the object
If you're using WCF, then you probably have the DataContractAttribute applied to the object whose data you're returning via the service. If this is a service definition (which I doubt, but you didn't post any C# code), then you'll want to get rid of the OperationContractAttribute that's decorating these properties. But I believe it's the latter rather than the former—so I'd look for DataContractAttributes first.
HTH.
Just wondering why ?.
Are this members for internal web service usage, or private data? I've seen sometimes some developers publishing directly the ORM object through the web service. While it may works, It's often a bad idea as you don't want to expose the whole object, but only a subset of the object, or even a composition of several objects (customer's main detail + last orders in the month for example).
Thus I strongly advise you to refactor your code. You should create some DTO objects that are dedicated to data output of your web service, and command objects for input.
You specified you can't change the object, but what about adding another layer?
What type of webservice are you using? Depending on this you can use attributes like XmlIgnore, NonSerialized, IgnoreDataMember etc.
See
Question 1
Question 2
Its a known bug.
http://archive.msdn.microsoft.com/WsdlHelpGenerator/Release/ProjectReleases.aspx?ReleaseId=412
download the file and add the following in the web config
<webServices>
<wsdlHelpGenerator href="CustomWsdlHelpGenerator.aspx"/>
</webServices>
Href should point to the file downloaded in your the project
I am trying to write some code in C# that will call a WCF service on the fly by importing the WSDL, examining it and then making calls to it dynamically.
The service I am calling can change from time to time - so if it does I want my client to know about new methods and new input parameters and output parameters to the calls, without rebuilding my client.
One possible solution to this is to import and compile a service reference on the fly.
Outlined here: Creating an assembly on the fly from a WSDL
I would like to avoid the generation of an assembly and then reflecting over it if possible.
I looked into the code of the dynamic proxy in the link and they use a framework class to do the import. This class is the WsdlImporter. So I had thought great - I can use that and examine the WSDL schema and determine what calls are present and what inputs and outputs are available.
The problem is that the type information is missing in the MessagePartDescription objects that the WsdlImporter creates. Apparently this is missing because it cannot find the types yet - see the response to the question from Brian.
So any advice on how I should proceed? Am I completely on the wrong track here?
This is probably not an answer but I will post it as one to fully describe my opinion.
Dynamic proxy:
IMO this is example of wrong usage of technology. It is elementary behavior of WSDL - if it changes you have to change client or you have to make good WSDL versioning and create new client.
You still have to somehow say your client to get WSDL - does it mean that you will parse WSDL before each call? Doesn't seem like a good idea.
Information about types is really not part of WSDL because by default WSDL is generated as interoperable. CLR types are not operation needed for interoperability. When you create service proxy by Add service reference or Svcutil it will generate code for types defined in WSDL. That code then need to be compiled.
You can try to use NetDataContractSerializer instead of default DataContractSerializer. NetDataContractSerializer adds CLR type information into WSDL but I still expect that new types must be known to your clients - it means deploying new assembly with types and use it by clients. This almost sounds like same approach when simply deploying assembly with new static client proxy.
Dynamic WF client
I also don't see too much usage of this architecture - you still need to change client to reflect new WF steps, don't you?
Changing the WF
Are we talking about Windows Workflow foundation? I can hardly imagine scenario where you create WF, expose it as a service and then change it. When you expose WF as service you are probably defining long running WF. Long running WFs use persistance which is based on serialization (at least in WF 3.5 but I believe it is same in WF 4). When you change WF definition, all persisted WFs are most probably doomed because they will never ever deserialize. This situation is usually solved by parallel deployment of new and old version where old version is only used to finish incomplete WFs. Again it means new clients.
If you look at the problem from a different angle. Do you need to regenerate the proxy each time or do you need a contract that continues to work when things change?
WCF has a mechanism for this IExtensibleDataContracts see: http://msdn.microsoft.com/en-us/library/ms731083%28v=VS.100%29.aspx
Best practices for versioning of contracts can be found here
Basically, I have a server-side type "Foo" with members X and Y. Whenever I use Visual Studio's "Add Server Reference" then I see the WSDL and the generated proxy both append the word "Field" to all the members and change the casing of the first letter. IE, "X" and "Y" are renamed "xField" and "yField". Any idea why this is happening? I can't figure out the pattern.
Details -- I have a legacy ASMX web service which exposes a "Foo" type. I created a new WCF service that's a wrapper around that old web service -- the new service just wraps those methods and maybe updates the values of a few fields, but it exposes the exact same methods and returns the exact same types. I've tried re-creating the referenes several times, and every time, it always renames my fields: the varible "STUFF" is exposed in the wsdl and proxy as "sTUFFField". Variable "X" is exposed as "xField", etc.
Funny thing is I can't figure out the pattern -- I tried creating a new ASMX web service as a test and wrapping that -- variables are not renamed then. So I can't figure out the pattern of why/when WCF renames variables.
Anybody know?
I had the same issue, and sergiosp's answer got me headed in the right direction. Just adding some additional info to hopefully help someone else.
Adding [System.ServiceModel.XmlSerializerFormatAttribute()] to the interface, and re-generating the client code resolved the problem for me.
public interface IMyService
{
[System.ServiceModel.XmlSerializerFormatAttribute()]
[System.ServiceModel.OperationContract]
recordResponse GetRecord(recordRequest request);
}
I had the same problem but i was able to find solution.
In the interface if you add [DataContractFormat] tag you will end up with "XFieldField" case.
But if you replace it with [XmlSerializerFormat] in the interface it will not change the names in the proxy generated.
Typically, the generated proxy will have "XField" and "YField" as internal/protected/private fields, and expose the values through properties called "X" and "Y". There are options you can set when creating the proxy client to tweak that to your liking, I think.
UPDATE: I don't seem to find any switches or options to control this behavior. It might depend on which serializer (DataContractSerializer vs. XmlSerializer) WCF uses for creating the client proxy.
In the end, it's really more or less just an issue of coding style - functionally, it shouldn't make a difference.
Marc
I had this problem too, but from the client I was still getting Field at the end of the class members even after making the mentioned change at the interface.
The problem was, I was using a DataContractSerializer to work with disk file serialized requests (during the test of our service, we were getting serialized requests from the provider, to be able to debug before going live).
After changing the DataContractSerializer to a XmlSerializer, specifying on its constructor the root element (by a typeof() call) and the rootnamespace (because by default, XmlSerializers write the standard namespace), I could deserialize the requests and work perfectly with the WCF Service.
Hope this helps somebody. I lost soooo many time with this "issue".
Adding XmlSerializerFormat worked for me. Got solution from http://geekswithblogs.net/mipsen/archive/2010/02/06/field-postfix-in-wcf-reference.aspx
[ServiceContract(Namespace="http://somenamespace.com/contracts")]
public interface ISchemaService
{
[OperationContract]
[XmlSerializerFormat]
void DoSomething(GeneratedType data);
}
I'm still new to the ASP.NET world, so I could be way off base here, but so far this is to the best of my (limited) knowledge!
Let's say I have a standard business object "Contact" in the Business namespace. I write a Web Service to retrieve a Contact's info from a database and return it. I then write a client application to request said details.
Now, I also then create a utility method that takes a "Contact" and does some magic with it, like Utils.BuyContactNewHat() say. Which of course takes the Contact of type Business.Contact.
I then go back to my client application and want to utilise the BuyContactNewHat method, so I add a reference to my Utils namespace and there it is. However, a problem arises with:
Contact c = MyWebService.GetContact("Rob);
Utils.BuyContactNewHat(c); // << Error Here
Since the return type of GetContact is of MyWebService.Contact and not Business.Contact as expected. I understand why this is because when accessing a web service, you are actually programming against the proxy class generated by the WSDL.
So, is there an "easier" way to deal with this type of mismatch? I was considering perhaps trying to create a generic converter class that uses reflection to ensure two objects have the same structure than simply transferring the values across from one to the other.
You are on the right track. To get the data from the proxy object back into one of your own objects, you have to do left-hand-right-hand code. i.e. copy property values. I'll bet you that there is already a generic method out there that uses reflection.
Some people will use something other than a web service (.net remoting) if they just want to get a business object across the wire. Or they'll use binary serialization. I'm guessing you are using the web service for a reason, so you'll have to do property copying.
You don't actually have to use the generated class that the WSDL gives you. If you take a look at the code that it generates, it's just making calls into some .NET framework classes to submit SOAP requests. In the past I have copied that code into a normal .cs file and edited it. Although I haven't tried this specifically, I see no reason why you couldn't drop the proxy class definition and use the original class to receive the results of the SOAP call. It must already be doing reflection under the hood, it seems a shame to do it twice.
I would recommend that you look at writing a Schema Importer Extension, which you can use to control proxy code generation. This approach can be used to (gracefully) resolve your problem without kludges (such as copying around objects from one namespace to another, or modifying the proxy generated reference.cs class only to have it replaced the next time you update the web reference).
Here's a (very) good tutorial on the subject:
http://www.microsoft.com/belux/msdn/nl/community/columns/jdruyts/wsproxy.mspx