3

最近、EF4 を使用して WCF レストフル サービスをセットアップしました。XML形式の応答を返すと、すべてうまくいきました。ただし、JSON に関しては、504 エラーが発生しました。json データを返せない、WCF Resful Service .NET 4.0

Service Trace Viewer を使用してさらに掘り下げると、次のエラーが見つかりました。

'タイプ 'xxx.DataEntity.AppView' は、IsReference 設定が 'True' であるため、JSON にシリアル化できません。参照を表す標準化された形式がないため、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

私はまったく同じ問題に遭遇しました。これは、JSON シリアル化された Entity オブジェクトを返そうとしたサービス メソッドの 1 つでのみ発生しました。他のすべてのメソッドでは、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 つしかないのでうまくいきますが、たくさんのクラスがあると少し面倒になることがわかります。

于 2012-01-28T21:40:56.727 に答える
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 に答える
0

これを行うもう 1 つの方法は、LINQ を使用して、エンティティから必要なフィールドのサブセットを持つ匿名型を作成し、JSON.NET を使用して、LINQ ステートメントで作成した匿名型のコレクションをシリアル化することです。次に、シリアル化してそのコレクションを文字列として永続化します。

于 2013-01-03T20:50:35.227 に答える