How to ignore a DataMember from the superclass in a subclass - wcf

The title is pretty self-explanatory.
I have a base WCF DataContract, let's call it the PersonContract, which covers all fields of the Person entity in my database.
I have a number of client applications that call the same service through endpoints of different interfaces implemented by that service. This is because (amongst other differences) I want every of those applications to be able to access and edit only a specific subset of the Person entity.
Now if I want to define a contract with all the properties of PersonContract except one, can I subclass PersonContract and ignore a single property in the subclass?
Or is my only option building contracts from the smallest subset (but I doubt I can fully avoid repeating code then)?

Out of curiosity I did a couple tests and it doesn't look like it'll work.
Here are the data contracts I used:
[DataContract]
public class Person
{
[DataMember]
public virtual string FirstName { get; set; }
[DataMember]
public virtual string MidName { get; set; }
[DataMember]
public virtual string LastName { get; set; }
}
[DataContract]
public class Person2 : Person
{
[IgnoreDataMember]
public override string MidName { get; set; }
}
And my service contract:
public interface IService1
{
[OperationContract]
Person GetPerson();
[OperationContract]
Person2 GetPerson2();
}
Both operations return the same result.
Another way that you might be able to produce the results you're looking for could be to define your minimal contract (the one with missing the excluded properties) and inherit from it adding the field needed by the other operation.
The equivalent data contracts would look something like:
[DataContract]
public class Person2 : Person
{
[DataMember]
public virtual string MidName { get; set; }
}
[DataContract]
public class Person
{
[DataMember]
public virtual string FirstName { get; set; }
[DataMember]
public virtual string LastName { get; set; }
}
And I've verified that the results are as I would expect.

Related

how to create a multiple datacontract class using wcf services

I have create a simple user login WCF Services.I have using large number of datamember properties in one datacontract class.so i have split the datamember properties in different class. for example (Userdetails class with using userid,usertype,username,password,address,city,state,phoneno,mobileno,country,pincode,etc...)so i have split on the two Datacontract classes into userdetails as Userinfo and contactdetails class.The userinfo class only define the userdetails only and contactdetails class defined contact details as. how to use on the multiple datacontact class in WCF services can you please explain them.
I'm not sure what exactly you want. but i hope you could use something like this:
[DataContract]
public class User
{
[DataMember]
public userdetails Userinfo { set; get; }
[DataMember]
public contactdetails contactdetails { set; get; }
}
[DataContract]
public class userdetails
{
[DataMember]
public long userid { set; get; }
[DataMember]
public string usertype { set; get; }
}
[DataContract]
public class contactdetails
{
[DataMember]
public long mobileNumber { set; get; }
[DataMember]
public string phoneNumber { set; get; }
}

How to set [DataMember] on an autogenerated proxy property

I am working on a wcf webservice. This service uses a third party webservice which I have added as a service reference.
Now I want to publish some properties of this proxyclient to clients who uses my wcfservice, without defining an own class and doing the mapping.
The auto generated code is done as partial class.
public partial class Person : object,
System.ComponentModel.INotifyPropertyChanged
{
public string FirstName;
public string LastName;
...
}
I tried to override these properties by using the MetadataType-Attribute and adding the [DataMember]-Attribute to properties. But this seams to work only for EF.
[DataContract]
[MetadataType(typeof(PersonMetaData))]
public partial class Person
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
public class PersonMetaData
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
Trying to implement an interface didn't help, the properties are invisible on client.
[DataContract]
public partial class Person : IPerson
{}
public interface IPerson
{
[DataMember]
string FirstName { get; set; }
[DataMember]
string LastName { get; set; }
}
Any idea?
Guido
On my service XmlSerializer failed to serialize the auto-generated class cause of PropertyChanged-event.
If I work with DataContractSerializer and decorate my auto-generated class with [DataContract], I'm not able to decorate the properties by inheritance with [DataMember] because the attibute is not inheritable.
So I extended this partial class by wrapper properties.
[DataContract]
public partial class Person
{
[DataMember]
public string FirstNameWrapper
{
get
{
return this.FirstName;
}
set
{
this.FirstName = value;
}
}
}

Data Contract for Two database Tables during Join Condition

