Problem with knowntype attribute in wcf

I have the following error in my wcf client.

The NetDispatcherFaultException was unhandled.

Formatting was ruled out when trying to deserialize the message: an error occurred while trying to deserialize the http://tempuri.org/:GetVehicleResult parameter. The InnerException message was "Error on line 1 of position 266. The element" http://tempuri.org/:GetVehicleResult 'contains data from a type that maps to the name' http://schemas.datacontract.org/2004/07/WCFServer: Car '. Deserializer does not know any type that maps to this name. Consider using a DataContractResolver or add a type matching "Car" to the list of known types, for example, using the KnownTypeAttribute attribute or adding it to the list of known types passed to the DataContractSerializer. '. See InnerException for more information.

Can someone help me where the error is.

WCF Server


IVehicle -------- [ServiceContract] public interface IVehicleService { [OperationContract] Vehicle GetVehicle(int type); [OperationContract] int GetNumberOfWheels(Vehicle vehicle); } 

VehicleService


 [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)] public class VehicleService : IVehicleService { public Vehicle GetVehicle(int type) { switch (type) { case 0: return new Car() { ID = 10, Brand = "Volvo", SteeringWheelPosition = "left" }; case 1: return new bike() { ID = 11, Brand = "Scott", HasFrontWheelBreak = true }; case 2: return new Kidsbike() { ID = 12, Brand = "Kid Scott", HasFrontWheelBreak = false, HasSupportingWheels = true }; default: return null; } } public int GetNumberOfWheels(Vehicle vehicle) { return vehicle.NoOfWheels; } } 

abstract class


 [KnownType(typeof(Car))] [KnownType(typeof(bike))] [DataContract] public abstract class Vehicle { [DataMember] public int ID { get; set; } abstract public int NoOfWheels { get; } [DataMember] public string Brand { get; set; } } 

specific classes


 [DataContract] public class Car : Vehicle { override public int NoOfWheels { get { return 4; } } [DataMember] public string SteeringWheelPosition { get; set; } } [KnownType(typeof(Kidsbike))] [DataContract] public class bike : Vehicle { override public int NoOfWheels { get { return 2; } } [DataMember] public bool HasFrontWheelBreak { get; set; } } [DataContract] public class Kidsbike : bike { [DataMember] public bool HasSupportingWheels { get; set; } } 

WCF Client


 namespace WCFClient { [ServiceContract] public interface IVehicleService { [OperationContract] Vehicle GetVehicle(int type); [OperationContract] int GetNumberOfWheels(Vehicle vehicle); } } namespace WCFClient { [KnownType(typeof(Car))] [KnownType(typeof(bike))] [DataContract] public abstract class Vehicle { [DataMember] public int ID { get; set; } abstract public int NoOfWheels { get; } [DataMember] public string Brand { get; set; } } [DataContract] public class Car : Vehicle { override public int NoOfWheels { get { return 0; } } [DataMember] public string SteeringWheelPosition { get; set; } } [KnownType(typeof(Kidsbike))] [DataContract] public class bike : Vehicle { override public int NoOfWheels { get { return 0; } } [DataMember] public bool HasFrontWheelBreak { get; set; } } [DataContract] public class Kidsbike : bike { [DataMember] public bool HasSupportingWheels { get; set; } } } private void btnGetVehicle_Click(object sender, EventArgs e) { Car carObj = (Car)fclient.GetVehicle(0); } 

just creating a proxy server on the client side. I can successfully call the service, but in response they got a problem. I am trying to use the Knowntype attribute. What is wrong with that.

+6
source share
2 answers

The following code works without errors.

 using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; namespace WcfService1 { [ServiceKnownType(typeof(Car))] [ServiceKnownType(typeof(bike))] [ServiceKnownType(typeof(Kidsbike))] [ServiceContract] public interface IVehicleService { [OperationContract] Vehicle GetVehicle(int type); [OperationContract] int GetNumberOfWheels(Vehicle vehicle); } [DataContract] public abstract class Vehicle { [DataMember] public int ID { get; set; } abstract public int NoOfWheels { get; } [DataMember] public string Brand { get; set; } } [DataContract] public class Car : Vehicle { override public int NoOfWheels { get { return 0; } } [DataMember] public string SteeringWheelPosition { get; set; } } [KnownType(typeof(Kidsbike))] [DataContract] public class bike : Vehicle { override public int NoOfWheels { get { return 0; } } [DataMember] public bool HasFrontWheelBreak { get; set; } } [DataContract] public class Kidsbike : bike { [DataMember] public bool HasSupportingWheels { get; set; } } [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)] public class VehicleService : IVehicleService { public Vehicle GetVehicle(int type) { switch (type) { case 0: return new Car() { ID = 10, Brand = "Volvo", SteeringWheelPosition = "left" }; case 1: return new bike() { ID = 11, Brand = "Scott", HasFrontWheelBreak = true }; case 2: return new Kidsbike() { ID = 12, Brand = "Kid Scott", HasFrontWheelBreak = false, HasSupportingWheels = true }; default: return null; } } public int GetNumberOfWheels(Vehicle vehicle) { return vehicle.NoOfWheels; } } } 

Svc file:

 <%@ ServiceHost Language="C#" Debug="true" Service="WcfService1.VehicleService" CodeBehind="Service1.svc.cs" %> 

Testing Service:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using WcfService1; namespace Test { class Program { static void Main(string[] args) { BasicHttpBinding hproxy = new BasicHttpBinding(); hproxy.MaxReceivedMessageSize = 2147483647; hproxy.MaxBufferSize = 2147483647; hproxy.MaxBufferPoolSize = 2147483647; EndpointAddress eaddrr = new EndpointAddress("http://localhost:62807/Service1.svc"); ChannelFactory<IVehicleService> CFactoryobj1 = new ChannelFactory<IVehicleService>(hproxy, eaddrr); IVehicleService isclientobj1 = CFactoryobj1.CreateChannel(); Car ve = (Car)isclientobj1.GetVehicle(0); } } } 
+7
source

KnownType should be used on the interface of the service contract, and not in the vehicle class, since it returns a Vehicle object for one of its operations. Adding KnownType to the Vehicle class does nothing that I think. because by default now you do not need to add a DataContract to your class so that they can be used in WCF. so you should have something like below.

 [ServiceKnownType(typeof(Car))] [ServiceKnownType(typeof(bike))] [ServiceKnownType(typeof(Kidsbike))] [ServiceContract] public interface IVehicleService { [OperationContract] Vehicle GetVehicle(int type); [OperationContract] int GetNumberOfWheels(Vehicle vehicle); } 
+6
source

Source: https://habr.com/ru/post/895668/


All Articles