I am learning wcf, and I am seeing this opt in and opt out serialization. I am still scratching my head. I have already seen this SO post. But it didn't help. Can someone explain me succinctly what it is?
actually its so simple:
Opt-In approach says properties that are considered to be part of DataContract must be explicitly marked othewise will be ignore, while Opt-Out means all of the properties will be assumed to be part of the DataContract unless marked explicitly.
namespace MySchoolService
{
[DataContract]
public class Student
{
[DataMember]
public string StudentNumber;
[DataMember]
public string FirstName;
[DataMember]
public string LastName;
public string MarksObtained;
}
[ServiceContract]
public interface IStudentService
{
//Service Code Here.
}
}
In above code StudentNumber, FirstName, LastName properties of Student class are explicitly marked with DataMember attribute as oppose to MarksObtained, so MarksObtained will be ignored.
Below code represents an example of Opt-Out approach.
namespace MySchoolService
{
[Serializable()]
public class Student
{
public string StudentNumber;
public string FirstName;
public string LastName;
[NonSerialized()]
public string marksObtained;
}
[ServiceContract]
public interface IStudentService
{
//Service Code Here.
}
}
In above example, we explicitly marked MarksObtained property as [NonSerialized()] attribute, so it will be ignored except the others.
hope could help you.
Related
Lets say that I have this line of code:
public abstract class User
{
public string name;
public string email;
public string password;
public abstract void Create();
public abstract void Remove();
public abstract void Modify();
}
And then another abstract class:
public abstract class AbstractCustomer : User
{
public string address;
public Order order;
public abstract override void Create(string n,string e,string pa,int ph,string a);
public abstract override void Modify(string e, string pa, int ph, string a);
public abstract override void Remove(Order o);
public abstract void PlaceOrder(Item i);
public abstract void MakePayment(Order o);
}
and we have the customer which implements the AbstractCustomer:
public class Customer : AbstractCustomer
{
public override void Create(string name, string email, string password, int phoneNum, string address)
{
this.name = name;
this.email = email;
this.password = password;
this.phoneNum = phoneNum;
this.address = address;
this.isActive = true;
ConnectionToDB.SaveCustToDB();
}
public override void Remove(Order order)
{
order.CancelOrder();
}
public override void Modify(string email, string password, int phoneNum, string address)
{
ConnectionToDB.UpdateCustInDB();
}
public override void PlaceOrder(Item item)
{
order = new Order(item);
}
public override void MakePayment(Order order)
{
ConnectionToDB.SavePayToDB(order);
}
}
and this is where the problem starts (this is a helper class whose purpose is to call the methods easily)
public static void Create(AbstractCustomer user, string name, string email, string password, int phoneNum, string address)
{
user.Create(name, email, password, phoneNum, address);
}
public static void Remove(AbstractCustomer user, Order order)
{
user.Remove(order);
}
public static void Modify(AbstractCustomer user, string email, string password, int phoneNum, string address)
{
user.Modify(email, password, phoneNum, address);
}
public static void PlaceOrder(AbstractCustomer user, Item item)
{
user.PlaceOrder(item);
}
public static void MakePayment(AbstractCustomer user, Order order)
{
user.MakePayment(order);
}
These lines of codes produces errors like:
VS will tell you that the Customer class didn't implement the User's abstract methods(well, I think I did because I tried overriding it in the AbstractCustomer). But apparently, we don't need to override it in the Abstract class because the child class(Customer) will automatically inherits it and from there you can just directly override the methods. I found the explanation here overriding abstract methods in an inherited abstract class
But by doing the above solution, it presents another problem. The AbstractCustomer class will lose its purpose and therefore the HelperClass can't call any methods because its static classes depends on the AbstractCustomer that will be passed in the method.
So for the questions: (Problem: Grouping the methods into a static class for me to call it easily)
Is there a way to fix this kind of problem?(I'm thinking of using decorator pattern)
If I use the decorator pattern, what is the purpose of the ConcreteComponent?Is it okay if I remove it?
If I don't use the decorator pattern, is there any pattern available for this kind of problem?
If I don't use any pattern, is there any way to solve this?
Thanks for reading! Sorry coz its a long one! :)
Your solution is not related to Decorator pattern. Decorator - it is something, that should be inherited from existing abstraction (AbstractCustomer in your case) and add extra logic to it (it can be logging, or it can be extra check of each method's parameters for null, or something like that...). See this link.
Btw, I don't like the way how you construct your abstractions. It is better to have well-grained interfaces for each of your methods, e.g. ICanCreate for Create() method, ICanRemove for Remove() method, etc. It allows you to control further types which will implement that functionality. E.g., one customer can implement only ICanCreate interface, another one - ICanCreate + ICanRemove, etc.
I have the following class I'd like to send from my WCF (C#) service to my client (WPF):
[DataContract]
public class OutputAvailableEventArgs
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Message { get; private set; }
[DataMember]
public bool IsError { get; private set; }
public OutputAvailableEventArgs(int id) : this(id, false, "") { }
public OutputAvailableEventArgs(int id, string output) : this(id, false, output) { }
public OutputAvailableEventArgs(int id, bool isError, string output)
{
ID = id;
IsError = isError;
Message = output;
}
}
It's used by the service as follows:
var channel = OperationContext.Current.GetCallbackChannel<IClientCallback>();
channel.OutputAvailable(new OutputAvailableEventArgs(1, false, "some message"));
At the client side, the members get their default values.
I tried marking them with IsRequired attribute but now the OutputAvailable at the client is not called. The code at the service side seems to run smoothly (I didn't notice anything with the debugger).
How can I transfer a DataContract class with WCF while maintaining the members' values?
(I saw solutions that suggested to use OnSerialized and OnDeserialized but I don't need just a default constructor.)
I saw many different solutions for this problem. For other people's sake I'll write some of them down + what worked for me:
It seems that in some cases specifying the items' order solves the problem. Please see this SO question for full details.
If it's some default initialization you're after, you can use OnSerialized and OnDeserialized methods to call your initialization methods.
I also tried using the IsRequired attribute on my DataMembers but still didn't get my objects.
What worked for me was adding NameSpace property in the DataContract attribute. Apparently, In order to have the contracts be considered equal, you must set the Namespace property on the DataContract to the same value on both sides.
I have a problem with serialization composite class (using WCF Service).
here my class in namespace1 (it is not in service namespace) :
[DataContract]
public class UpData
{
[DataMember]
public double Version ;
public UpData()
{
this.Version = -1;
}
}
In my Service namespace (in interface) I deŃlare this procedure :
ArrayList GetDownloadPath(Dictionary<string,string> lib1, Dictionary<string,string> lib2);
ArrayList contains UpData objects.
I have error(
How will be right to send ArrayList of UpData objects? (may be specific DataContract?)
Thanks a lot!
I'm not sure if ArrayList is serializable by default. Using a generic list could solve your problem:
[OperationContract]
List<UpData> GetDownloadPath(Dictionary<string,string> lib1, Dictionary<string,string> lib2);
EDIT: I think you also need to specify a getter and setter for your Version property, i.e.
[DataContract]
public class UpData
{
[DataMember]
public double Version { get; set; }
public UpData()
{
this.Version = -1;
}
}
More info here.
I have a WCF service where I am trying to return a List (where IWatchable is a custom interface I have built) in one of my operation contracts. When I test the service on the client the method returns an object[] instead of List<IWatchable>. Is it possible to return a List of IWatchable, since IWatchable is an interface with WCF?
Method:
public List<IWatchable> GetWorkload( Guid nodeId, int maximum )
IWatchable:
public interface IWatchable
{
string ActionName { get; set; }
Guid ActionReference { get; set; }
}
Hopefully a bit more info will be helpful...
I have a derived interface:
public interface IAMRAWatchable: IWatchable
And three concrete implementations from IAMRAWatchable:
public class InstrumentationWatch: IAMRAWatchable
public class OutputWatch: IAMRAWatchable
etc...
In my WCF method that returns List<IWatchable> I want to send an InstrumentationWatch and an OutputWatch to the client... Is this possible or am I going about this the wrong way?
Resolved
Thanks to John I found my solution. KnownType wasn't working since I was using List<IWatchable> - So I wrapped my list into a new class and added the attributes to it. I'll need to re-factor my code but for others who are interested here is the class:
[DataContract]
[KnownType( typeof( InstrumentationWatch ) )]
[KnownType( typeof( OutputWatch ) )]
public class WorkInfo
{
[DataMember]
public List<IWatchable> WorkQueue { get; set; }
}
and my WCF method:
public WorkInfo GetWorkload( Guid nodeId, int maximum )
An interface can never be serialized. It is only a description of behavior.
You can serialize objects which implement the interface, but you must tell WCF what their types are. See Data Contract Known Types.
I m trying to rest-ify our existing WCF service and one of the hurdle is mapping complex type using Uritemplate. For example take a look at the below code
[DataContract]
public class Stock
{
[DataMember]
public string Symbol { get;set; }
[DataMember]
public double FaceValue { get; set; }
}
[ServiceContract]
public interface IRestService
{
[OperationContract]
[WebGet(UriTemplate = "?Symbol={stk.Symbol}")]
void Test1(Stock stk);
}
The above Uritemplate declaration will definitely not work, but this is what is my intention of mapping the input query variable to one of the property of that object.. Is this possible ?
Tks in advance for your help.
The example you give doesn't illustrate the problem. In that case, all that's needed is to pass a stock symbol, a simple string, and there's no need for a complex type.
In cases where you want to pass a more complex set of data, a JSON-encoded object, use WebInvoke with PUT or POST, a non-parameterized UriTemplate, and pass form data. See this answer for details.
In cases where you want GET, and can pass a small set of discrete parameters, you can use WebGet, an appropriate UriTemplate, and do the manual mapping. like so:
public enum OptionFlavor { Put, Call }
public class OptionInqury { public String Symbol; public String Month; public OptionFlavor Flavor;}
[OperationContract]
[WebGet(UriTemplate = "/optionquote/{stockSymbol}/{month}/{flavor}")]
void GetOptionPrice(string stockSymbol, string month, string flavor)
{
var x = new OptionInquiry {
Symbol = stockSymbol,
Month = month,
Flavor = (flavor.Equals("put")) ? OptionFlavor.Put : OptionFlavor.Call
};
// off you go...
}
If you want to map your query string parameters to the properties in your object, you need to go with WebInvoke. Unfortunately with GET, you will have to do this manually.