how to use MessageParameterAttribute in wcf - wcf

I wanted to know what is the use of MessageParameterAttribute in wcf.
In my function:
[OperationContract]
public float GetAirfare(
[MessageParameter(Name=”fromCity”)] string originCity,
[MessageParameter(Name=”toCity”)] string destinationCity);
I dont use fromCity or toCity anywhere in the implementation or even while using a service. Then whats the point in giving it a name?

This attribute is used to control serialization. It can be particularly useful when you want to use a keyword or type name in the resulting XSD schema that describes an incoming message. Likewise, you can control the XML element name for the return value in a response message. It can also be a useful attribute for standardizing on XML element naming conventions, separate from CLR naming conventions. For example, you may prefer to use camel case for parameter names and Pascal case for XML.
If we were to use your provided code snippet as an example, the request would look like:
<s:Body>
<GetAirFare xmlns="yournamespacehere">
<fromCity>Chicago</fromCity>
<toCity>Las Vegas</toCity>
</GetAirFare>
</s:Body>

Related

Can we use [DataMember] instead of [ProtoMember] while use protobuf in WCF?

I've already a service working using the DataContract attributes. We would like to switch to the protobuf implementation, but if we have to change all the attributes, it would be a lot of hardwork.
Is it possible to NOT use the ProtoMember and ProtoContract and have ProtoBuf using the DataMember and DataContract attributes?
thanks
Sure; protobuf-net is perfectly happy with [DataContract] / [DataMember] as long as it can still get valid numbers, which it does by looking for the Order property of DataMemberAttribute.
There is, however, a small problem... tools like svcutil don't guarantee the actual numbers - just the order. This can make it problematic to ensure that you have the same numbers of both sides. In addition, svcutil tends to start at zero, not one - and zero is not a valid field number for protobuf. If the numbers you get all turn out to be off-by-one, then you can tweak this by adding a partial class in a seperate file with a fixup, for example:
[ProtoContract(DataMemberOffset = 1)]
partial class Whatever { }
However, if the numbers are now all over the place (because they weren't sequential originally), they you might want to either use multiple [ProtoPartialMember(...)] attributes to tell it how to map each one (remembering that you can use nameof rather than hard-coding the member names):
[ProtoContract]
[ProtoPartialMember(1, nameof(SomeStringValue))]
[ProtoPartialMember(2, nameof(WhateverId))]
partial class Whatever { }
or just share the original type definition, which might be easier.

WCF Serialised List object giving strange names for objects

Here is the Method signature in the WCF service:
APIMessageList<APISimpleContact> GetMembers(string apiKey, APIContactSearchFilter filter);
APIMessageList inherits from IList. Once I have built a proxy against this WCF service the class name is APIMessageListOfAPISimpleContactjHldnYZV.
Why do I not get: APIMessageListOfAPISimpleContact?
It adds random text to the end of every APIMessageList object in the interface (there are several) They all end with the same few chars - jHldnYZV. I have looked online for possible causes, but I can't find any posts of people having this problem.
This is a purely cosmetic issue but this interface is exposed to our external customers so its appearance is important.
Anybody know why I am getting this problem?
Many thanks
Joe
Your solution will be at http://msdn.microsoft.com/en-us/library/ms731045.aspx. Basically, since you could have multiple "SimpleContract" classes (in different namespaces), WCF will add a disambiguation hash to the end of the contract name, which is what you have in the 8 chars at the end of the contract name. But you can control that, by using the CollectionDataContract and its Name property:
[CollectionDataContract(Name = "APIMessageListOfSimpleContract")]
public class APIMessageList : IList<SimpleContract> { ... }
We had a similar problem while using Generic types for return values. If we are not specifying a concrete type, the default data contract serializer or the WCF serializer is unable to infer the exact type of the returned entity. Hence it generates a random class name for the returned type.
In our project we overcame this problem by building a data contract which was of specific type and returned the same as a result of a WCF operation call.
My guess is that you are using a generic type and the serializer is unable to infer the type of the returned object.
I suggest you create a Data Transfer Object (DTO) and return the same from the WCF service. That should solve your problem.

Svcutil.exe generates XmlElement property for xsd:any element in schema

I'm using the svcutil tool to generate a set of proxies for a 3rd party wdsl. One of the types, defined in an associated XSD file uses the xs:any element:
<xs:any namespace="##any" processContents="lax"/>
The code produced uses a property of type XmlElement to represent this:
[System.Xml.Serialization.XmlAnyElementAttribute(Order=0)]
public System.Xml.XmlElement Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
What actually needs to go in this field is one of the strongly-typed objects also generated by the tool.
My question is: is there an easy/recommended way to get from an instance of the object to an instance of XmlElement?
All I can think of is serializing the object graph into a XmlDocument and then using that. But that seems awkward.
The generated code is correct for the schema. xs:any mas to a xml blob. You will need to change the schema from xs:any to the specific type if you want the generated code to be more specific.
However, if the schema is not under your control, this is the only correct way to consume the schema. You cannot assume that a message contains any specific type.

Recommended naming conventions for same method with different signatures?

been creating a few wcf methods and i have a method called IsValidLogin ... there various versions, 1 takes 2 strings, 1 takes an object etc.
Of course in WCF you can't overload methods can anyone suggest the best way to name these methods..
I was thinking of IsValidLogin1, IsValidLogin2??
But I am open to any suggestions.
When you start adding index numbers to your identifiers, you're usually doing it wrong.
One way I've seen is adding "With" and the parameter names to the name, i.e. IsValidLoginWithUsernamePassword, and IsValidLoginWithToken (assuming your object is some kind of authentication token). These are kind of long though.
I'd just call the methods IsValidUsernamePassword and IsValidToken.
First of all, you should stick with message/contract first methodology when working with wcf services, passing in a request and returning a response. This will save you a lot of headache down the road.
That being said, you should create two methods like so:
public LoginValidResponse IsLoginValid(UserObjectRequest userRequest)
and
public LoginValidResponse IsLoginValid(UsernamePasswordRequest usernameRequest)
There are probably better names for these, but you get the idea. If you provided more information about what you were passing in and back, I could help out with naming a bit more.
Notice these two methods return the same response LoginValidResponse.
Put your two strings in the UsernamePasswordRequest (I'm assuming the strings are username and password). Put the User Object in the UserObjectRequest.
You can also reuse these requests / responses in later methods, e.g, GetUserInfo(UserObjectRequest request).
The LoginValidResponse will contain your bool (and any other information you want to pass back in your response).
*Note - I only named the methods IsLoginValid b/c that was your question. On top of the request / response pattern, I might also rename the methods to something like ValidateLoginByUser and ValidateLoginByUsername (or something like that).
Of course in WCF you can't overload methods can anyone suggest the best way to name these methods..
You can overload methods in WCF by adding unique OperationContract behaviours. OperationContract has the Name property that exposes the WCF methods to WSDL Schemas. Your service-side (WCF) code would remain clean. But you would still have to call the methods by signature you defined in the Name property of the OperationContract behaviour.
[OperationContract(Name="IsValidLoginWithUsernameAndPassword")]
void IsValidLogin(string username,string password);
[OperationContract(Name="IsValidLoginWithToken")]
void IsValidLogin(AuthToken token);
Usage......
TestClient client = new TestClient();
string callMethod1 = client.IsValidLoginWithUsernameAndPassword("user","pass");
string callMethod2 = client.IsValidLoginWithToken(authToken);
You can read more here
http://www.codeproject.com/Tips/656042/Method-Overloading-in-WCF
I don't think that IsValidLogin1,2, etc. is clear enough. When you overload methods normally, you don't have to worry about names because it's the same name with different parameters, however in this case you have to remember the parameters for each method, and numbers could get confusting.
I might suggest IsValidLoginNumStr etc, which is to say, maybe list key parameters in the method name to help remind you which method you're referring to. Either that or if one takes a password, then IsValidLoginPass, or something of the like. I say this because I'm a fan of long, descriptive method names. If you want to keep the name short as possible, and you can think of a letter that would help, like P for password, or O for object, then tack on a helpful letter at the end. Something more than a number will help you in the long run

How to transfer objects through the header in WCF

I'm trying to transfer some user information in the header of the message through message inspectors.
I have created a behavior which adds the inspector to the service (both client and server).
But when I try to communicate with the service I get the following error:
XmlException:
Name cannot begin with the '<' character, hexadecimal value 0x3C.
I have also get exception telling me that DataContracts where unexpected.
Type
'System.DelegateSerializationHolder+DelegateEntry'
with data contract name
'DelegateSerializationHolder.DelegateEntry:http://schemas.datacontract.org/2004/07/System'
is not expected. Consider using a
DataContractResolver or add any types
not known statically to the list of
known types - for example, by using
the KnownTypeAttribute attribute or by
adding them to the list of known types
passed to DataContractSerializer.
The thing is that my object contains other objects which are marked as DataContract and I'm not interested adding the KnownType attribute for those types.
Another problem might be that my object to serialize is very restricted in form of internal class and internal properties etc.
Can anyone guide me in the right direction. What I'm I doing wrong?
Some code:
public virtual object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var header = MessageHeader.CreateHeader("<name>", "<namespace>", object);
request.Headers.Add(header);
return Guid.NewGuid();
}
Don't put the angle brackets into the actual strings. Remember, the serialization format may not even be text based, all you're doing is specifying the name of the element and the namespace. So your code should look more like this:
var header = MessageHeader.CreateHeader("name", "urn:myNamespace", object);
request.Headers.Add(header);
To close this question, I never solved the exception. Instead I implementated ISerializable which worked great for me.