jdang

I have some questions regading how to use of data object using WFC Service.
For example I have an object called Student (see codes below), and property IsOver25 this is readOnly property. However, if I do not put set { ;}, it's won't compile . What I need to do here in order to get rid of set { ;} statement. Another problem is using contructors and methods of data object. Since we don't put [ServiceContract] on the data object, I could not use the override ToString() version of Student object on client side. So the question are:

1. What should I do in order to use the constructor of data object
2. What should I do in order to use the methods on data object ( will not many but somes)

Regards,
John dang

using System;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace Dq.Services.Student
{
// Sercice Contract
[ServiceContract]
public interface IStudentService
{
[OperationContract]
Student GetStudent(string studentId);
[OperationContract]
Boolean AddStudent(Student student);
}

// Service
public class StudentService : IStudentService
{

Student IStudentService.GetStudent(string studentId)
{
Student student = new Student();

student.Dob = new DateTime(1970, 1, 24);
student.FullName = "James Bond";
student.Gpa = 3.48f;
student.StudentId = "12345";

return student;

}

Boolean IStudentService.AddStudent(Student student)
{
// Insert student code here;
return true;
}
}

// Data Object
[Serializable, DataContract]
public class Student
{

private string studentId;
private string fullName;
private float gpa;
private DateTime dob;

#region - Code Generated by Ultimate Code Generator....

// [what attribute ]
public Student(string studentId,
string fullName,
float gpa,
DateTime dob)
{
this.studentId = studentId;
this.fullName = fullName;
this.gpa = gpa;
this.dob = dob;
}

[DataMember]
public string StudentId
{
get { return studentId; }
set { studentId = value; }
}

[DataMember]
public string FullName
{
get { return fullName; }
set { fullName = value; }
}

[DataMember]
public float Gpa
{
get { return gpa; }
set { gpa = value; }
}

[DataMember]
public DateTime Dob
{
get { return dob; }
set { dob = value; }
}

[DataMember]
public bool IsOver25
{
get
{
if (DateTime.Now.Year - dob.Year > 25)
return true;
return false;
}
set { ;}
}

// [what attribute ]
public override string ToString()
{
StringBuilder sb = new StringBuilder("***** Student's Info *******\n");
sb.AppendFormat("Student: {0}, Name: {1}, DOB:{2}, GPA:{3}",
studentId, fullName, dob.ToString(), gpa.ToString("{0:f2}"));
return sb.ToString();
}

#endregion

}
}



Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

Sellersss

I am in the process of trying to figure out WCF myself, so may be way off base here.

If you are using the student object on both the server and client, I think you can just drop the [DataContract] attribute from the IsOver25 and because the ToString is using all data in the student object, it should not need an attribute.

I have no idea on the constructor

Shannon





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

jdang

hi Shannon,

Just forget about ToString() method. Usually, I don't put method in data object, however what happen if you want to since C# allows you to do that. If you remove [DataMember] attribute on "IsOver25" property, on client side, you will NOT be able to access to IsOver25 property.

Regards,

JDang





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

Mohammad Makarechian - MSFT

Hello,

If I understand your question correctly, you don't need any attribute on consructors on the service side; you can use them as you do when WCF is not in the picture. On the client side, you'll need special attributes on your (custom) constructors, because the de-serializer populates the fields based on what is received on the wire. See post http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1101309&SiteID=1 on how to control constructor calls on de-serialization.

Thanks.





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

Sellersss

JDang,

That depends on how you build your proxy. I am using the same business classes on both the server and the client, and reference the business object when generating the WCF proxy. WCF transfers the property values the have the [DataMemeber] attribute, but the non attributed properties are also available for use on the client.

I am also pretty sure you can add the "isOver25" property using a partial class on the client. The isOver25 does not add data to the object, so it does not need to be serialized. Or you could make it a method "isOver25()"

Someday I hope to undestand this well enough to drop the "I think" and "I am pretty sure" and can just say "that is the way it works".

