Do I need to translate enum values across a WCF service? - wcf

The scenario is as follows: I implemented a WCF service (lets call it X) which has its own data objects.
The service X is using another WCF service (Y) which has its own set of data objects. Service X needs to pass some data it receive from service Y to its clients (service X clients).
As far as i know, it is considered a "best practice" to translatethe objects received from Y service to data objects of X service.
What is the best practice when it comes to Enum values? Do i need to map each enum value or is there another way?

Generally the idea is to isolate users of your service from changes in your implementation. Therefore, you do not expose your implementation types on the wire. Image the situation where you decide to rename an enum value. If the service consumer does not update their implementation you will have introduced a breaking change as the service user will be sending the old enum value to you which will not deserialize correctly.
In addition you may find that not all of the enum values are applicable to users of your service (maybe they are used internally)
So, yes, you should translate enum values just like other types
If you give your enums explicit numeric values you could translate between them using casts
class Program
{
static void Main(string[] args)
{
Internal i = Internal.Too;
External e = (External) i;
Console.WriteLine(e);
}
}
enum Internal
{
One = 1,
Too = 2
}
[DataContract]
enum External
{
[EnumMember]
One = 1,
[EnumMember]
Two = 2
}
However, you would have to be careful that they did not become out of sync

Related

HttpContext.Features vs HttpContext.Items In Asp.Net Core

What is the differences between these two Properties?
I can use HttpContext.Items instead of HttpContext.Features to share data between middlewares. The only difference I see is that I tell Items for a key and it gives me an object and I have to cast it. This casting can be done in Features automatically.
Is there something else behind them?
The biggest difference is that the HttpContext.Items is designed to store Key-Value-Pair, while the HttpContext.Features is designed to store Type-Instance-Pair.
To be more clear, HttpContext.Items is designed to share items within the scope of current request, while the HttpContext.Features, which is an instance of IFeatureCollection, is by no means to be used like that .
The IFeatureCollection interface represents a collection of HTTP features, such as:
IAuthenticationFeature which stores original PathBase and original Path.
ISessionFeature which stores current Session.
IHttpConnectionFeature which stores the underlying connection.
and so on.
To help store and retrieve a Type-Instance-Pair, the interface has three important methods:
public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>{
// ...
object this[Type key] { get; set; }
TFeature Get<TFeature>();
void Set<TFeature>(TFeature instance);
}
and the implementation (FeatureCollection) will simply cast the value into required type:
public class FeatureCollection : IFeatureCollection
{
// ... get the required type of feature
public TFeature Get<TFeature>()
{
return (TFeature)this[typeof(TFeature)]; // note: cast here!
}
public void Set<TFeature>(TFeature instance)
{
this[typeof(TFeature)] = instance; // note!
}
}
This is by design. Because there's no need to store two IHttpConnectionFeature instances or two ISession instances.
While you can store some Type-Value pairs with FeatureCollection, you'd better not . As you see, the Set<TFeature>(TFeature instance) will simply replace the old one if the some type already exists in the collection; it also means there will be a bug if you have two of the same type.
HttpContext.Items is designed to share short-lived per-request data, as you mentioned.
HttpContext.Features is designed to share various HTTP features that allow middleware to create or modify the application's hosting pipeline. It's already filled with several features from .NET, such as IHttpSendFileFeature.
You should use HttpContext.Items to store data, and HttpContext.Features to add any new HTTP features that another middleware class might need.

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.

WCF Service Contract

