prevent object memebers from appearing in placeholders of web service - c#

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

Related

C# - Can WebMethodAttribute adversely effect performance?

I just noticed my Excel service running much faster. I'm not sure if there is an environmental condition going on. I did make a change to the method. Where before it was
class WebServices{
[ WebMethod( /*...*/) ]
public string Method(){}
}
Now its attribute is removed and the method moved into another class
class NotWebService {
public string Method(){}
}
But, I did this because the Method is not called or used as a service. Instead it was called via
WebServices service = new WebServices();
service.Method();
and inside the same assembly. Now when I call the method
NotWebService notService = new NotWebService();
notService.Method();
The response time appears to have gone up. Does the WebMethodAttribute have the potential to slow local calls?
Indeed the WebMethod attribute adds a lot of functionality in order to expose the method through a XML WebService.
Part of the functionality that causes overhead are the following features considered as part of the configurable stuff for a web method:
BufferResponse
CacheDuration
Session Handling
Transaction Handling
For more information just check the WebMethod attribute documentation
Regards,
I know this is an old question, but to avoid misinformation I feel the need to answer it anyway.
I disagree with wacdany's assessment.
A method marked as a webmethod should have no additional overhead if called directly as a method, rather than via HTTP. After all, it compiles to exactly the same intermediate language, other than the presence of a custom attribute.
Now adding a custom attribute can impact performace if it is one of the ones that is special to the compiler or runtime. WebMethodAttibute is neither.
I would next consider whether there is any special overhead to constructing the webservice object. If you have added a constructor there might be some, but by default there is no real overhead, since the constuctors of the base classes are trivial.
Therefore if you really were calling the method directly, there should be no real overhead, despite it also being accesable as a web service action. If you experienced a significant difference, it would be wise to verify if you were constructing the real WebServices class, and not somehow inadvetently using a web service proxy, perhaps due to adding a web service reference to your project.

Why does WCF sometimes add "Field" to end of generated proxy types?

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);
}

Is it possible to create read only elements in SOAP web services?

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.

Should I bind directly to objects returned from a webservice?

Should I bind directly to objects returned from a webservice or should I have client-side objects that I bind to my gridcontrols? For instance if I have a service that returns object Car should I have a client side Car object that I populate with values from the webservice Car object?
What is considered best-practice?
In C# do I need to mark my classes as serializable or do something special to them?
This is a good question, which follows the sames lines as two questions I have asked myself:
Large, Complex Objects as a Web Service Result.
ASP.NET Web Service Results, Proxy Classes and Type Conversion.
Both of these may be a worthwhile read for you.
Heres my two bits:
Try to keep the return types of your Web Services to primitives where possible. This not only helps reduce the size of the messages, but also reduces complexity at the receiving end.
If you do need to return complex objects, return them as a raw xml string (I'll explain below).
What I then do is create a seperate class which represents the object and handles it's xml. I ensure the class can be instantiated from and serialized to xml easily. Then both projects (the web service and the client) can reference the DLL with the concrete object in, but there is none of the annoying coupling with the proxy class. This coupling causes issues if you have shared code.
For example (using your Car class):
Web Service (CarFactory) method BuyCar(string make, string model) is a factory method that returns a car.
You also write a Mechanic class that works on Car objects to repair them, this is developed without knowledge of the Web Service.
You then right a Garage class for your application. You add a web reference to the CarFactory service to get your cars, and then add some Mechanic's to your garage and then crack your knuckles and get ready to get some cars from the factory to get them working on.
Then it all falls over, when you get the result of CarFactory.BuyCar("Audi", "R8") and then tell your Mechanic.Inspect(myAudi) the compiler moans, because the Car is actually of type CarFactory.Car not the original Car type, yes?
So, using the method I suggested:
Create your Car class in its own DLL. Add methods to instantiate it and serialize it from/to XML respectively.
Create your CarFactory web service, add a reference to the DLL, build your cars as before, but instead of returning the object, return the XML.
Create your Garage adding a reference to the Mechanic, Car DLL and the CarFactory web service. Call your BuyCar method and now it returns a string, you then pass this string to the Car class, which re-builds its object model. The Mechanic's can happily work on these Car's too because everything is singing from the same hymn sheet (or DLL?) :)
One major benefit is that if the object changes in its design, all you need to do is update the DLL and the web service and client apps are completely decoupled from the process.
Note: Often it can be useful to then create a Facade layer two work with the web services and auto-generate objects from the XML results.
I hope that makes sense, if not, then please shout and I will clarify .
This really depends on what you are getting from the web service. If they are simple data transfer objects and you are only displaying data, then yes, you can bind. If you plan to edit the objects, it may not be usefull as you will need to track changes.
Do your objects and/or collections on the client track changes? If so you can use them.
If you have no change tracking, then you will need to track changes yourself, so you may need to translate the objects or wrap them in something to track changes.
Again, it really depends on what you are getting, what they support, what you are doing with them, as well as what response the server wants back for changes.
One thing you can do is to create client classes corresponding to the web service data contracts with any additional functionality that you want and set the web service reference to reuse existing types. Then there is no reason to create an additional wrapper class to bind to.
If you bind directly to the Web service types, you're introducing a coupling. Should the Web service change in future, this may have undesired side-effects that mean lots of code changes.
For example, what if you're using .asmx Web services today, then shift to WCF tomorrow? That might mean quite a few changes through your code if you've used types that WCF won't serialize.
It's often better in the long run to create specific client-side objects and then translate to and from Web service data contract types. It may seem a lot of work, but this is often repaid greatly when it's time to refactor, as your changes are localised in one place.
If you are the owner of both the web service and the client.
And you need the parameters of the web service calls to be complex classes which contain not only data but also behavior (actual coded logic) then you are in a bit of a pickle when developing these web services using web service frame works.
As suggested in the answer by Rob Cooper you can use pure xml as web service parameters and xml serialization, but there is a cleaner solution.
If you are using Visual Studio 2005 (probably applies the same for 2008), You can customize the way VS creates you proxy as described in this article:
Customizing generated Web Service proxies in Visual Studio 2005
This way you can tell VS to use your own classes instead of generating a proxy class.
Well when I think of it, it's pretty much same solution as proposed by Rob Cooper, with the little twist, that you wont be writing a Facade layer your self but will be using VS itself as this layer.

ASP.NET Web Service Results, Proxy Classes and Type Conversion

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

Categories

Resources