1

这可能是该框架的 beta 版本中的一个错误,或者我对我的类做了一些非常错误的事情。

我有一个基本模型,我试图通过 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在此过程中进行练习)。

是否有一些我错过的技巧,一些我忽略的设置?我确信问题在于IActionBinder尝试将反序列化的 XML 请求中的值绑定到操作的参数,但我没有更多关于原因的信息。

4

1 回答 1

0

我了解到这是由框架的 Beta 版本实现的当前模型绑定的问题(并随后进行了改进)。

本文建议解决方法是禁用模型绑定以支持更简单的“序列化”模型,这听起来更接近我真正想要的。

不幸的是,作为副作用,这也丢弃了所有路由参数绑定,因此我不再从 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 之前参考此代码,此时我们确信这些问题会消失。

于 2012-05-17T20:34:02.407 回答