读取POST请求XML - 布尔值始终读为false

时间:2013-01-06 22:26:39

标签: c# xml wcf boolean

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

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

此XML与我的网络服务上的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; }
}

问题是<InStockOnly>true</InStockOnly>元素,当我将其设置为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) - 然后传入<InStockOnly>true</InStockOnly> - 当它到达StockList构造函数时,它会被反转并显示正确的数据 - 所以它必须在到达if语句时将其读作false。

如果我传入<InStockOnly>false</InStockOnly>,它仍会显示“正确”的结果,因此它会将其读取为假,直到它进入反转!

同样,如果我将其保留为if(inStockOnly)并传入<InStockOnly>false</InStockOnly>,则会显示false的数据!

我还将requestData.InStockOnly添加到StockListResponseData DataContract,然后显示它将requestData.InStockOnly的值输出为false

2 个答案:

答案 0 :(得分:1)

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

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

  

接下来按顺序排列当前类型的数据成员,它们没有按字母顺序设置DataMemberAttribute属性的Order属性。

如果未明确指定数据成员的顺序,则其序列化顺序是按字母顺序排列的。这就解释了为什么InStockOnly在移动到顶部时起作用,因为它首先按字母顺序排列。另一方面,为什么StockDatabase工作有点神秘,因为按字母顺序排在UserId之后(如果StockDb为空,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; }
}

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

答案 1 :(得分:0)

我尝试了上面的建议但它仍然无效!保持搜索并找到另一个解决方案,实际上将'Specified'属性设置为true:

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