【问题标题】:Reading POST Request XML - Boolean value always read as false读取 POST 请求 XML - 布尔值始终读取为 false
【发布时间】:2012-12-20 16:20:59
【问题描述】:

我正在开发托管在 IIS 中的 WCF RESTful Web 服务。我目前正在处理一个相当简单的发布请求,将以下 XML 发送到端点:

<StockListRequestData xmlns="http://myWebService.com/endpoint">
<UserID>2750</UserID>
<StockDatabase>stockLeekRoadVenue</StockDatabase>
<InStockOnly>true</InStockOnly>
</StockListRequestData>

此 XML 与我的 Web 服务上的 DataContract 匹配:

[DataContract(Namespace = "http://myWebService.com/endpoint")]
public class StockListRequestData
{
    [DataMember]
    public string UserID { get; set; }

    [DataMember]
    public string StockDatabase { get; set; }

    [DataMember]
    public bool InStockOnly { get; set; }
}

问题在于&lt;InStockOnly&gt;true&lt;/InStockOnly&gt; 元素,当我将其设置为truefalse 时,它将始终被解释为false...

这是处理请求的代码:

public StockListResponseData GetListOfProducts(StockListRequestData requestData)
    {
        var stockList = new StockList(requestData.InStockOnly, requestData.StockDatabase);
        StockListResponseData response;
        if (stockList.Any())
        {
            var stockArray = new Stock[stockList.Count];
            var i = 0;
            foreach (var s in stockList)
            {
                stockArray[i] = s;
                i++;
            }
            response = new StockListResponseData
                           {
                               StockList = stockArray,
                               WasSuccessful = true,
                           };
            return response;
        }
        response = new StockListResponseData
                       {
                           WasSuccessful = false
                       };
        return response;
    }

StockList 类:

[DataContract]
public class StockList : List<Stock>
{
    public StockList(bool inStockOnly, string stockDb)
    {
        if (inStockOnly)
        {
            // Get only products that are in stock
            var conn = AndyServerDatabase.ConnectToStockMovementByDb(stockDb);
            conn.Open();
            // Compile SQL query
            var q = new SqlCommand(null, conn) { CommandText = "SELECT StockID, Name, PerBox FROM Stock WHERE InStock = 1;" };

            // Execute query
            var rdr = q.ExecuteReader();

            // Check that the output isn't null
            if (rdr.HasRows)
            {
                while(rdr.Read())
                {
                    var id = Convert.ToInt32(rdr[0]);
                    var name = rdr[1].ToString();
                    var perBox = Convert.ToInt32(rdr[2]);
                    Add(new Stock(id, name, perBox));
                }
                conn.Close();
            }
            // Output is null
            conn.Close();
        }
        else
        {
            // Get all products
            // Get only products that are in stock
            var conn = AndyServerDatabase.ConnectToStockMovementByDb(stockDb);
            conn.Open();
            // Compile SQL query
            var q = new SqlCommand(null, conn) { CommandText = "SELECT StockID, Name, PerBox FROM Stock;" };
            q.Prepare();

            // Execute query
            var rdr = q.ExecuteReader();

            // Check that the output isn't null
            if (rdr.HasRows)
            {
                while (rdr.Read())
                {
                    var id = Convert.ToInt32(rdr[0]);
                    var name = rdr[1].ToString();
                    var perBox = Convert.ToInt32(rdr[2]);
                    Add(new Stock(id, name, perBox));
                }
                conn.Close();
            }
            // Output is null
            conn.Close();
        }
        // Add();
    }
}

生成的 XML:

<StockListResponseData xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <StockList xmlns:a="http://schemas.datacontract.org/2004/07/SMS">
        <a:Stock>
            <a:Id>1</a:Id>
            <a:Name>Smirnoff Vodka (70cl)</a:Name>
            <a:PerBox>6</a:PerBox>
            <a:Quantity>0</a:Quantity>
            <a:Remains>0</a:Remains>
        </a:Stock>
        <a:Stock>
            <a:Id>2</a:Id>
            <a:Name>Jagermeister (70cl)</a:Name>
            <a:PerBox>6</a:PerBox>
            <a:Quantity>0</a:Quantity>
            <a:Remains>0</a:Remains>
        </a:Stock>
    </StockList>
    <WasSuccessful>true</WasSuccessful>

我希望这足以继续下去,我已经被难住了很久,只是无法弄清楚为什么它会以这种方式运行..如果您需要我未包含的其他代码,请随时询问.

非常感谢,

安迪

编辑:

添加一些上下文以显示正在发生的事情:

