首页 文章

WCF通过使用Entity Framework Complex来返回JSON

提问于
浏览
3

最近我用EF4设置了WCF休息服务 . 返回XML格式响应时,一切都很顺利 . 但是当谈到JSON时,我得到了504错误 . unable to return json data, 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 回答

  • 1

    我遇到了完全相同的问题 . 它只发生在我试图返回JSON序列化实体对象的一个服务方法上 . 对于我所有的其他方法,我正在返回JSON序列化数据传输对象(DTO),这些对象是独立的,没有连接到Entity框架 . 我正在使用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个实体,但我可以看到,如果你有很多类,它会变得有点乏味 .

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

    以下是我正在使用的Serializers:

    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());
    
    }}
    
  • 1

    使用实体元数据而不是反射更清晰 . 元数据非常广泛 .

  • 0

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

相关问题