3

最近我用 EF4 建立了 WCF 宁静服务。当返回 XML 格式响应时,一切都解决了。但是,当涉及到 JSON 时,我得到了 504 错误。无法返回 json 数据,WCF Resful Service .NET 4.0

通过使用服务跟踪查看器深入挖掘:我发现了这个错误:

''xxx.DataEntity.AppView' 类型无法序列化为 JSON,因为其 IsReference 设置为 'True'。JSON 格式不支持引用,因为没有用于表示引用的标准化格式。要启用序列化,请禁用类型或该类型的适当父类的 IsReference 设置。

“AppView”是由 EF4 从存储过程生成的复杂对象类。我花了很多时间谷歌如何禁用 IsReference,到目前为止结果很少。

任何人?有什么解决办法吗?

提前致谢

代码:

[OperationContract]
        [WebInvoke(Method = "GET",
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "App/{id}/{format}")]
        AppView FuncDetail(string id, string format);



public AppView FuncDetail(string id, string format)
        {
            SetResponseFormat(format);
            return AppSvcs.GetById(id);
        }


private void SetResponseFormat(string format)
            {
                if (format.ToLower() == "json")
                {
                    ResponseContext.Format = WebMessageFormat.Json;
                }
                else
                {
                    ResponseContext.Format = WebMessageFormat.Xml;
                }
            }
4

4 回答 4

1

由于使用自动生成的 ADO 实体模型,我遇到了同样的问题。我还没有找到直接解决这个问题的方法,但作为一种解决方法,我将响应显式地序列化为 json。

因此,在您的示例中,AppView FuncDetail 如下所示:

public object FuncDetail(string id, string format)
    {
        SetResponseFormat(format);

        // where AppSvc is the object type and the enumerable list of this type is returned by the GetById method, cast it to a json string
        return JSONSerializer.ToJson<AppSvc>(AppSvcs.GetById(id));
    }

这是我正在使用的序列化程序:

public static class GenericSerializer 
{
public static DataTable ToDataTable<T>(IEnumerable<T> varlist)
{
    DataTable dtReturn = new DataTable();

    // column names 
    PropertyInfo[] oProps = null;

    if (varlist == null) return dtReturn;

    foreach (T rec in varlist)
    {
        // Use reflection to get property names, to create table, Only first time, others will follow 
        if (oProps == null)
        {
            oProps = ((Type)rec.GetType()).GetProperties();
            foreach (PropertyInfo pi in oProps)
            {
                Type colType = pi.PropertyType;

                if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()
                == typeof(Nullable<>)))
                {
                    colType = colType.GetGenericArguments()[0];
                }

                dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
            }
        }

        DataRow dr = dtReturn.NewRow();

        foreach (PropertyInfo pi in oProps)
        {
            dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue
            (rec, null);
        }

        dtReturn.Rows.Add(dr);
    }
    return dtReturn;
}

}

public static class JSONSerializer 
{
public static string ToJson<T>(IEnumerable<T> varlist)
{
    DataTable dtReturn = GenericSerializer.ToDataTable(varlist);
    return GetJSONString(dtReturn);
}

    static object RowsToDictionary(this DataTable table)
{

    var columns = table.Columns.Cast<DataColumn>().ToArray();

    return table.Rows.Cast<DataRow>().Select(r => columns.ToDictionary(c => c.ColumnName, c => r[c]));

}

static Dictionary<string, object> ToDictionary(this DataTable table)
{

    return new Dictionary<string, object>
    {
        { table.TableName, table.RowsToDictionary() }
    };

}

static Dictionary<string, object> ToDictionary(this DataSet data)
{

    return data.Tables.Cast<DataTable>().ToDictionary(t => "Table", t => t.RowsToDictionary());

}

public static string GetJSONString(DataTable table)
{

    JavaScriptSerializer serializer = new JavaScriptSerializer();

    return serializer.Serialize(table.ToDictionary());

}

public static string GetJSONString(DataSet data)
{

    JavaScriptSerializer serializer = new JavaScriptSerializer();

    return serializer.Serialize(data.ToDictionary());

}}
于 2011-01-19T21:14:11.053 回答
1

使用实体元数据而不是反射要清楚得多。元数据非常广泛。

于 2011-04-26T19:44:16.583 回答
1

我遇到了完全相同的问题。它只发生在我试图返回 JSON 序列化实体对象的一种服务方法上。对于我的所有其他方法,我返回的是 JSON 序列化数据传输对象 (DTO),它们是独立的,未连接到实体框架。我正在使用 DTO 将数据发布到方法中。通常,您发送的数据不需要您存储在模型或数据库中的所有数据,例如 ID 值、更新日期等。映射在模型类中完成,如下所示:

public partial class Location
{

    public static LocationDto CreateLocationDto(Location location)
    {
        LocationDto dto = new LocationDto
        {
            Accuracy = location.Accuracy,
            Altitude = location.Altitude,
            Bearing = location.Bearing                
        };
        return dto;
    }

它可能看起来有点笨拙,但它可以工作,并确保您只发送您打算发回的数据字段。它对我有用,因为我只有 5 或 6 个实体,但我可以看到,如果你有很多类,它会变得有点乏味。

于 2012-01-28T21:40:56.727 回答
0

另一种方法是使用 LINQ 创建一个匿名类型,其中包含您从实体中需要的字段子集,然后使用 JSON.NET 序列化您在 LINQ 语句中创建的匿名类型的集合。然后通过序列化将该集合作为字符串保存。

于 2013-01-03T20:50:35.227 回答