1

これはフレームワークのベータリリースのバグである可能性があります。または、クラスでひどく間違ったことをしています。

サービスのアクションへのPOSTを介して受信しようとしている基本モデルがあります。モデルには、XML要素としてのいくつかのプロパティとXML属性としてのいくつかのプロパティが含まれています。要素はモデルに正常にバインドされますが、属性は無視されます。

モデルの基本的な形式は次のとおりです。

[XmlRoot]
public class Entry
{
    [XmlAttribute]
    public string Label { get; set; }

    [XmlElement]
    public Link Parent { get; set; }

    [XmlElement]
    public string Data { get; set; }
}

public class Link
{
    [XmlElement]
    public string Href { get; set; }
}

これにより、次のXML応答に正常にシリアル化されます。

<Entry Label="Test">
  <Parent Href="http://service/entries/123" />
  <Data>WibblyWobblyTimeyWimey</Data>
</Entry>

同じXMLを使用してリクエストをサービスに送り返すと、Data要素のみが正常に永続化されていることがわかります。

を調べるHttpActionContextと、RequestKeyValueModelプロパティにはキー「Data」と「Parent」のみが含まれており、「Data」のみに値があることがわかります。

System.Net.Http.HttpClientエントリの逆シリアル化を手動でテストしましたが、リクエストをオブジェクトとして読み取る(そしてプロセスで実行する)ための簡単なテストクライアントを使用して、応答を正常に逆シリアル化できますMediaTypeFormatter

私が見逃したトリック、見落としたような設定はありますか?問題は、逆シリアル化されたXMLリクエストの値をアクションの引数にバインドしようとすることにあると確信していますが、IActionBinderその理由についてはこれ以上の情報がありません。

4

1 に答える 1

0

これは、フレームワークのベータ リリースで実装された現在のモデル バインディングの問題であることを知りました (その後改善されました)。

この記事では、回避策としてモデル バインディングを無効にして、より単純な「シリアル化」モデルを使用することを提案しました

残念ながら、副作用として、これによりすべてのルート パラメーター バインディングも削除されたため、URL からパラメーターを取得できなくなり、欠落している値がなければアクションは実行されませんでした。

ただし、次の属性を導入することで、この問題を回避することができました。

public class AddRouteParametersAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var descriptor = actionContext.ActionDescriptor
            as ReflectedHttpActionDescriptor;
        var parameters = descriptor.MethodInfo.GetParameters();

        foreach (var key in actionContext.ActionArguments.Keys.ToList())
        {
            if (actionContext.ActionArguments[key] == null)
            {
                var parameter = parameters
                    .SingleOrDefault(param => param.Name == key);

                var valueProvider = new RouteDataValueProvider(
                    actionContext,
                    CultureInfo.InvariantCulture);

                var result = valueProvider.GetValue(key);

                if (result != null && parameter != null)
                {
                    actionContext.ActionArguments[key]
                        = result.ConvertTo(parameter.ParameterType);
                }
            }
        }

        base.OnActionExecuting(actionContext);
    }
}

これは少し厄介ですが (すべての最善の回避策がそうあるべきであるため)、RouteDataValueProvider通常の逆シリアル化プロセスによってパラメーターが設定されない場合は常に、既存のクラスを使用してルート情報を正しいタイプとして読み取ります。うまくいかない場合もあると思いますが、これまでのところ、埋める必要のあるギャップを埋めており、フレームワークに深く入り込むことなく問題を解決してくれます。

同様の問題が発生した場合は、RC までこのコードを参照していただければ幸いです。RC の時点で、これらの問題はなくなることが保証されます。

于 2012-05-17T20:34:02.407 に答える