Shannon





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

Carlos Figueira - MSFT

Adding to the replies above: what is transferred between client/server in a WCF application is data only - no behavior/code/functionality is passed between client and server. That follows one of the main tenets of service oriented architectures (loose coupling between participants), which enables your service to be called, for example, by a client written in a language other than C#. That's also why the ToString() method is not generated on the client proxy.

If you want to share behavior as well as data in your system, and you have the same class on the client and server, you can do as Sellersss suggested (referencing the classes/assemblies when you generate the client proxy). IsOver25 is not part of the data of the class Student, it's a function of other fields, so it doens't need to be transferred.





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

jdang

Many thanks for your input. However, I do not agree 100% on your explaination about why the property isOver25 or contructors are not generated. Since the client codes ( proxy) is generated based on client's languge not the language which you use to build your class at first, so the ToString() method will be generated as VB.net or J# or C++ as you choose. This is a easy thing to do since all the DotNet languages are managed codes and share the same CLR. One thing I know for sure is we do have a bug when to generate client codes. About how to make to contructors work on client side, I am not quite sure how to use the "StreamingContext" object to force client must use my contructors yet. I need to lean soem more about this before I make any comments.

In my example: IsOver25 is a readOnly property, not a method. when we generate client code it is a read and write property.

[DataMember]
public bool IsOver25
{
get{
if (DateTime.Now.Year - dob.Year > 25)
return true;
return false;
}
set { ;}
}

and this is code generated by SvcUtil.exe

