I have two .NET 3.5 WCF services build with VS2008.
I have two WCF clients in Silverlight to consume these services. The clients are generated with the 'Add Service Reference'. I am using Silverlight 4.
ONE of the proxies is generated with Specified properties for each property. This is a 'message-in' class for my service method :
// properties are generated for each of these fields
private long customerProfileIdField;
private bool customerProfileIdFieldSpecified;
private bool testEnvField;
private bool testEnvFieldSpecified;
Now my other service (still with a Silverlight client) does NOT generate Specified properties.
Now I don't care about 'tenets of good SOA'. I just want to get rid of these damn properties because in the context of what I'm doing I absolutely hate them.
There has to be some difference between the two services - but I don't want to have to completely rip them apart to find out the difference.
A similar question before had the answer 'you cant do it' - which is definitely not true because I have it - I just don't know what I did differently.
Edit: I am now in a situation where I regenerate my Silverlight 4 proxy to my 3.5 WCF service (all on the same localhost machine) that sometimes I get 'Specified' properties and sometimes I don't. I no longer think (as I suspected originally) that this is due solely to some endpoint configuration or service level [attribute]. Theres certain triggers in the message itself that cause Specified to be generated (or not). There may be many factors involved or it may be something very simple.
try this in your WCF service where the property is declared
[DataMember(IsRequired=true)]
public bool testEnvField { get; set; }
IsRequired=true will negate the need for the testEnvFieldSpecified property
These extra Specified properties are generated for value types which are being specified as optional in either the contract or the attribute markup.
As value types have a value by default, the extra Specified flags are being added for these properties, to allow the client (and server) to distinguish between something explicitly not specified or explicitly specified - which may well be set to the default value. Without it, integers would always end up being 0 (and being serialized) even if you don't set them (because of the mapping to int) in your client code. So when you do, you need to also make sure that you set the Specified flag to true, otherwise these properties will not get serialized.
So to prevent these flags being generated for value types, you would have to change the contract to make these value type properties mandatory, instead of optional.
Hope that makes sense.
OK I've found one thing so far that will cause Specified properties to be generated:
The presence of an XTypedElement in the message.
These are used by Linq2XSD. I was returning an element from a Linq2XSD model.
This triggered Specified properties to be generated EVERYTHING in all my classes :
public XTypedElement Foo { get; set; }
This however didn't :
public XElement Foo { get; set; }
Still curious as to why this is, and if there are any other things that trigger this.
NOTE: I realize this is an old question. I'm adding this here because this question comes up as a top result on Google, and it's helpful information for whoever comes looking.
Try adding this line into your operation contract declaration:
[XmlSerializerFormat]
It should look something like this:
namespace WebServiceContract
{
[ServiceContract(Namespace = "http://namespace")]
[XmlSerializerFormat] //This line here will cause it to serialize the "optional" parameters correctly, and not generate the extra
interface InterfaceName
{
/*...Your web service stuff here...*/
}
}
I found that if I put a DataTable in a service DataContract then the generated client will use xml serializer and thus generate the *IsSpecified members.
Related
I've managed to reproduce one of the errors in a test project with a similar structure to my production code. It consists of three simple projects:
Common (class library):
namespace Common
{
public enum PrimaryColor
{
Red,
Green,
Blue
};
}
Library (WCF service library), which has a reference to Common:
using Common;
namespace Library
{
[ServiceContract]
public interface ILibrary
{
[OperationContract]
PrimaryColor GetColor();
}
public class Library : ILibrary
{
public PrimaryColor GetColor()
{
return PrimaryColor.Red;
}
}
}
ClientApp (console application), which has a reference to Common, and a service reference to Library called "LibraryServiceReference":
using Common;
using ClientApp.LibraryServiceReference;
namespace ClientApp
{
class Program
{
static void Main(string[] args)
{
LibraryClient client = new LibraryClient("WSHttpBinding_ILibrary");
PrimaryColor color = client.GetColor();
}
}
}
The app.config files in ClientApp and Library are auto-generated and I have not modified them, and I have not changed the default configuration for the LibraryServiceReference in ClientApp.
When I compile this solution, I get the following errors in the ClientApp project:
Error 1
'PrimaryColor' is an ambiguous reference between 'Common.PrimaryColor' and 'ClientApp.LibraryServiceReference.PrimaryColor'
Error 2
Cannot implicitly convert type 'ClientApp.LibraryServiceReference.PrimaryColor' to 'Common.PrimaryColor'. An explicit conversion exists (are you missing a cast?)
please help me to fix this.
Make sure that 'Reuse types in all referenced assemblies' is selected in the Advanced options of Add service reference or Configure Service Reference.
it's because you're building x64 not "AnyCpu". I am running across this right now, and am trying to figure out if it's a bug, or if it's expected behavior.
Decorate your enum like this:
namespace Common
{
[DataContract]
public enum PrimaryColor
{
[EnumMember]
Red,
[EnumMember]
Green,
[EnumMember]
Blue
};
}
Update Your service reference (with checking reuse types just like Mark stated).
Rebuild your client code.
I have had this issue arise in innocuous, unpredictable manners so many times! I thought I'd share how I "fixed" it this last time.
I am using Visual Studio 2013 - but have had the issue down rev.
The ambiguous reference seems to come on by itself. I did nothing of note to cause it. In the latest instance I was debugging some code behind and suddenly I had 7, then 22 then 49 errors - all of the same nature.
I deleted the service reference altogether and re-added it. Simply modifying the re-use type did nothing. My solution has a WCF service, Class Library, UI and a Control Library. I also removed the using - in some code behind, of the class library.
This is an exceptionally troublesome issue which thankfully only occurs about every few weeks. Why this worked? Beyond my pay grade. I feel your pain! Hope this helps. In this case, the error came on, again, when I opened some code behind on a xaml page.
It sounds like you control both the client and the server code. Why do you want to create a service reference, is there a specific reason or is it just deemed easier?
In projects where you control both sides of the client server application you are better of creating a "contract assembly" (which is probably your common assembly). This contains the interfaces and objects that are involved with the contract and should be referenced by both your client and your server. In order to communicate with the service the client creates a proxy class using the ChannelFactory, there is no need to have a dedicated WCF client.
Example:
ChannelFactory<ISampleService> factory = new ChannelFactory<ISampleService>("Binding_from_config");
ISampleService sampleService = factory.CreateChannel();
sampleService.SomeCall();
factory.Close();
The factory pattern also makes it an ideal candidate for injecting your proxy in via IoC.
The benefits of referencing a common assembly over creating a service reference are:
No ambiguous reference as there will be no need for auto generated classes.
You will not have to update your service reference every time you change the contract.
For what it's worth, I was running in to this same error after moving my data contracts to a separate library. Updated the service references multiple times and tried all combinations of the settings for assembly reuse, to no avail.
What eventually fixed it for me was to 1) restart Visual Studio and 2) update the service reference. The auto-generated code in Reference.cs in the service definition looked very different and did not duplicate my data contract class. It used the proper reference from my library. So something must be getting cached in the IDE.
Hopefully someone else finds this useful.
I was able to fix this by right-clicking on the Service Reference and then changing from "Reuse types in all referenced assemblies" to "Reuse types in specified referenced assemblies" and then checking the specific common assembly.
Just remove the reference to Common project from your ClientApp project and the error should go away. When you're creating a proxy for your service, all dependent code from the service must be injected into the proxy. If you want your types to be same as those on the service side, just enable the 'Reuse types' option while generating the proxy code (otherwise they will be put under a different namespace).
The problem here is that PrimaryColor exists in both Common and ClientApp.LibraryServiceReference and you are referencing both namespaces in your class.
To overcome this issue, either explicitly reference the instance that you require, i.e.
Common.PrimaryColor color = ....
or set up an alias:
using Service = ClientLibraryServiceReference;
...
Service.PrimaryColor color = ......
When making the service reference aren't there some options that say something like: "inlcude common types in generated service contract" ?
I have the idea that in your service reference the classes are "copied" and that's why you get this error. Inspect the generated service files, remove then and add them again with "Add Service Reference" and see what options you have there.
EDIT
Although I'm almost sure that the Type PrimaryColor is defined twice. One time in the common project and one time in your service reference, you can also try this in your clientApp (to more explicitely specify the PrimaryColor Type):
Common.PrimaryColor color = client.GetColor();
Following advices from people on the internet about service references, I got rid of them now and split the service/data contracts into a common assembly accesible by both the server and the client. Overall this seems to work really well.
However I’m running into problems when trying to use custom objects, or rather custom subtypes, in the service. Initially I wanted to define only interfaces in the common assembly as the contract for the data. I quickly learned that this won’t work though because the client needs a concrete class to instantiate objects when receiving objects from the service. So instead I used a simple class instead, basically like this:
// (defined in the common assembly)
public class TestObject
{
public string Value { get; set; }
}
Then in the service contract (interface), I have a method that returns such an object.
Now if I simply create such an object in the service implementation and return it, it works just fine. However I want to define a subtype of it in the service (or the underlying business logic), that defines a few more things (for example methods for database access, or just some methods that work on the objects).
So for simplicity, the subtype looks like this:
// (defined on the server)
public class DbTestObject : TestObject
{
public string Value { get; set; }
public DbTestObject(string val)
{
Value = val;
}
}
And in the service, instead of creating a TestObject, I create the subtype and return it:
public TestObject GetTestObject()
{
return new DbTestObject("foobar");
}
If I run this now, and make the client call GetTestObject, then I immediately get a CommunicationException with the following error text: “The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:09:59.9380000'.”
I already found out, that the reason for this is that the client does not know how to deserialize the DbTestObject. One solution would be to declare the base type with the KnownTypeAttribute to make it know about the subtype. But that would require the subtype to be moved into the common assembly, which is of course something I want to avoid, as I want the logic separated from the client.
Is there a way to tell the client to only use the TestObject type for deserialization; or would the solution for this be to use data transfer objects anyway?
As #Sixto Saez has pointed out, inheritance and WCF don't tend to go together very well. The reason is that inheritance belongs very much to the OO world and not the messaging passing world.
Having said that, if you are in control of both ends of the service, KnownType permits you to escape the constraints of message passing and leverage the benefits of inheritance. To avoid taking the dependency you can utilise the ability of the KnownTypeAttribute to take a method name, rather than a type parameter. This allows you to dynamically specify the known types at run time.
E.g.
[KnownType("GetKnownTestObjects")]
[DataContract]
public class TestObject
{
[DataMember]
public string Value { get; set; }
public static IEnumerable<Type> GetKnownTestObjects()
{
return Registry.GetKnown<TestObject>();
}
}
Using this technique, you can effectively invert the dependency.
Registry is a simple class that allows other assemblies to register types at run-time as being subtypes of the specified base class. This task can be performed when the application bootstraps itself and if you wish can be done, for instance, by reflecting across the types in the assembly(ies) containing your subtypes.
This achieves your goal of allowing subtypes to be handled correctly without the TestObject assembly needing to take a reference on the subtype assembly(ies).
I have used this technique successfully in 'closed loop' applications where both the client and server are controlled. You should note that this technique is a little slower because calls to your GetKnownTestObjects method have to be made repeatedly at both ends while serialising/deserialising. However, if you're prepared to live with this slight downside it is a fairly clean way of providing generic web services using WCF. It also eliminates the need for all those 'KnownTypeAttributes' specifying actual types.
In some enterprise-like project (.NET, WCF) i saw that all service contracts accept a single Request parameter and always return Response:
[DataContract]
public class CustomerRequest : RequestBase {
[DataMember]
public long Id { get; set; }
}
[DataContract]
public class CustomerResponse : ResponseBase {
[DataMember]
public CustomerInfo Customer { get; set; }
}
where RequestBase/ResponseBase contain common stuff like ErrorCode, Context, etc. Bodies of both service methods and proxies are wrapped in try/catch, so the only way to check for errors is looking at ResponseBase.ErrorCode (which is enumeration).
I want to know how this technique is called and why it's better compared to passing what's needed as method parameters and using standard WCF context passing/faults mechanisms?
The pattern you are talking about is based on Contract First development. It is, however not necessary that you use the Error block pattern in WCF, you can still throw faultexceptions back to the client, instead of using the Error Xml block. The Error block has been used for a very long time and therefore, a lot of people are accustom to its use. Also, other platform developers (java for example) are not as familiar with faultExceptions, even though it is an industry standard.
http://docs.oasis-open.org/wsrf/wsrf-ws_base_faults-1.2-spec-os.pdf
The Request / Response pattern is very valuable in SOA (Service Oriented Architecture), and I would recommend using it rather than creating methods that take in parameters and pass back a value or object. You will see the benefits when you start creating your messages. As stated previously, they evolved from Contract First Development, where one would create the messages first using XSDs and generate your classes based on the XSDs. This process was used in classic web services to ensure all of your datatypes would serialize properly in SOAP. With the advent of WCF, the datacontractserializer is more intelligent and knows how to serialize types that would previously not serialize properly(e.g., ArrayLists, List, and so on).
The benefits of Request-Response Pattern are:
You can inherit all of your request and responses from base objects where you can maintain consistency for common properties (error block for example).
Web Services should by nature require as little documentation as possible. This pattern allows just that. Take for instance a method like public BusScheduleResponse GetBusScheduleByDateRange(BusDateRangeRequest request); The client will know by default what to pass in and what they are getting back, as well, when they build the request, they can see what is required and what is optional. Say this request has properties like Carriers [Flag Enum] (Required), StartDate(Required), EndDate(Required), PriceRange (optional), MinSeatsAvailable(Option), etc... you get the point.
When the user received the response, it can contain a lot more data than just the usual return object. Error block, Tracking information, whatever, use your imagination.
In the BusScheduleResponse Example, This could return Multiple Arrays of bus schedule information for multiple Carriers.
Hope this helps.
One word of caution. Don't get confused and think I am talking about generating your own [MessageContract]s. Your Requests and Responses are DataContracts. I just want to make sure I am not confusing you. No one should create their own MessageContracts in WCF, unless they have a really good reason to do so.
lHi,
I'm currently writing a WCF service.
One of those methods get's a request object and returns a response object. In the request there are a couple of value-type members.
Is there a way to define members are mandatory in the declarative way?
I'm in an early stage of development and I don't want to start with versioning now. In addition I don't want to have method sig with 25 parameters, therefore I created the request object.
The problem I have is that due to the value-types, I can never be sure if the consumer of the service intended to have the default value in there, or it was just by lazyness.
On consumer side you don't easily detect that you probably missed that property.
So I would like to have something that forces the caller of the service to provide an value, and if not he ideally get's a compile-time error.
any ideas?
tia,
Martin
Yes, absolutely:
[DataContract]
public class YourRequestClass
{
[DataMember(IsRequired=true)]
int RequestID { get; set; }
}
There are a number of sub-attributes to the DataMember attribute that you can use - Order and IsRequired probably being the most frequently used ones.
Please check if the following is resolving your issue:
IsRequired/EmitDefaultValue Attribute on DataMember
http://social.msdn.microsoft.com/forums/en-US/wcf/thread/d9e45449-cc50-42e2-b955-75ab86f01d4f
The topic above describes a combination of
IsRequired and EmitDefaultValue attributes set on a request member, which according to the discussion there at least seams to resolve the "issue"
cheers
Adding a service reference to a web service (this is all WCF) in Visual Studio produces some generated code including a client-side restatement of the interface being exposed.
I understand why this interface is generated: you might be consuming a 3rd party service and not have access to the actual interface.
But I do, and the two are not assignment compatible even though the transparent proxy does indeed exactly implement the interface to which I want to cast.
I can use reflection, but that's ugly. Is there some way to defeat this faux type safety and inject metadata to so I can use an interface with a class?
My specific problem departs from the norm in complicated ways that have to do with a single client that uses some derivatives of a base class directly and uses others remotely via service references. The base class for each server needs to keep references to subscribing clients in a collection for enumeration to notify events, and the problem was type varied due to the use of proxies.
None of these answers solves my specific problem, yet every single answer was instructive and helpful. I found my own solution (use a dual binding) but I would never have figured it out if you hadn't radically improved my understanding of the whole business.
Three excellent answers. How to choose just one? I choose the first, because it directly solves the problem I first thought I had.
If you already have the contract dll at the client, you don't even need a service reference (unless you are using it to write the setup code for you) - you can simply subclass ClientBase and expose the Channel, and use that directly - something like (no IDE handy...):
public class WcfClient<T> : ClientBase<T> where T : class
{
public new T Channel {get {return base.Channel;}}
}
Then you can just do things like:
using(var client = new WcfClient<IFoo>())
{
client.Channel.Bar(); // defined by IFoo
}
You still need the configuration settings in the config to determine the address, binding, etc - but less messy than proxy generation. Also, you might choose to re-implement IDipsoable to deal with the fact that WCF proxies can throw in Dispose() (which is bad):
public class WcfClient<T> : ClientBase<T>, IDisposable where T : class
{
public new T Channel {get {return base.Channel;}}
void IDisposable.Dispose() {
try {
switch(State) {
case CommunicationState.Open: Close(); break;
// etc
}
} catch {} // swallow it down (perhaps log it first)
}
}
When you add the service reference, go to "Advanced" and make sure "Reuse types in referenced assemblies" is selected and that the assembly containing your interface definition is selected. You can also do this with an existing service reference by right clicking on it and going to "Configure".
In order to return an interface from a service you need to use the KnownType attribute:
http://weblogs.asp.net/avnerk/archive/2006/07/31/WCF-Serialization-part-1_3A00_-Interfaces_2C00_-Base-classes-and-the-NetDataContractFormatSerializer.aspx
If you want to return a custom type from the service:
http://msdn.microsoft.com/en-us/library/bb628653.aspx
Does any of that help?