I am new to WCF and facing some issue. I have three project WCFClient,WCFService,CommonModel
CommonModel :- Have below classes
public class Room: INotifyPropertyChanged
{
int roomID;
public virtual int roomID_PK { get; set; }
public Room()
{
Row1Details = new RoomRowDetails();
Row2Details = new RoomRowDetails();
}
}
[Serializable]
public class RoomRowDetails : ISerializable, INotifyPropertyChanged
{
public RoomRowDetails()
{
RoomColor = "White";
RowSaleAmount = "";
}
....
}
WCFClient : is having client proxy class.
WCFService: Have ServiceContract OperationContract DataContract and have below class :-
[DataContract()]
[ServiceKnownType(typeof(Room))]
[ServiceKnownType(typeof(RoomRowDetails))]
public class RequestData
{
[DataMember]
public string ClientName { get; set; }
[DataMember]
public bool isServer { get; set; }
[DataMember]
public bool isSuccess { get; set; }
[DataMember]
public Room room { get; set; }
[DataMember]
public RoomRowDetails roomrow{ get; set; }
}
In both the project CommandModel project is added as a reference. Client proxy is generated properly but when run the project. I got below error:-
There was an error while trying to serialize parameter http://tempuri.org/:eventData. The InnerException message was 'Type 'CommonModel.MODELS.Room' with data contract name 'Room:http://schemas.datacontract.org/2004/07/CommonModel.MODELS' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.
Can you please help me out how can i use CommonModel classes in WCF service and client (So Room is shared POCO between both the project) and avoid above error?
Thanks
Related
I have an object called Organization that represents different rows in a database table called ORGANIZATION. Some organizations represent merchants and the merchant can have a "MerchantAux" record.
The Organization class looks like this:
[DataContract]
public class Organization : Core.Framework.BaseEntity
{
[Key]
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public virtual MerchantAux MerchantAuxRecord { get; set; }
public Organization()
{
}
}
The MerchantAux class looks like this:
[DataContract]
public class MerchantAux : BaseEntity
{
[Key]
[DataMember]
public int Code { get; set; }
[DataMember]
public int SettlementDelay { get; set; }
[DataMember]
public Nullable<System.Guid> WalletSiteId { get; set; }
[DataMember]
public bool? AddCardNotPresent { get; set; }
[DataMember]
public bool? BatchEmailNotification { get; set; }
[DataMember]
public string CsvEmailRecipients { get; set; }
[IgnoreDataMember]
public virtual ICollection<Organization> Organizations { get; set; }
public MerchantAux()
{
Organizations = new List<Organization>();
}
}
These objects are defined in a Models assembly. The WCF Service Assembly has a ServiceContract and OperationContracts to Get and Save Organizations.
Getting an organization works without issue. Saving an organization is failing with a VERY strange result.
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter boardingservice:organization. The InnerException message was 'The use of type 'MerchantAux' as a get-only collection is not supported with NetDataContractSerializer. Consider marking the type with the CollectionDataContractAttribute attribute or the SerializableAttribute attribute or adding a setter to the property.'. Please see InnerException for more details.
And there is no inner exception.
Oh yeah... Soap UI has no problem calling the Save method, but a .Net client throws the above error. Has anyone else seen this behavior where the serializer thinks that an object is a collection?
For the curious, I did try changing it to CollectionDataContract instead, but of course it fails straight away with an exception saying that MerchantAux doesn't implement IEnumerable (duh). Anyway... any ideas would be great.
As part of my WCF web service's return message I created three custom classes. They are implemented in my the return message class, which contains a DataContract decoration (pretty sure that's how it's supposed to be done).
However when I run the Visual Studio 2012 WCF Test Client I get the following error message (highlighted in black)
App Code
Class exposed to the program calling the web service. This calls a method with a return type of CloneMessage (detailed below)
namespace OKeeffeDataService
{
public class MonetToDss : IMonetToDss
{
private AgentCloneRules _agentClone;
public MonetToDss()
{
_agentClone = new AgentCloneRules();
}
[PrincipalPermission(SecurityAction.Demand, Role = "AgentPaymentUpdater")]
public CloneMessage CloneRequest(string agentId)
{
//TODO: Validate agent Id?
EventLog.WriteEntry("OKeeffe", "Made it to CloneRequest", EventLogEntryType.Information);
return _agentClone.CloneRequest(agentId);
}
}
}
App Code Interface
namespace OKeeffeDataService
{
[ServiceContract]
public interface IMonetToDss
{
[OperationContract]
CloneMessage CloneRequest(string agentId);
}
}
Clone Message Class
This is the class the WCF service returns. The AgentClone and RelationshipCode classes were generated by the Entity Framework and extend System.Data.Objects.DataClasses.EntityObject. AgentAddresses is a custom class I wrote with standard string properties representing Street, City, State, Zip, etc (listed below).
namespace BusinessEntities
{
[DataContract]
public class CloneMessage : ICloneMessage
{
[DataMember]
public AgentClone AgentInformation { get; set; }
[DataMember]
public IList<AgentAddress> AgentAddresses { get; set; }
[DataMember]
public IList<RelationshipCode> RelationshipCodes { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
public CloneMessage(){}
public CloneMessage(AgentClone agtTran, IList<AgentAddress> addresses, IList<RelationshipCode> relationshipCodes)
{
this.AgentInformation = agtTran;
this.AgentAddresses = addresses;
this.RelationshipCodes = relationshipCodes;
}
}
}
Clone Message Interface
namespace BusinessEntities
{
public interface ICloneMessage
{
AgentClone AgentInformation { get; set; }
IList<AgentAddress> AgentAddresses { get; set; }
IList<RelationshipCode> RelationshipCodes { get; set; }
String ErrorMessage { get; set; }
}
}
EDIT
Adding the enum and classes to the post
AgentAddresses class
AddressType is custom enum.
namespace BusinessEntities
{
[DataContract]
public class AgentAddress : IAgentAddress
{
[DataMember]
public AddressTypeValues.AddressType AddressType { get; set; }
[DataMember]
public string Street1 { get; set; }
[DataMember]
public string Street2 { get; set; }
[DataMember]
public string Street3 { get; set; }
[DataMember]
public string City { get; set; }
[DataMember]
public string State { get; set; }
[DataMember]
public string ZipCode { get; set; }
}
}
AddressTypeValues enum
namespace BusinessEntities
{
public class AddressTypeValues
{
[DataContract(Name = "AddressType")]
public enum AddressType
{
[EnumMember(Value = "Home")]
Home,
[EnumMember(Value = "Mailing")]
Mailing,
[EnumMember(Value = "Location")]
Location,
[EnumMember(Value = "Other")]
Other
}
}
}
AgentClone and RelationshipCode class headers
[EdmEntityTypeAttribute(NamespaceName="AgentResourcesReturn", Name="AgentClone")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class AgentClone : EntityObject
[EdmEntityTypeAttribute(NamespaceName="AgentResourcesReturn", Name="RelationshipCode")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class RelationshipCode : EntityObject
Try adding the following known types to your CloneMessage data contract.
[DataContract]
[KnownType(typeof(AgentClone))]
[KnownType(typeof(AgentAddress))]
[KnownType(typeof(RelationshipCode))]
public class CloneMessage : ICloneMessage
And this AddressTypeValues type to the AgentAddress class.
[DataContract]
[KnownType(typeof(AddressTypeValues))]
public class AgentAddress : IAgentAddress
Once you do this, rebuild the service and try to browse it again the WCF test client.
Add DataContract attribute to AgentClone & RelationshipCode classes
If AddressTypeValues.AddressType is Enum type, then apply the DataContractAttribute attribute to the type. You must then apply the EnumMemberAttribute attribute to each member that must be included in the data contract. refer - http://msdn.microsoft.com/en-us/library/aa347875(v=vs.110).aspx
Add the below attributes to CloneMessage class
[KnownType(typeof(AgentAddress))]
[KnownType(typeof(RelationshipCode))]
try changing like this..
namespace BusinessEntities
{
[DataContract(Name = "AddressType")]
public enum AddressType
{
[EnumMember(Value = "Home")]
Home,
[EnumMember(Value = "Mailing")]
Mailing,
[EnumMember(Value = "Location")]
Location,
[EnumMember(Value = "Other")]
Other
}
}
[DataMember]
public AddressType AddressType { get; set; }
If you are still facing issue, then I am 100% sure that the problem is with AgentInformation/RelationshipCodes. Just comment these two members of CloneMessage class and try. you will get some pointers. If you don't face issue after commenting, then it is something to do with EntityObject. similar issue - Why doesn't WCFTestclient understand standard EF objects but understands STE objects
I have solution with 3 projects:
1. Client (reference: DataContracts and ServiceReference created via Visual Studio 2012 with name TaskerWcfService)
2. DataContracts
3. WCF Service (DataContracts)
First I've created WCFService and in DataContracts was only one class:
[DataContract]
public class WorkItem
{
[DataMember]
public Int64 Id { get; set; }
[DataMember]
public String Title { get; set; }
[DataMember]
public String Description { get; set; }
[DataMember]
public String ItemType { get; set; }
}
Then, I've created a Client with a ServiceReference (with name: TaskerWcfReference) and namespace for the WorkItem class has been - DataContracts lib.
And finally, I've extended WCF Service and DataContracts with additional class:
public class InfoData
{
[DataMember]
public Guid Id { get; set; }
[DataMember]
public String Value { get; set; }
[DataMember]
public Int32 Order { get; set; }
[DataMember]
public bool IsDefault { get; set; }
}
But when I've updated the ServiceReference I found that InfoData class was inside of the automatically generated proxy and it's namespace is: TaskerWcfReference.InfoData.
Why the classes described in similar way - placed in different places?
The functions of the service contracts return Generic.List and T in same way. Descriptions of the service contracts are similar too.
I have a message contract as under
[MessageContract]
public class PartnerLogViewRequest
{
[MessageBodyMember(Order = 0)]
public PartnerLogView PartnerViewLog { get; set; }
}
And the data contract as under
[DataContract]
public class PartnerLogView
{
public int PartnerViewLogId { get; set; }
public string URL { get; set; }
public string ClientIPAddress { get; set; }
public DateTime CreationDate { get; set; }
}
So the data contract is exposed as a property from the message contract.
Now I have created the client proxy. And want to access the properties of the data contract but could not...
My attempt
PartnerLogViewRequest request = new PartnerLogViewRequest();
request.PartnerViewLog.ExtensionData
Instead of properties to appear, some "ExtensionData" is coming...
What I am missing and how to assign values to the properties of PartnerLogView?
Thanks in advance
You are missing the [DataMember] attribute. I am not sure if you missed it in your query, but you havent created an object for PartnerLogView.
PartnerLogView partnerLogView = new PartnerLogView();
partnerLogView.PartnerViewLogId =0;
...
...
PartnerLogViewRequest request = new PartnerLogViewRequest();
request.PartnerViewLog=partnerLogView;
I am trying to use the WCF Test Client to test a WCF service I have built.
The service has one method "SubmitRequest".
[OperationContract]
Response SubmitRequest(Request request);
When I load up the WCF Test Client, the method is grayed out with the message "This operation is not supported in the WCF Test Client because it uses type WcfLibrary.Objects.Request
Below is the type definition, does anyone see anything wrong?
[DataContract]
public class Request
{
[DataMember]
public string LoanNumber { get; set; }
[DataMember]
public string ClientCode { get; set; }
[DataMember]
public Region Region { get; set; }
[DataMember]
public RequestType RequestType { get; set; }
[DataMember]
public List<RequestParameter> RequestParameters { get; set; }
[DataMember]
public List<MspWebCallType> MspWebCallsForXmlRequest { get; set; }
[DataMember]
public Hashtable XmlRequestParameters { get; set; }
public Request(string loanNumber, string clientCode, Region region, RequestType requestType, List<RequestParameter> requestParameters)
{
LoanNumber = loanNumber;
ClientCode = clientCode;
Region = region;
RequestType = requestType;
RequestParameters = requestParameters;
}
}
[DataContract]
public class MspWebCallType
{
[DataMember]
public string WebService { get; set; }
[DataMember]
public string Operation { get; set; }
[DataMember]
public string Version { get; set; }
[DataMember]
public Hashtable Parameters { get; set; }
[DataMember]
public Msp.FavReadViews FAVReadViewIndicator { get; set; }
[DataMember]
public Msp.DsReadIndicators DSReadInidicator { get; set; }
}
[DataContract]
public enum Region
{
[EnumMember]
P2,
[EnumMember]
PROD
}
[DataContract]
public enum RequestType
{
[EnumMember]
None,
[EnumMember]
XmlRequest,
[EnumMember]
SomeOtherRequestType
}
[DataContract]
public struct RequestParameter
{
[DataMember]
public string ParameterName { get; set; }
[DataMember]
public string ParameterValue { get; set; }
}
Thanks.
EDIT w/ answer...
The operation was not available via the WCF Test Client because the type MspWebCallType had a property of type Hashtable. Once I removed this property it fixed the issue. Thanks for everyone's help.
The following is a list of features not supported by WCF Test Client:
Types: Stream, Message, XmlElement, XmlAttribute, XmlNode, types that
implement the IXmlSerializable interface, including the related
XmlSchemaProviderAttribute attribute, and the XDocument and XElement
types and the ADO.NET DataTable type.
Duplex contract.
Transaction.
Security: CardSpace , Certificate, and Username/Password.
Bindings: WSFederationbinding, any Context bindings and Https binding,
WebHttpbinding (Json response message support).
Source: MSDN
Check Msp.FavReadViews and Msp.DsReadIndicators to ensure they comply.
It might be because Request needs to have a public non-parametric constructor.
Answering here as this is the first result on Google currently for this error:
In addition to #Igby Largeman 's answer, you will also receive this error if somewhere in your operation or data contracts, you have used a type that is not serializable.
Take an example of the Exception class in .NET...
I had a case whereby a developer on my team had opted to send back the Exception object to the service's client via a DTO, rather than put the exception message into the DTO manually. Visual Studio will not warn you at build time (it should, really), that the class is not serializable, it will only fail at runtime.
So if you are receiving this error and have ruled out the answer above, ensure you check the types used in your contracts and DTOs; something not being serializable could be your culprit.
I hope this saves someone some time.
I had the same error and the problem was that the class had an System.Drawing.Image property. I remove it from the class and it worked. I convert the byte array to a base64 string.