I have a problem using an custom data type in a WCF service method, below is my sample code
[ServiceContract()]
public class SampleServise : ISampleServise
{
void object GetSomething(ICustomData objectData)
{
// Do Something
}
}
What shall I do with ICustomData class interface?
Thanks
Afshin
WCF is based on message passing, and that message passing is modelled using XML schema (XSD). As such, whatever can be expressed in XML schema can be used in WCF.
This also means: interfaces are not supported. You need to use actual, concrete types for the parameters in your WCF service methods.
In your case, create a concrete class that implements ICustomData and then use that class as the parameter type.
For a good reference, read MSDN Designing Service Contracts which states for parameters:
Parameters and Return Values
Each operation has a return value and a parameter, even if these are
void. However, unlike a local method, in which you can pass references
to objects from one object to another, service operations do not pass
references to objects. Instead, they pass copies of the objects.
This is significant because each type used in a parameter or return
value must be serializable; that is, it must be possible to convert an
object of that type into a stream of bytes and from a stream of bytes
into an object.

wcf and asp.net communication

I am creating an website. It has two web pages. I am trying to pass value between the two pages using wcf..
WCF has two functions
static int a;
void send(int b)
{
a=b;
}
int get()
{
return a;
}
class1 creates an object for wcf(say w) and calls w.send(5)
class2 creates an object for wcf(say w1) and calls a= w1.get()
But the value changed by class1 is not getting reflected in class2..
How are you hosting your service?
If your service is hosted in IIS, it is possible that the application was recycled between the 2 calls. In this case the app domain is recreated and the static members loose their values.
By the vary nature WCF is stateless.. What is done by w.send(5) is not known to w1.get() as both the calls are treated as seperate calls.
Either you save the data in some statefull mechanism like (table or file) or else the behavior is as expected.
Though it's static variable but when you create new object it will refer to that particular object only. SO when you are setting value of one variable with one object and getting value from other object then it wont give correct value.
So
w.send(5)
a= w1.get()
wont work.

WCF Sharing an object between Client and Host

Hey, I can't seem to access the returned value from a method I called on my Host.
//Service---------------------------------------------------------
[DataMember]
private List<CalculationRecord> History = new List<CalculationRecord>();
public IEnumerable<CalculationRecord> CalculationHistory()
{
return (IEnumerable<CalculationRecord>)History;
}
public CalculationResult Calculate(CalculationNode problem)
{
CalculationResult calcResult = new CalculationResult();
//Calculates results of expression
CalculationEvaluation Evaluator = new CalculationEvaluation();
Evaluator.Calculate(problem, calcResult);
return calcResult;
}
//interface---------------------------------------------------------
[ServiceContract]
public interface ICalculate
{
[OperationContract]
CalculationResult Calculate(CalculationNode problem);
[OperationContract]
IEnumerable<CalculationRecord> CalculationHistory();
}
//Client------------------------------------------------------------
CalculatorClient client = new CalculatorClient();
ICalculate calcProxy = client.ChannelFactory.CreateChannel();
CalculationNode calcRootNode = parser.Parse(expression);
CalculationResult result = calcProxy.Calculate(calcRootNode);//result is null
You're under a wrong impression - the DataContract that the server exposes can (and should) only contain data - never any behavior. As such, you can never share an object between client and host - all you can share are service methods to call, and concrete types to use on those methods. That's it.
The process is this: when the client connects up to the server, it will download the metadata for the service - it can find out what service methods are available, what data those take - but it cannot infer any additional methods on the data contract. It just can't. The client then builds up an exact copy of the data contract type - but it's a totally separate class, and it only matches the server-side data contract class as far as its serialized representation in XML is concerned. It is not the same class - it just look the same.
Because in the end, all that happens between the server and the client is an exchange of a serialized message - basically a XML text document. You are not sending across a .NET object! All you're exchanging is a data representation of your data contract, nothing more.
So in your case, the client side proxy will have a new class that looks like the one the server uses - at least on the serialized level on the wire - but it will not contain the Calculate method. The Calculate method you're calling is on the service contract - it's not the one on the data member you have.
In your concrete example, too - you seem to be intermixing [DataMember] and service interface definition. Avoid this at all costs. Also, all the types involved in the calculation - most definitely CalculationNode and CalculationResult - must be exposed as [DataContract] elements containing a number of [DataMember] fields or properties. This is not clear from the snippet of code you posted.