I have 2 tables in my DB like Patient Table and Appointment Table
for which I have created 2 Data Contracts namely Patient,Appointment in my WCFREST Service.
I use List<Patient> to fill the DB Table info in the List object and
List<Appointment> to fill the DB Table info in List obj as well.
Here I have an Operation Contract which returns data from 2 tables using Join Statement
For that how should I store the result, because I have 2 different objects ?
Do I need to create one more DataContract by combining fields of these two tables?
Use Entity frame work (table first or model first approach). But as you already have tables available you might want to base your model on the tables. Whatever way you choose ultimately your Data Contract should look as below:
[DataContract]
public class Patient
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public List<Appointment> Appointments { get; set; }
}
[DataContract]
public class Appointment
{
[DataMember]
public int ID { get; set; }
[DataMember]
public DateTime AppointmentTime { get; set; }
[DataMember]
public Address Venue { get; set; }
}
Trick is to make DataContract for each of table. You don't have to create multiple data contracts to match your needs.
The service contract should be as below:
[ServiceContract]
public interface IPatientService
{
[OperationContract]
List<Patient> GetAllPatients();
}
you can then use the DbContext provided by the EF in combination with extensions (Dependency injection) as below. Or just get rid of the constructor if you don't want to go advanced with it and create _context object right on intialization. Here is a sample.
public class PatientService : IPatientService
{
HospitalDbContext _context;
public PatientService(HospitalDbContext _context)
{
this._context = _context;
}
public List<Patient> GetAllPatients()
{
return (from patient in _context.Patients
select patient).ToList<Patient>();
}
}
You are free to add LINQ conditions here to take joins and other operations as well.
[DataContract]
class A
{
[DataMember]
public string PatientName { get; set; }
// more stuff.
}
[DataContract]
class B
{
[DataMember]
public string HospitalName { get; set; }
// more stuff.
}
[DataContract]
class C
{
[DataMember]
public A prop1 { get; set; }
[DataMember]
public B prop2 { get; set; }
// more stuff.
}

Consuming WCF Service with DataContract

I do have a simple WCF service in which If I put the method with simple Data Type then I can access that service in the MVC project which is in same Solution. But if I change the Data Type of the Service method even to array or list of string or any other simple Data Type, I cannot access the service. Do I need to make any config changes.
[DataContract]
public class Property
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string PropertyPost { get; set; }
[DataMember]
public string PropertyType { get; set; }
[DataMember]
public string DealType { get; set; }
[DataMember]
public string Department { get; set; }
[DataMember]
public string ProjectName { get; set; }
}
I actually want to return the List from the WCF service for which I have created the Datacontract, but it is not working even with simple List Type.
Do we need to specify anything in Service like WebInvoke?
Can any one help?

Building application with Entity framework dbContext API issues

I am developing a WCF Service application. It is going to be a part of large system. It provides some business logic and is based on Entity framework 4.1. I want to divide application code into 2 tiers (projects in VS, dll's): Service (which contains business logic) and DAL.
I have such database model in my project
ClassModel
classID : int, PK
classIdentity : string
teacherName : string
statisticInfo : int
isRegistered : bool
StudentModel
studentID : int, PK
studentIdentity : string
classID : int, FK
For this I am generating code using dbContext templates and I get:
public partial class ClassModel
{
public ClassModel()
{
this.Student = new HashSet<StudentModel>();
}
public int ClassID { get; set; }
public string ClassIdentity { get; set; }
public string TeacherName { get; set; }
public int StatisticInfo { get; set; }
public bool IsRegistered { get; set; }
public virtual ICollection<TerminalModel> Terminal { get; set; }
}
public partial class StudentModel
{
public int StudentID { get; set; }
public string StudentIdentity { get; set; }
public bool IsRegistered { get; set; }
public virtual ClassModel Class { get; set; }
}
I want to expose only some of this information through the service, so I have different model as a data contract:
[DataContract]
public class Clas{
[DataMember]
public string ClassIdentity {get;set;}
[DataMember]
public string TeacherName {get;set;}
[DataMember]
public string ClassMark {get;set;} //computed from statisticInfo
[DataMember]
public int NumberOfStudents {get;set;} //amount of students in this class
}
And my part of my ServiceContract:
[OperationContract]
public void RegsterClass(Clas clas); //(if given clas does not exists adds it and) sets its isRegistered column to True
[OperationContract]
public Clas GetClass(string classIdentity);
As you can see some fields are not present, others are being computed.
In such case I have some concerns about how should I built application properly. Could you write example code which implements the interface methods using everything I mentioned in the way that you think is proper?
Try using T4 templates
It is possible to use T4 templates to generate the dbContext classes, the data transfer objecs (more on that later), the interface as well as all the two methods you have there for each entity in your model: RegsterClass and GetClass. (this would translate to RegsterStudent, GetStudent, and so on for every entity)
Then you can use AutoMapper on NuGet to map from Clas to ClassModel.
I've implemented something similar. I don't pass any of my dbcontext based entities across the wire. I use Data transfer objects for each entity. So a Toyota entity, has a ToyotaDto that has the data annotations and is used for all the WCF CRUD operations. When "Getting" a toyotaDto, I map Toyota to ToyotaDto and return the Dto, when saving, I map the Dto to an entity, of course deleting is done by key, so no Dto necessary.
There are several(1) good(2) examples(3) online you can modify to suit, and if you want I can paste in some of the templates I'm using.