Проблема с сериализацией типа данных объекта в wcf с использованием атрибута DataContract - PullRequest
1 голос
/ 21 марта 2011

Я создал службу API отдыха WCF, используя предварительный просмотр 2 стартового комплекта wcf rest, который автоматически возвращает данные JSON или XML в зависимости от запрошенного типа контента. все работает нормально, но так как мои сервисные методы возвращают множественный тип данных, некоторые методы возвращают объект класса или коллекции класса, типа bool, int или collection. поэтому я планировал вернуть один и тот же Response во всех методах для этого. Создайте новый класс следующим образом:

 [DataContract(Namespace = "")]
public class ServiceResponse
{
    [DataMember]
    public bool IsError
    { get; set; }

    [DataMember]
    public string ResponseMessage
    { get; set; }

    [DataMember]
    public Object ResponseData
    { get; set; }       

}

и класс пользователя следующим образом:

[DataContract(Namespace = "")]
public class User
{
    [DataMember]
    public string UserName 
    { get; set; }

    [DataMember]
    public int UserID
    { get; set; }      

}

В классе ServiceResponse я объявил свойство типа объекта ResponseData, и мой метод all имеет тип возврата ServiceResponse. Моя проблема в том, что когда я задаю любую строку, тип bool, int как ResponseData, она сериализуется, но когда я устанавливаю тип коллекции или объект другого класса, который также имеет атрибут DataContarct, этот класс не сериализуется, см. Код ниже:

public ServiceResponse GetUser(int userID)
    {

        User user = getUser(userID); get user data from database

        ServiceResponse response=new ServiceResponse();
        var response = new ServiceResponse
                           {
                               IsError = false,
                               ResponseMessage = string.Empty,
                               ResponseData = user; // Setting Result Data here
                           };
        return response;

    }

когда я вызывал вышеуказанный метод (GetUser), я получил нулевой ответ из-за проблемы с сериализацией, но следующий код работает нормально

public ServiceResponse TestMethod(string testMessage)
    {


        ServiceResponse response=new ServiceResponse();
        var response = new ServiceResponse
                           {
                               IsError = false,
                               ResponseMessage = string.Empty,
                               ResponseData = testMessage; // Setting Result Data here
                           };
        return response;

    }

Кто-нибудь может мне помочь?

1 Ответ

2 голосов
/ 21 марта 2011

Проблема, с которой вы столкнулись, связана с тем, что в вашем DataContract вы объявляете ResponseData как Object, но не сообщаете WCF, какие типы являются допустимыми известными типами. Вам необходимо явно указать WCF, какие известные типы допустимы для вашей службы, и вы можете сделать это, используя атрибут ServiceKnownType. Я взял ваш код и сделал несколько модификаций, чтобы продемонстрировать это:

DataContracts

[DataContract(Name="ServiceResponse")]
public class ServiceResponse
{
    [DataMember(Name="IsError", Order=1)]
    public bool IsError
    { get; set; }

    [DataMember(Name="ResponseMessage", Order=2)]
    public string ResponseMessage
    { get; set; }

    [DataMember(Name="ResponseData", Order=3)]
    public Object ResponseData
    { get; set; }

}

[DataContract(Name="User")]
public class User
{
    [DataMember(Name="UserName", Order=1, IsRequired=true)]
    public string UserName
    { get; set; }

    [DataMember(Name="UserID", Order=2, IsRequired=true)]
    public int UserID
    { get; set; }

}

[DataContract(Name = "User2")]
public class User2
{
    [DataMember(Name = "UserName", Order = 1, IsRequired = true)]
    public string UserName
    { get; set; }

    [DataMember(Name = "UserID", Order = 2, IsRequired = true)]
    public int UserID
    { get; set; }

}

ServiceCode

[ServiceContract(Namespace = "WebApplication1")]
[ServiceKnownType(typeof(User))]
[ServiceKnownType(typeof(User2))]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
    [OperationContract(Name="GetUser")]
    [WebGet(UriTemplate = "GetUser/{userID}", ResponseFormat = WebMessageFormat.Json)]
    public ServiceResponse GetUser(String userID)
    {
        User theUser = new User()
        {
            UserID=Convert.ToInt32(userID),
            UserName="bob"
        };

        ServiceResponse sr = new ServiceResponse()
        {
            IsError = false,
            ResponseMessage = "",
            ResponseData = theUser
        };

        return sr;
    }

    [OperationContract(Name = "GetUser2")]
    [WebGet(UriTemplate = "GetUser2/{userID}", ResponseFormat = WebMessageFormat.Json)]
    public ServiceResponse GetUser2(String userID)
    {
        User2 theUser = new User2()
        {
            UserID = Convert.ToInt32(userID),
            UserName = "bob"
        };

        ServiceResponse sr = new ServiceResponse()
        {
            IsError = false,
            ResponseMessage = "",
            ResponseData = theUser
        };

        return sr;
    }

}

Что я сделал:

  1. На самом деле не обязательно, но я добавил некоторые дополнительные атрибуты для DataContract и членов. В любом случае, мне обычно нравится это делать, поэтому я просто болею там. :)
  2. Я создал второй DataContract, чтобы продемонстрировать использование ServiceKnownType.
  3. В сервисе я добавил атрибуты ServiceKnownType в свой класс сервиса, указав, какие типы могут быть возвращены из моих методов сервиса.

Вот и все. Использование атрибутов ServiceKnownType довольно уродливо - есть некоторые решения, которые можно обойти ( здесь ).

Дайте мне знать, если у вас есть дополнительные вопросы. Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...