6

Interface から継承したクラスがあり、Web API get methed からインターフェイスを返しています。問題は、継承されたクラスの値を json 文字列として取得していることです。

これがインターフェースです

 public interface IFoo
    { 
    string A { get ;set ; } 
    string B { get ; set ; } 
    } 

継承クラス

 public class Child : iFoo
    { 
    string A { get ; set ; } 
    string B { get ; set ; } 
    string C { get ; set ; } 
    string D { get ; set ; } 
    } 

次に、コントローラーの GetMethod から IFoo を返します

 public IFoo GetIFoo()
        {
        return  ChildInstance ; 
        }

現在の結果は、継承されたクラスとインターフェイスの両方のすべての値を提供しますが、json結果のインターフェイスに実装されている値のみが必要です。

4

4 に答える 4

6

Json シリアライザーに到達するまでは、メソッドの戻り値の型は気にしません。それが知っているのは、「私はこのオブジェクトを持っています。それで何ができるか見てみましょう」ということだけです。

インターフェイスが持つプロパティのみをシリアライザーに含めたい場合は、インターフェイスが持つプロパティのみを持つオブジェクトを与えることをお勧めします。たとえば Automapper を使用してChildInstance、この新しいオブジェクトに値をコピーすることを検討してください。

別の方法はより複雑です。独自のシリアライザーを実装して、Json シリアライザーが関与する機会がないようにします。

于 2013-10-29T08:23:34.600 に答える
0

コントローラー メソッドの戻り値の型がインターフェイスの場合は、アクション フィルターを適用して、インターフェイス プロパティのみをシリアル化することもできます。このようにして、インターフェイスを実装するクラスの属性を変更しなくても、常にインターフェイス定義との同期を保つことができます。

このためには、最初にここでInterfaceContractResolver説明されているように、カスタム コントラクト リゾルバーを作成する必要があります。

    public class InterfaceContractResolver : DefaultContractResolver
    {
        private readonly Type _interfaceType;
        public InterfaceContractResolver(Type interfaceType)
        {
            _interfaceType = interfaceType;
        }

        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            IList<JsonProperty> properties = base.CreateProperties(_interfaceType, memberSerialization);
            return properties;
        }
    }

次に、コントローラー メソッドの戻り値の型を調べ、それがインターフェイスの場合は上で定義したコントラクト リゾルバーを使用するアクション フィルターを (ここで説明されているように属性として、またはこれをデフォルトの動作として使用する場合はグローバルに)追加します。

    public class InterfaceFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
            if (content != null)
            {
                Type returnType = actionExecutedContext.ActionContext.ActionDescriptor.ReturnType;
                if (returnType.IsInterface && content.Formatter is JsonMediaTypeFormatter)
                {
                    var formatter = new JsonMediaTypeFormatter
                        {
                            SerializerSettings =
                                {
                                    ContractResolver = new InterfaceContractResolver(returnType)
                                }
                        };
                    actionExecutedContext.Response.Content = new ObjectContent(content.ObjectType, content.Value, formatter);
                }
            }
        }
    }
于 2016-03-11T20:52:58.050 に答える
0

動的に返すことを気にしない場合は、次のようにします。

反対に、これは json シリアライザーを使用する場合にのみそのままで機能するため、機能させるには「accept: application/json」を指定する必要があります。

public class Person
{
    public string Name { get; set; }
}

public class User : Person
{
    public string Title { get; set; }
    public string Email { get; set; }
}

public dynamic Get()
{
    var user = new User { Title = "Developer", Email = "foo@bar.baz", Name = "MyName" };

    return new { user.Name, user.Email };
}
于 2013-11-01T15:23:25.500 に答える