2011-08-23 19 views
6

Ho riscontrato il seguente errore nel mio client wcf.Problema con attributo knowntype in wcf

NetDispatcherFaultException non gestito.

Il formatter ha generato un'eccezione durante il tentativo di deserializzare il messaggio: Si è verificato un errore durante il tentativo di deserializzare il parametro http://tempuri.org/:GetVehicleResult. Il messaggio InnerException era 'Errore nella posizione della linea 1 266. L'elemento' http://tempuri.org/:GetVehicleResult 'contiene i dati di un tipo associato al nome' http://schemas.datacontract.org/2004/07/WCFServer:Car '. Il deserializzatore non ha alcuna conoscenza di alcun tipo che mappa questo nome. Prendi in considerazione l'utilizzo di DataContractResolver o aggiungi il tipo corrispondente a "Car" all'elenco dei tipi noti, ad esempio utilizzando l'attributo KnownTypeAttribute o aggiungendolo all'elenco dei tipi noti passati a DataContractSerializer. '. Si prega di consultare InnerException per maggiori dettagli.

Qualcuno può aiutarmi dov'è l'errore.

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; 
    } 
} 

classe astratta


[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; } 
} 

classi concrete


[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);   
} 

solo la creazione di proxy lato client. Posso in grado di chiamare il servizio con successo, ma in risposta sto avendo il problema. Provo con l'attributo Knowntype. Cosa c'è di sbagliato in questo.

risposta

7

Il seguente codice funziona correttamente senza errori.

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; 
    } 
} 

} 

file di Svc: servizio

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

Testing:

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); 
     } 
    } 
} 
+0

@ rgpmaker- Im selfhosting invece di svcutil. Ma sto ottenendo lo stesso errore. –

+0

Sto avendo l'auto di classe astratta, bici sia lato client che lato server ma l'effettiva implementazione in Server side, fittizio lato client. –

6

Il codice KnownType deve essere utilizzato sull'interfaccia del contratto di servizio stesso, non sulla classe del veicolo poiché è quella che restituisce l'oggetto veicolo per una delle sue operazioni. L'aggiunta di KnownType alla classe Vehicle non fa nulla. perché per impostazione predefinita ora non è necessario aggiungere DataContract alla classe affinché siano utilizzabili in WCF. quindi dovresti avere qualcosa come sotto.

[ServiceKnownType(typeof(Car))] 
[ServiceKnownType(typeof(bike))] 
[ServiceKnownType(typeof(Kidsbike))] 
[ServiceContract] 
public interface IVehicleService 
{ 
    [OperationContract] 
    Vehicle GetVehicle(int type); 

    [OperationContract] 
    int GetNumberOfWheels(Vehicle vehicle); 
} 
+0

ho provato anche questo. Ma continuando a ottenere lo stesso errore. –

+0

Qualcuno può suggerire qualche esempio usando l'attributo knowntype usando il client wcf (proxy client a livello di codice, stub lato client) per chiamare wcf sevice e ottenere la risposta. –

+0

Che avrebbe dovuto funzionare, dal momento che stai dicendo al servizio che tipo sarebbe previsto. Ricordare che è necessario avere l'attributo ServiceKnownType sia sul lato server che sull'interfaccia del contratto di servizio lato client. Ricorda inoltre che non hai bisogno dell'attributo knowntype sulla classe Vehicle, ne hai solo bisogno in una classe che ha una proprietà che usa il tipo di veicolo ha il suo tipo di ritorno. fare riferimento a questo collegamento su ServiceKnownType, http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceknowntypeattribute.aspx – rpgmaker

Problemi correlati