Send a list with appointments through WCF - wcf

I would like to send a list of Appointments through WCF. My Interface looks like this:
[ServiceContract]
public interface IServices
{
[OperationContract]
string addAppointments(List<Appointment> appointmentList);
}
If I call my WCF Service I'm always getting the following error:
Type 'Microsoft.Exchange.WebServices.Data.Appointment' cannot be
serialized. Consider marking it with the DataContractAttribute
attribute, and marking all of its members you want serialized with the
DataMemberAttribute attribute. See the Microsoft .NET Framework
documentation for other supported types.
My Service currently looks like this:
class Service : IServices
{
public string addAppointments(List<Appointment> appointmentList)
{
foreach (Appointment app in appointmentList)
{
Console.WriteLine(app.Organizer.Name);
}
return "true";
}
}

It's not your service that's at fault, it's the class your passing, Appointment.
Start by adding [DataContract] to your class. then [DataMember] to each of the properties you'd like to pass.
For example, if you started with:
public class Appointment{
public DateTime Date { get; set; }
public string Name { get; set; }
}
You can make it serializable by WCF's DataContractSerializer by adding those attributes:
[DataContract]
public class Appointment{
[DataMember]
public DateTime Date { get; set; }
[DataMember]
public string Name { get; set; }
}

Related

How do we send a message with Object type or a abstract class to the masstransit message

Currently, I want to pass an object type to the message to avoid reading the DB twice.
But my solution which has the RabbitMQ is not a reference to the domain entities, it only has the abstract class and the interface of the entities.
So, Is there any way to pass an abstract class or interface to the message of the RabbitMQ?
Thank you for your advices!
public interface IDomainEntity
{
// The rest of the code
}
public abstract class Person
{
// The rest of the code
}
public class Employee
{
// The rest of the code
}
public class Employee: IDomainEntity, Person
{
// The rest of the code
}
public class RefreshEmployeeCache : CorrelatedBy<Guid>
{
public Guid EmployeeId { get; set; }
public Person Employee { get; set; } // or public IDomainEntity Employee { get; set; } Can we use this or an althernative way?
public bool IsDeleted { get; set; }
public Guid CorrelationId { get; set; } = Guid.NewGuid();
}
You should be able to cast the message to an object, which should use the Publish(object message) overload (or the Send(object message) overload), allows whatever concrete type is present to be published.
Consumers can implement IConsumer<Person>, providing access to the properties of Person. The subclass type would only be available if it is known to the consumer and requested specifically.

How to setup a DataContract to match the complex XML input in WCF 4.0 REST Service