[ [System.Runtime.Serialization.DataMemberAttribute()]
public bool IsOver25
{
get
{
return this.IsOver25Field;
}
set
{
this.IsOver25Field = value;
}
}





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

Mohammad Makarechian - MSFT

There is no bug in this case, but rather your use of data contracts is not correct. Specifically, data contracts require that any property that is a data member be settable; this is by design. The de-serializer needs to be able to populate the object that it creates by setting all data members to some value.

The problem is that IsOver25 is not data but interpretation of data. Based on some calculation on the 'dob' field, IsOver25 returns true or false. The 'dob' field is what contains the data and it is already marked as a data member. If you don't want IsOver25 to be part of the data contract (and thus be settable), you should remove it from the data contract, i.e., not make it a data member. You can then on the client side derive a class from the data contract and add additional logic such as determining if 'dob'.Year is greater than 25, etc.

Please post back if the explanation is not clear.

Thanks.





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

jdang

Makarechian,

Thanks for your comment. WCF is total new to me. At this time I want to know how it works. Therefore, there are a lot of things I doní»t know about this new architecture, please teach me if you doní»t mind.

However, I still do not agree 100% with you on this subject.

The IsOver25 still not "settable", SvcUtil.exec assumes it's "settable", not software developer.

Let me give another problem when I try to generate the proxy codes:

// My Codes

[DataMember]

public float Gpa

{

get { return gpa; }

set

{

if (value > 4.00 || value < 0.00 )

throw new Exception("Invalid number. The valid GPA must be between 0.0 to 4.0");

gpa = value;

}

}

// Proxy Codes

[System.Runtime.Serialization.DataMemberAttribute()]

public float Gpa

{

get

{

return this.GpaField;

}

set

{

this.GpaField = value;

}

}

Where is my validate codes Why SvcUtil.exe modifies our logic Then the program will produce unexpected result. If the software developer are not allow to right codes anywhere in side the Get and Set methods, then why we create get and set for To me you should not make any assumptions at all. If the code is valid for C# but not for WCF then SvcUtil.exe needs to raise error at least.

If you think it works by design, then I think Microsoft needs to help it's clients to fix this problem ASAP otherwise we are not be able to use this technique to implements our solutions at all.

Regards,

Jdang





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

Mohammad Makarechian - MSFT

I think what might help you understand the behaviour that you see is if you take a step back and look at the situation conceptually.

A data contract, as the name suggests, is a contract for the data that is sent and received between a client and a service. This means, data is serialized and de-serialized, and the only thing that goes on the wire is data, not any logic whatsoever, such as the logic that you used in your example to determine if the value is larger than four or less than zero.

Once you understand the above, you'll hopefully see that svcutil.exe has no clue about any logic that you have added to a data member on your service side; all it knows is that there's a 'float' value on the wire and that it needs to set that property to some value on de-serialization, so it produces a simple settable property on the client side.

Any logic of determining if the actual value is acceptable due to some business logic is the responsibility of the added-on logic on either the client or service side because none of this information sent on the wire.

To answer your question, software developers are allowed to write as much logic in the get and set properties on either side, but should not expect that information to be part of the data contract and thus should not expect the proxy code (generated by svcutil.exe) to contain that logic. The service side can validate the data that it receives, and the client side code can do the same on the data that it receives from the service (either in a reply message or request in the case of a callback implmentation).

I hope this makes sense.

Thanks.





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

jdang

Thanks for your input.

After talking to many people, I think we will NOT using SvcUtil.exe to generates proxy for data object because we have to scarify too much C# features such as Read-Only property, extra codes inside set or get methods and constructors since we need to see the proxy of data object look alike to data object on the server side. What we need to do is change the design a little bit to separate the services and data objects in to different namespaces.
For example the name space could be like this:

CompanyName.Apps.DataContract.Employee
CompanyName.Apps.DataContract.Customer

CompanyName.Apps.ServiceContract.Employee
CompanyName.Apps.ServiceContract.Customer

On the data objects, DO NOT put any [DataContract] attribute on your data class since you will not using SvcUtil.exe to generate proxies of data objects for client.

On the client side, we need to reference to namespace of DataContract only not the ServiceContract ; then use SvcUtil.exe to generate the proxies for ServiceContracts for client.

This design gives you more control when try to deploy application with WCF architecture. If anyone see something wrong with this design please share the ideas.

Regards
Jdang





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

Mohammad Makarechian - MSFT

I did not quite follow your design decision. If you're sending data between the client and server, you'll need to have them serialized and de-serialized by a serialization engine and Data Contract is WCF's engine. Thus, you'll need to make your data objects (which I assume will be exchanged between the client and the server) data contracts.

My recommendation would be to clearly separate your data from any additional logic that you want to act on the data (such as interpreting/validating the data as received/sent on the client/server side), and share that logic, if it's the same logic on both sides, as assembly references between the client and the server. The main point is to separate your data from the operations that use the data; the operations would go inside one or more contracts (depending on how you want to organize the operations).

You'll still have to use svcutil.exe to create proxy code not only for the service contract and its operations, but also for the data contracts (as well as message contract, if any is used/applicable) because they'll be exchanged between the client and the server.

Thanks.





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

macfarmw

Hello Mohammad,

If I create an service operation that returns the type DateTime I don't think the svcutil creates a proxy of DateTime on the client. I can use the System.DateTime object on both service and client. WCF just serializes the date and passes it to the client where it is then deserialized back into a DateTime. If I create a custom class and make it serializable can I use the custom class as a parameter or return type in the same way

Matthew





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

Mohammad Makarechian - MSFT

Hello Matthew,

You are correct: DateTime is natively supported by WCF's serialization engine, Data Contract, and thus svcutil.exe will not generate a data contract proxy class for it.

The answer to your second question is yes. You'll have to make sure that you have correctly created a data class that can be serialized (and de-serialized) by WCF. Using data contract is the recommended approach. Please start by looking at the WCF documentation and samples to get started on defining your own serializable data contracts.

Thanks.





Re: Windows Communication Foundation (Indigo) How to use constructors or methods of data object with WCF service

macfarmw

Mohammad,

If I create a data object with the Data Contract attributes and then deploy this object on both the client and the server, will I be using a proxy of the data object in the client or will I be using the actual object

Thanks,

Matthew