2011-08-23 18 views
6

私のwcfクライアントに次のエラーがあります。wcfのknowntype属性の問題

NetDispatcherFaultExceptionが処理されませんでした。

メッセージをデシリアライズしようとしているときにフォーマッタが例外をスローしました。パラメータhttp://tempuri.org/:GetVehicleResultを逆シリアル化しようとしてエラーが発生しました。 InnerExceptionメッセージは、ライン1の位置266でエラーです。エレメント 'http://tempuri.org/:GetVehicleResult'には、名前「http://schemas.datacontract.org/2004/07/WCFServer:Car」にマップされているタイプのデータが含まれています。デシリアライザには、この名前にマップされている型の知識はありません。 DataContractResolverを使用するか、「Car」に対応する型を既知の型のリストに追加することを検討してください。たとえば、KnownTypeAttribute属性を使用するか、DataContractSerializerに渡される既知の型のリストに追加します。詳細については、InnerExceptionを参照してください。

誰がどこで障害を助けることができますか?

WCFサーバー


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

抽象クラス


[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 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クライアント


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

。私はサービスを正常に呼び出すことができますが、問題が発生しています。私はKnowntype属性で試してみます。これで何が間違っている。

答えて

7

次のコードはエラーなく正常に動作します。

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ファイル:

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

試験サービス:

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-私はsvcutilの代わりに自己ホスト。しかし、私は同じエラーを取得しています。 –

+0

私は抽象クラスの車、クライアントとサーバー側の両方で自転車を持っているが、実際の実装はサーバー側で、クライアント側はダミーです。 –

6

KnownTypeは、その操作の1つのためにVehicleオブジェクトを返すものであるため、Vehicleクラスではなくサービスコントラクトインターフェイス自体で使用する必要があります。 VehicleクラスにKnownTypeを追加すると、私は何も考えません。これは、デフォルトでは、WCFで使用できるようにDataContractをクラスに追加する必要がないためです。あなたは以下のようなものを持っているはずです。

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

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

また、私はそれを試してきました。しかし、まだ同じエラーが発生しています。 –

+0

誰でもwcfクライアント(コードレベルのクライアントプロキシ、クライアント側のスタブ)を使ってwcf seviceを呼び出して応答を取得するknowntype属性を使っていくつかの例を提案できます。 –

+0

あなたはサービスにどんなタイプが期待されているかを伝えているので、これはうまくいったはずです。サーバー側とクライアント側のサービス契約インタフェースの両方にServiceKnownType属性を設定する必要があることに注意してください。また、Vehicleクラスのknowntype属性は必要なく、Vehicle Typeを使用するプロパティを持つクラスでのみ必要です。戻り値の型はVehicle Typeです。 ServiceKnownTypeに関するこのリンクを参照してください。http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceknowntypeattribute.aspx – rpgmaker