2

ASP.Net Web API は初めてです。Recurly REST ベースの API と対話しようとしていますが、ReadAsAsync 呼び出し中に以下のようなエラーが発生します。これは、応答をシリアル化しようとしていると思われるポイントです。

{"Error in line 1 position 73. Expecting element 'account' from namespace 'http://schemas.datacontract.org/2004/07/RecurlyWebApi.Recurly'.. Encountered 'Element'  with name 'account', namespace ''. "}

簡潔にするために簡略化した、私の HttpClient 実装を次に示します。

  public class RecurlyClient
  {
    readonly HttpClient client = new HttpClient();

    public RecurlyClient()
    {
      var config = (RecurlySection)ConfigurationManager.GetSection("recurly");

      client.BaseAddress = new Uri(string.Format("https://{0}.recurly.com/v2/", config.Subdomain));

      // Add the authentication header
      client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(config.ApiKey)));

      // Add an Accept header for XML format.
      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
    }

    public T Get<T>(string id)
    {
      var accounts = default(T);

      // Make the request and get the response from the service
      HttpResponseMessage response = client.GetAsync(string.Concat("accounts/", id)).Result;  // Blocking call!

      if (response.IsSuccessStatusCode)
      {
        // Parse the response body. Blocking!
        accounts = response.Content.ReadAsAsync<T>().Result;
      }

      return accounts;
    }
  }

そして、ここに私のモデルがあります:

  [XmlRoot("account")]
  public class Account
  {
    [XmlAttribute("href")]
    public string Href { get; set; }

    [XmlElement("account_code")]
    public string AccountCode { get; set; }

    [XmlElement("state")]
    public AccountState State { get; set; }

    [XmlElement("username")]
    public string Username { get; set; }

    [XmlElement("email")]
    public string Email { get; set; }

    [XmlElement("first_name")]
    public string FirstName { get; set; }

    [XmlElement("last_name")]
    public string LastName { get; set; }

    [XmlElement("company_name")]
    public string Company { get; set; }

    [XmlElement("accept_language")]
    public string LanguageCode { get; set; }

    [XmlElement("hosted_login_token")]
    public string HostedLoginToken { get; set; }

    [XmlElement("created_at")]
    public DateTime CreatedDate { get; set; }

    [XmlElement("address")]
    public Address Address { get; set; }
  }

サービスからの XML 応答の例:

<account href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01">
  <adjustments href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01/adjustments"/>
  <invoices href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01/invoices"/>
  <subscriptions href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01/subscriptions"/>
  <transactions href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01/transactions"/>
  <account_code>SDTEST01</account_code>
  <state>active</state>
  <username>myusername</username>
  <email>simon@example.co.uk</email>
  <first_name>First name</first_name>
  <last_name>Last name</last_name>
  <company_name>My Company Name</company_name>
  <vat_number nil="nil"></vat_number>
  <address>
    <address1>My Address Line 1/address1>
    <address2>My Address Line 2</address2>
    <city>My City</city>
    <state>My State</state>
    <zip>PL7 1AB</zip>
    <country>GB</country>
    <phone>0123456789</phone>
  </address>
  <accept_language nil="nil"></accept_language>
  <hosted_login_token>***</hosted_login_token>
  <created_at type="datetime">2013-08-22T15:58:17Z</created_at>
</account>
4

1 に答える 1

3

問題は、デフォルトで DataContractSerializer が XML のデシリアライズに使用されており、デフォルトで DataContractSerializer が名前空間http://schemas.datacontract.org/2004/07/Clr.Namespaceの名前空間を使用しているためだと思います。(この場合、Clr.Namepace は RecurlyWebApi.Recurly です。)

XML には属性があるため、DataContractSerializer の代わりに XmlSerializer を使用する必要があります。アカウント クラスは Xml* 属性で装飾されているため、これを行うように設定されています。ただし、XmlSerializer を使用している XmlMediaTypeFormatter を使用する必要があります。このページで説明されているように、グローバル XMLFormatter にフラグを設定することでこれを行うことができます。

var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;

または、ReadAsAsync 呼び出しのパラメーターとして MediaTypeFormatter を指定します。

var xmlFormatter = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xmlFormatter.UseXmlSerializer = true;
accounts = response.ReadAsAsync<T>(xmlFormatter).Result

これは、エラー メッセージの最初の「アカウント」が小文字である理由を説明していないため、100% 確実ではありません。DataContractSerializer は XmlRoot 属性を無視する必要があります。

于 2013-08-22T21:15:08.617 に答える