I have a XML structure like this:
<Message>
<Messagehead>
<OSType>Android</OSType>
<RouteDest>SiteServerName</RouteDest>
<ActionType>Enroll</ActionType>
</Messagehead>
<MessageBody>
<Raw>
<![CDATA[OrienginalMessageContent]]>
</Raw>
</MessageBody>
</Message>
and I want upload this XML to WCF 4.0 my rest service:
public string Enroll(Message instance)
{
// TODO: Add the new instance of SampleItem to the collection
return "success";
}
the Message is a DataContract type, I setup it like below:
[DataContract(Namespace = "")]
public class Message
{
[DataMember]
public MessageHead MessageHead { get; set; }
[DataMember]
public MessageBody MessageBody { get; set; }
}
public class MessageHead
{
public OSType OSType { get; set; }
public string RouteDest { get; set; }
public Action Action { get; set; }
}
public class MessageBody
{
public string RawRequestContent { get; set; }
}
but when I get the Message instance from the server side, all the property is null, except the OSType, can anybody tell me why? How could I solve this problem?
Besides being a really bad name for a class (since it's already used in the WCF runtime), your Message class also has some flaws:
<Message>
<Messagehead>
....
</Messagehead>
Your <Messagehead> has a lower-case h in the middle - yet your class defines it to be upper case:
[DataContract(Namespace = "")]
public class Message
{
[DataMember]
public MessageHead MessageHead { get; set; }
This will not work - case is important and relevant in a WCF message! If your XML has a lower-case h, so must your DataContract class!
Your XML also requires a <Raw> tag inside your <MessageBody>
<MessageBody>
<Raw>
<![CDATA[OriginalMessageContent]]>
</Raw>
</MessageBody>
yet your data contract doesn't respect that:
public class MessageBody
{
public string RawRequestContent { get; set; }
}
Again - those don't line up! Names are important - and they must match between your XML representation of the message, and the C# class representing that message.....

Solve a circular reference in WCF from my POCOs

I have a couple of classes (for now) and I'm trying to clear up a circular reference between the two since it is killing WCF's serialization.
I am using EF with POCOs in a WCF REST service is that helps. I have simplified my problem down to bare bones for an easy example here:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Groups
{
[WebGet(UriTemplate = "")]
public Message GetCollection()
{
var message = new Message { Body = "Test message" };
var group = new Group { Title = "Title of group" };
message.Group = group;
group.Messages = new List<Message> { message };
return message;
}
}
public class Message
{
public string Body { get; set; }
public Group Group { get; set; }
}
[DataContract(IsReference = true)]
public class Group
{
public string Title { get; set; }
public ICollection<Message> Messages { get; set; }
}
I have added the [DataContract(IsReference = true)] to the Group class so that the circular reference is cleaned up however my returned results end up like this:
<Message xmlns="http://schemas.datacontract.org/2004/07/LmApi" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Body>Test message</Body>
<Group z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"/>
</Message>
Where are the properties of the Group and how can I get them?
BritishDeveloper,
There are no properties associated with Group. That's why all you see is the ID of 1.
The reason is that as soon as you annotate the Group class with [DataContract(IsReference = true)], you are telling the DataContract serializer that it's no longer a POCO type. It's a DataContract type.
So, to serialize Group with properties, you now need to go ahead and annotate the Title and Message properties with DataMemberAttribute.
An alternative would be use the "preserveObjectReferences", which you can pass as a parameter to DataContractSerializer, DataContractSerializerOperationBehavior, and other classes.
Hope this helps!
I decided to make my own smaller classes that have a constructor that takes an entity and sets all of this lighterweight properties correctly.
Basically it is a very small copy of the class that has just the properties needed in the payload. (Obviously I have excluded the problem navigation properties)
This is similar to Circular References and WCF Here is my answer modified for this case
I had the same problem and resolved it by excluding the navigation property back to the parent from the DataContract
[DataContract]
public partial class Message
{
[DataMember]
public virtual string Body { get; set; }
[DataMember]
public virtual Group Group { get; set; }
}
[DataContract]
public partial class Group
{
[DataMember]
public virtual string Title { get; set; }
public virtual ICollection<Message> Messages {get; set;}
}

RIA DomainService not generating client code using DataContracts

I'm working on a Silverlight 4.0 application and am using RIA services. I have created a class on the server-side which has DataContract and DataMember attributes applied to it.
A DomainService exposes this class as a query result and as such, generates code for it on the client. But somehow it doesn't generate code for all properties of the class. Primitive properties of type guid, string, int, bool etc are generated just fine, but if I have a property of my own complex type, that property isn't created on the client.
Here's the class in question:
[DataContract]
[KnownType(typeof(SummaryGroup))]
public class SummaryDataSet
{
public SummaryDataSet()
{
}
[KeyAttribute]
[DataMember]
public Guid Guid { get; set; }
[DataMember]
public SummaryGroup SummaryGroup { get; set; }
}
The Guid property is created on the client just fine. The SummaryGroup property isn't created on the client. Here's the code for the SummaryGroup:
[DataContract]
public class SummaryGroup
{
public SummaryGroup()
{
}
[KeyAttribute]
[DataMember]
public Guid Guid { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int Sequence { get; set; }
}
Both classes are in the same namespace.
Question: why isn't the SummaryGroup property of SummaryDataSet created on the client and what should I do to fix this?
WCF RIA cannot handle complex types, but you could try this:
[DataContract]
[KnownType(typeof(SummaryDataSet))]
public class SummaryDataSet
{
public SummaryDataSet()
{ }
[KeyAttribute]
[DataMember]
public Guid Guid { get; set; }
[DataMember]
[Association("SummarySet_SummaryGrp_FK", "Guid", "Guid")]
public SummaryGroup SummaryGroup { get; set; }
}
This gives RIA the information to connect from the SummaryDataSet to the SummaryGroup.
This assumes that you can request both the SummaryDataSet and SummaryGroup from the serverside service.

Testing for interface implementation in WCF/SOA

I have a reporting service that implements a number of reports. Each report requires certain parameters. Groups of logically related parameters are placed in an interface, which the report then implements:
[ServiceContract]
[ServiceKnownType(typeof(ExampleReport))]
public interface IService1
{
[OperationContract]
void Process(IReport report);
}
public interface IReport
{
string PrintedBy { get; set; }
}
public interface IApplicableDateRangeParameter
{
DateTime StartDate { get; set; }
DateTime EndDate { get; set; }
}
[DataContract]
public abstract class Report : IReport
{
[DataMember]
public string PrintedBy { get; set; }
}
[DataContract]
public class ExampleReport : Report, IApplicableDateRangeParameter
{
[DataMember]
public DateTime StartDate { get; set; }
[DataMember]
public DateTime EndDate { get; set; }
}
The problem is that the WCF DataContractSerializer does not expose these interfaces in my client library, thus I can't write the generic report generating front-end that I plan to. Can WCF expose these interfaces, or is this a limitation of the serializer? If the latter case, then what is the canonical approach to this OO pattern?
I've looked into NetDataContractSerializer but it doesn't seem to be an officially supported implementation (which means it's not an option in my project). Currently I've resigned myself to including the interfaces in a library that is common between the service and the client application, but this seems like an unnecessary extra dependency to me. Surely there is a more straightforward way to do this? I was under the impression that WCF was supposed to replace .NET remoting; checking if an object implements an interface seems to be one of the most basic features required of a remoting interface?
I believe you just need to put the ServiceContract attribute on the interface defintions, too, as in
[ServiceContract]
public interface IReport
{
[OperationContract]
string PrintedBy { get; set; }
}
etc...