2011-08-23 4 views
6

wcf 클라이언트에서 다음 오류가 발생했습니다.wcf의 knowntype 속성 문제

NetDispatcherFaultException 처리되지 않았습니다.

메시지를 deserialize하려고 할 때 포맷터에서 예외가 발생했습니다. 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

Im은 클라이언트와 서버 측 모두에서 추상 클래스 자동차, 자전거를 사용하고 있지만 서버 측의 실제 구현은 클라이언트 측의 더미입니다. –

6

KnownType은 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을 사용하는 속성을 가진 클래스에서만 반환 유형이 필요합니다. ServiceKnownType, http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceknowntypeattribute.aspx의이 링크를 참조하십시오. – rpgmaker