7

编辑:当我问这个问题时,我想尝试一些东西。我已经在请求上设置了 XmlNamespace 属性,这就是诀窍。

request.XmlNamespace = "http://musicbrainz.org/ns/mmd-2.0#";

但是我真的不明白为什么...

下一个问题是让 RestSharp 将 xml 属性识别为对象属性


周末的大部分时间我都在处理这个问题,但我只是没有让它工作。

我正在尝试围绕 RestFul 网络服务(MusicBrainz)编写一个包装器。我正在使用一个简单的示例进行测试:获取一位艺术家的详细信息并将其放入自定义艺术家对象中。

当我在 RestClient 上执行 Execute 时,它​​结束正常,但我的对象属性为空。但是当我使用 XmlDeserializer 测试反序列化时,对象属性被填充(但不适用于与属性对应的属性,但我稍后会解决这个问题)

在响应的反序列化和将对象放入 response.data 之间会发生什么?很可能这是我正在犯的“新手”错误,因为这是我使用 RestSharp 的第一步。

帮助将不胜感激..

返回的 xml:

<metadata>
   <artist type="Group" id="f1548c5b-329e-4036-921c-02213a04b525">
       <name>Uriah Heep</name>
           <sort-name>Uriah Heep</sort-name>
           <country>GB</country>
           <life-span>
               <begin>1970</begin>
           </life-span>
    </artist>
</metadata>

我的课 :

public class Artist
{
    public int Id { get; set; }
    public string Type { get; set; }
    public string Name { get; set; }
    public string SortName { get; set; }
    public string Country { get; set; }

}

在下面的代码中,输出属性被填充

var output = xml.Deserialize<Artist>(response);

但是调用时相同的响应不会填充属性

var response = client.Execute<T>(request);

完整代码(为简单起见,我将测试代码放在通用方法中):

public T Execute<T>(RestRequest request) where T : new()
{
    var client = new RestClient();
    client.BaseUrl = BaseUrl;
    client.Authenticator = null;

    //does not fill properties 
    var response = client.Execute<T>(request);

    if (response.ErrorException != null)
    {
        throw response.ErrorException;
    }
    var xml = new XmlDeserializer();

    //fills properties
    var output = xml.Deserialize<Artist>(response);

    return response.Data;
}
4

1 回答 1

0

发生这种情况是因为Execute方法在收到响应后,会尝试根据请求的 RootElement 和 XmlNamespace 属性对其进行协商,并将它们复制XmlDeserializer.

这是来自 RestClient的代码:

     handler.RootElement = request.RootElement;
     handler.DateFormat = request.DateFormat;
     handler.Namespace = request.XmlNamespace;
     response.Data = handler.Deserialize<T>(raw);

如果您传递带有不匹配的 XmlNamespace 的 RestRequest,RestSharp XmlDeserializer(在幕后使用 XDocument)将无法将响应 XML 映射到对象属性,而您将获得默认/空值。

现在对于默认实现(当您XmlDeserializer手动创建时),如果您不设置 XmlNamespace,反序列化器将执行自动检测,基本上忽略响应中的所有命名空间并仅通过其名称映射所有属性。

请参阅XmlDeserializer 的源代码:

     // autodetect xml namespace
     if (!Namespace.HasValue())
     {
         RemoveNamespace(doc);
     }

考虑到以上所有因素,很明显为什么在您使用此行将 XmlNamespace 属性显式设置为请求对象中的匹配命名空间后它开始工作:

     request.XmlNamespace = "http://musicbrainz.org/ns/mmd-2.0#";

Execute方法将命名空间复制到反序列化器中,并将 XML 适当地映射到对象。

于 2014-12-14T01:07:03.143 回答