I'm trying to convert an ASP.Net web service to WCF application. The client is on the .Net Compact Framework which does not support WCF so I need to make sure the WCF keeps supporting ASP style webservices. When I add the web service reference in Visual Studio the generated proxy class' methods have extra arguments.
For example if a method is defined as:
public void GetEmpInfo(int empNo)
That method will appear in the proxy class as:
public void GetEmpInfo(int empNo, bool empNoSpecified)
What causes this, and how do I get it to stop?
Check out this blog post ...
Where did these extra boolean
“specified” members come from and what
do they do? The answer is the schema
that the WCF data contract serializer
generates by default. Because of the
way its versioning model works, the
serializer generates all data members
as optional elements. The older web
services stack, ASP.NET Web Services
(“ASMX”), uses a different serializer,
the XmlSerializer, which maintains
full schema and XML fidelity. The
XmlSerializer maps all optional
elements to two members: one
represents the data itself, and one
specifies whether or not the data is
actually present – this is the
“xxxSpecified” member. These
xxxSpecified members must be set to
true to enable the serialization of
the corresponding “actual data”
members.
The .NET Compact Framework does support a subset of WCF. You can review this support on MSDN. Take a look, it may support enough for you to remove your legacy Web Services support.
This happens for types with a default value of not null. In these cases, it's impossible for the web service to know whether a parameter was set to the default value or simply not set at all.
You can get rid of the extra specification parameter by decorating your operation with the [XmlSerializerFormat] attribute like:
[OperationContract]
[XmlSerializerFormat]
string GetEmpInfo(int? empNo);
This attribute can also be added at the Class level, and this would make sense in most cases.
I understand you can handle this situation using nullable types (int?), but I was unable to fix it using this.
Related
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 consume a web service that has a numeric element. The Delphi wsdl importer sets it up as Int64.
The web service allows this element to be blank. However, because it is defined as Int64, when I consume the web service in Delphi without setting a value for it, it defaults to 0 because it's an Int64. But I need it to be blank and the web service will not accept a value of 0 (0 is defined as invalid and returns an error by the web service).
How can I pass a blank value if the type is Int64?
Empty age (example)
<E06_14></E06_14>
could have a special meaning, for example be "unknown" age.
In this case, the real question is how to make the field nillable on the Delphi side.
From this post of J.M. Babet:
Support for 'nil' has been an ongoing issue. Several built-in types of
Delphi are not nullable. So we opted to use a class for these cases
(not elegant but it works). So with the latest update for Delphi 2007
I have added several TXSxxxx types to help with this. Basically:
TXSBoolean, TXSInteger, TXSLong, etc. TXSString was already there but
it was not registered. Now it is. When importing a WSDL you must
enable the Use 'TXSString for simple nillable types' option to make
the importer switch to TXSxxxx types. On the command line it is the
"-0z+" option.
The DocWiki for the Import WSDL Wizard also shows two options related to nillable elements:
Process nillable and optional elements - Check this option to make the WSDL importer generate relevant information about optional
and nillable properties. This information is used by the SOAP runtime
to allow certain properties be nil.
Use TXSString for simple nillable types - The WSDL standard allows simple types to be nil, in Delphi or NULL, in C++, while Delphi
and C++ do not allow that. Check this option to make the WSDL importer
overcome this limitation by using instances of wrapper classes.
Can I pass a custom object between AJAX enabled WCF and my asp.net page?
I searched the web but could not find any examples. Most shows simple types like string and integers.
I also do not know how to populate custom object's property through JavaScript on the client side.
We have a browser add on and we have to pass data to that addon from a web service, I researched and looks like AJAX enabled WCF is way to go
Using .net framework 3.5 and VS 2008
You can't pass the actual custom objects, but you can of course pass the serialized version of them through your service and to your page, javascript, etc. Basically, you have to map the fields of your complex custom .NET types to classes decorated with the DataContract attribute. These classes are the types that your service will return. The DataContract-decorated classes will contain fields with primitive types, like strings, integers, etc. The WCF service will serialize these into XML or JSON.
On the client side, jQuery will be your best friend. I personally prefer JSON because the properties of your objects are much easier to get at that way instead having to deal with parsing a bunch of XML. So, setup your service to output JSON.
Also, to make your service URLs easier to read, make sure to use a RESTful approach. It's as easy as decorating your service methods with the WebGet attribute and supplying a UriTemplate. Once you see some examples, it'll blow your mind. Note: if you ever encounter a WebInvoke with Method="GET", just use WebGet instead...it's more compact...no Method specification needed.
This particular article was EXTREMELY useful to me when I was developing my WCF service and the ASP.NET app that consumed it: http://www.c-sharpcorner.com/UploadFile/sridhar_subra/116/
Here's another person asking the same question as you: http://social.msdn.microsoft.com/forums/en-US/wcf/thread/879d46af-9c78-4b5d-b746-82843d742a6f
Hope this helps! Long live WCF!
With .NET 3.5 your best bet is WebHttpBinding which accepts plain old XML (POX) and you need to send XML to the WCF service.
You can also use WCF REST using REST starter kit. For samples have a look here. This supports JSON as well.
If you were using .NET 4.0, JSON-enabled WCF HTTP was the way to go. WCF REST with 4.0 was an alternative although I really do not like it.
I have a class with a read-only property defined. In my code I define this as a property with a getter only.
I want to be able to send this object back and forth across a web service. When I call a "Get" method in the service, it would be populated with a value on the service side. Once I define this property, I don't want the consumer of the web service to be able to set/change this property.
When I add a reference to this web service to a project, the object has the property serialized a few different ways depending on how I try to define the object on the service side:
internal setter: Creates the property in the WSDL. Visual Studio generates a class with both a getter & a setter for this property.
no setter: Does not create the property in the WSDL. Visual Studio then obviously does not define this property at all.
Read-only public member variable - Does not create the property in the WSDL. Again, Visual Studio will not do anything with this property since it doesn't know about it.
Allowing the consumer of the web service to set a value for this property will not cause any harm. If the value is set, it is ignored on the web service side. I'd just prefer if the consumer can't change/set the property to begin.
Is there any way to define a property as read-only? Right now we're using C#/.NET 2.0 for the web service, and (for now at least) we have control over all of the consumers of this service, so I can try changing configurations if needed, but I prefer to only change things on the web service and not the consumers.
I can be wrong, but I think the problem here is how serialization works - in order to deserialize an object the serializer creates an empty object and then sets all the properties on this object - thats why you need a setter for the properties to be included in serialization. The client code has the same "interface" to the object as the deserializer.
Caveat, I am a Java guy so the first part of my answer focuses on what may be possible in C#.
Firstly, with a custom serializer in Java, you can do almost anything you want, including directly setting values of a protected or private field using reflection so long as the security manager doesn't prevent this activity. I don't know if there are analogous components in C# for the security manager, field access, and custom serializers, but I would suspect that there are.
Secondly, I think there is a fundamental difference in how you are viewing Web services and the Web service interface as part of your application. You are right-click generating the Web service interface from existing code - known as "code first". There are many articles out there about why WSDL first is the preferred approach. This one summarizes things fairly well, but I would recommend reading others as well. While you are thinking in terms of a shared code library between the client side and server side of your Web service and maintaining object structure and accessibility, there is no such guarantee once you publish an API as a Web service and don't have control over all of the consumers. The WSDL and XSD serve as a generic description of your Web service API and your server and client can be implemented using different data binding configurations, object classes, or languages. You should think of your Web service interface and the XML that you pass in and out of it as describing the semantics of the exchange, but not necessarily the syntax of the data (your class structure) once it is internalized (deserialized) in your client or server.
Furthermore, it is advisable to decouple your transport related structures from your internal business logic structures lest you find yourself having to refactor both your server implementation, your Web service API, and your (and other's) client implementations all at the same time.
There's no built-in way to do this in .NET 2.0 as far as I know. In cases where I wanted to serialize a read-only property, I've implemented the IXmlSerializable interface so that I could control the ReadXml() and WriteXml() methods.
In later versions of the .NET framework, you can serialize read-only properties by setting an attribute on the backing field.
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