例如,我知道:

    <a:Stock>
        <a:Id>2</a:Id>
        <a:Name>Jagermeister (70cl)</a:Name>
        <a:PerBox>6</a:PerBox>
        <a:Quantity>0</a:Quantity>
        <a:Remains>0</a:Remains>
    </a:Stock>

将其InStock 行设置为0,这意味着如果我传入true,则不应在生成的XML 中显示。

我已将 StockList 构造函数 if(inStockOnly) 更改为 if(!inStockOnly) - 然后我传入 &lt;InStockOnly&gt;true&lt;/InStockOnly&gt; - 当它到达 StockList 构造函数时,它会被反转并显示正确的数据 - 所以它必须将其读取为到此 if 声明时为 false。

如果我传入&lt;InStockOnly&gt;false&lt;/InStockOnly&gt;,它仍会显示“正确”的结果,因此在反转之前它会将其读取为假!

同样,如果我将其保留为if(inStockOnly) 并传入&lt;InStockOnly&gt;false&lt;/InStockOnly&gt;,它会显示false 的数据!

我还将requestData.InStockOnly 添加到 StockListResponseData DataContract 中,并在那里显示它以false 输出requestData.InStockOnly 的值。

【问题讨论】:

  • 您的代码看起来没问题,只是您没有填写 Quantity 和 Remains,因此它们始终为 0。您确定退回的商品实际上没有库存吗?顺便说一句,您用来填充 stockArray 的代码不是必需的。你应该只使用 Stock[] stockArray = stockList.ToArray();
  • 是的,我认为这可能会引起一些混乱,&lt;InStockOnly&gt;true&lt;/InStockOnly 元素的目的是检查股票表中的InStock 行 - 这是bit 类型。 Quantity 和 Remains 元素无关紧要。
  • 那么您如何验证 InStockOnly 实际上总是错误的?你的帖子没有提到那个细节,也没有提供任何东西来证明它总是错误的。
  • 我会更详细地更新问题。
  • 修复了!我将&lt;InStockOnly&gt; 的数据类型更改为string,我还将if(inStockOnly) 更改为if(inStockOnly.Equals("1")) - 然后我传入&lt;InStockOnly&gt;1&lt;/InStockOnly&gt;,我得到了NullReferenceException。诡异的!所以我决定重新排序我的请求 XML,将 InStockOnly 元素移动到顶部 - 它有效!所以我将数据类型切换回bool,现在一切正常,如果有人知道为什么会发生这种情况,我非常想知道!很奇怪!一旦它在这里持续了 8 小时,我将用我的答案更新它 - 没有足够的声誉......

标签: c# xml wcf boolean


【解决方案1】:

我试过上面的建议还是不行!继续搜索,找到了另一个解决方案,实际上将“指定”属性设置为 true:

PackageImagesPayload payload = new PackageImagesPayload();
payload.UsesSplitBy = usesSplitBy;
payload.UsesSplitBySpecified = true;

【讨论】:

    【解决方案2】:

    您的发现使我得到了解释,并且有人遇到了与您类似的问题:

    WCF DataContract DataMember order? http://msdn.microsoft.com/en-us/library/ms729813.aspx

    接下来是当前类型的不具有 DataMemberAttribute 属性集的 Order 属性的数据成员,按字母顺序排列。

    当没有明确指定数据成员的顺序时,它们的序列化顺序是按字母顺序排列的。这就解释了为什么 InStockOnly 在移到顶部时起作用,因为它是按字母顺序排列的第一个。另一方面,StockDatabase 工作的原因有点神秘,因为这是在 UserId 之后按字母顺序排列的(如果 StockDb 为 null,AndyServerDatabase.ConnectToStockMovementByDb() 是否使用默认值?)。

    为了争论,如果出于某种原因你想保持你的订单,你可以这样做:

    [DataContract(Namespace = "http://myWebService.com/endpoint")]
    public class StockListRequestData
    {
        [DataMember(Order = 0)]
        public string UserID { get; set; }
    
        [DataMember(Order = 1)]
        public string StockDatabase { get; set; }
    
        [DataMember(Order = 2)]
        public bool InStockOnly { get; set; }
    }
    

    事实上,明确指出顺序可能是一种好习惯,因此以后添加新属性不会破坏任何内容。

    【讨论】:

    • 这完全有道理,是的,数据库连接似乎默认到同一个数据库,这就是它工作正常的原因 - 我需要解决这个问题。好吧,至少它没有被发现,谢谢你的解释!
    猜你喜欢
    • 2011-01-05
    • 1970-01-01
    • 2011-03-25
    • 2016-10-22
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 2012-08-02
    相关资源
    最近更新 更多