WCF服务使用匿名对象返回JSON

时间:2011-11-30 20:36:37

标签: c# wcf json dynamic return-type

对于我正在构建的简单API,我使用了几种技术。首先,这不是我创建的第一个API,但它是我第一次将WCF,json和匿名对象组合在一起。

我为WCF API提供了以下界面:

[ServiceContract]
public interface IAPI
{
    [OperationContract]
    [WebInvoke(Method = "POST",
                 BodyStyle = WebMessageBodyStyle.WrappedRequest,
                 ResponseFormat = WebMessageFormat.Json,
                 RequestFormat = WebMessageFormat.Json)]
    ServiceResponse Authenticate(string username, string hashedPassword);

    [OperationContract]
    [WebInvoke(Method = "POST",
                 BodyStyle = WebMessageBodyStyle.WrappedRequest,
                 ResponseFormat = WebMessageFormat.Json,
                 RequestFormat = WebMessageFormat.Json)]
    ServiceResponse GetProducts();
}

这一切都非常简单,只有两种方法我想要工作。您在那里看到的ServiceResponse课程也非常简单,但却引发了我认为的问题:

[DataContract]
public class ServiceResponse
{
    [DataMember]
    public ResponseCode Status { get; set; }

    [DataMember]
    public object Value { get; set; }
}

我创建了这个类,所以我总是可以发送一个Status(Simple int enum)和一个对象,例如一个字符串或一个对象列表。

我使用jQuery创建了一个小脚本来测试我的服务,Authenticate方法就像它应该的那样工作,但是这个方法返回一个ServiceResponse对象,Status只有0 }字段。此处Value字段为空。

GetProducts方法是一个棘手的方法,一个像这样的匿名对象数组:

public ServiceResponse GetProducts()
{
       DataClassesDataContext db = new DataClassesDataContext();
       var results = from p in db.Products
                     where p.UserID == 1
                     select new
                     {
                         ID = p.ID,
                         Name = p.DecryptedName
                     };

        return ServiceResponse.OK(results.ToArray());
}

我在这里使用的是匿名类型对象,因为我不想为我想在API中使用的所有类创建代理类。

当我尝试使用我的简单jQuery脚本编写此代码时,FireBug告诉我我的请求已被中止。我想这是因为错误500或其他什么。当我在我的GetProducts方法中放置一个断点时,它会在Firefox说它被中止并且脚本完全运行之前被点击7次。

这是我用来测试我的WCF服务的jQuery脚本:

$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: "/Handlers/API.svc/GetProducts",
    data: '{}',
    dataType: "json",
    success: function (response) {
        var test = inspect(response, 5);
        $("#output").html(test);
    },
    error: function (message) {
        $("#output").html(inspect(message, 5));
    }
});

你在那里看到的inspect方法只是一个小的JS脚本,向我展示了一个对象的内容。

我尝试了以下方法来推动它:

  • 使用Product类型的对象替换匿名对象,但这种方法失败的方式相同
  • 返回List<T>而不是数组,但也没有运气。
  • 在没有分配给Value属性的情况下返回,这有效
  • 将属性Value更改为dynamic类型,此操作也失败

如果我可以使用WCF返回某种匿名对象数组,我会很喜欢它,因为这可以节省我创建30多个代理类。

注意Product类是LINQ生成的类。我正在使用C#4.0。

2 个答案:

答案 0 :(得分:2)

我可能错了,但我相信WCF相当严格,不允许你按照你想要的方式返回对象。如果您知道每次更改定义以反映该数据时数据将成为一个数组(但听起来这在您的情况下不起作用)。否则,您可能需要考虑将签名更改为简单字符串,并在返回之前将数据序列化为JSON。

答案 1 :(得分:0)

简短回答:你不能。您必须使用Web服务,或者 - 如您所说 - 使用代理类。