C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

Webサービスからのタグなし項目を取得時の挙動 /雪だるま (18/07/12(Thu) 16:51) #87907
Re[1]: Webサービスからのタグなし項目を取得時の挙動 /PANG2 (18/07/12(Thu) 17:32) #87909
Re[1]: Webサービスからのタグなし項目を取得時の挙動 /WebSurfer (18/07/12(Thu) 17:30) #87908
Re[1]: Webサービスからのタグなし項目を取得時の挙動 /WebSurfer (18/07/13(Fri) 12:49) #87920
  └ Re[2]: Webサービスからのタグなし項目を取得時の挙動 /雪だるま (18/07/17(Tue) 01:09) #87943
    ├ Re[3]: Webサービスからのタグなし項目を取得時の挙動 /Hongliang (18/07/17(Tue) 11:06) #87945
    └ Re[3]: Webサービスからのタグなし項目を取得時の挙動 /WebSurfer (18/07/17(Tue) 14:04) #87946


親記事 / ▼[ 87909 ] ▼[ 87908 ] ▼[ 87920 ]
■87907 / 親階層)  Webサービスからのタグなし項目を取得時の挙動
□投稿者/ 雪だるま (1回)-(2018/07/12(Thu) 16:51:52)

分類:[ASP.NET (VB)] 

環境はVisual Studio 2010でVBです。

サービス参照の追加からWSDLを取り込んでWebサービスにアクセスするプログラムを作成しました。
Webサービスからタグなしで返却された項目(Long型)をアプリケーション側から取得すると0が取得されました。
タグなしの場合は"N/A"として出力したいので、タグなしと値が0で返却された場合を見分けたいです。

何か方法があればご教授いただけないでしょうか。

※SOAP UIで取得した際には、タグなしで表示されました。
[ □ Tree ] 返信 編集キー/

▲[ 87907 ] / 返信無し
■87909 / 1階層)  Re[1]: Webサービスからのタグなし項目を取得時の挙動
□投稿者/ PANG2 (222回)-(2018/07/12(Thu) 17:32:14)
ASP.NETでヌルを渡せる項目を作ってみました。


■ASP.NET Webサービス
public class POINT
{
public long? x;
public long y;
}

■WSDL
<s:element minOccurs="1" maxOccurs="1" name="x" nillable="true" type="s:long" />
<s:element minOccurs="1" maxOccurs="1" name="y" type="s:long" />

---
■プロクシクラス
public System.Nullable<long> x
public long y  

[ 親 87907 / □ Tree ] 返信 編集キー/

▲[ 87907 ] / 返信無し
■87908 / 1階層)  Re[1]: Webサービスからのタグなし項目を取得時の挙動
□投稿者/ WebSurfer (1554回)-(2018/07/12(Thu) 17:30:23)
No87907 (雪だるま さん) に返信

もう少し詳しく開発環境(OS, .NET, IIS のバージョン、使用ブラウザなど)を書いてください。

> Webサービスからタグなしで返却された項目(Long型)をアプリケーション側から取得すると0が取得されました。

「タグなしで返却」とはどういう意味ですか?
[ 親 87907 / □ Tree ] 返信 編集キー/

▲[ 87907 ] / ▼[ 87943 ]
■87920 / 1階層)  Re[1]: Webサービスからのタグなし項目を取得時の挙動
□投稿者/ WebSurfer (1557回)-(2018/07/13(Fri) 12:49:58)
No87907 (雪だるま さん) に返信
> 環境はVisual Studio 2010でVBです。

PANG2 さんのレスから想像を膨らませてみました。

xml 上で NULL を表すのが既定では要素が存在しないということになるそうですが、それを「Web
サービスからタグなしで返却」と言っていたのだと理解します。

以下の Web サービスの GetLong メソッドの戻り値は long? 型でこの例では null を返します。
GetDataTable は SQL Server DB のテーブルの全レコードを DataTable に取得して返しますが、
その最初のレコードの CategoryID が NULL になっています。

<%@ WebService Language="C#" Class="NorthwindProductsWebService" %>

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using NorthwindProducts;
using NorthwindProducts.ProductsDataSetTableAdapters;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class NorthwindProductsWebService  : System.Web.Services.WebService
{
    [WebMethod]
    public long? GetLong()
    {
        return null;
    }

    [WebMethod]
    public ProductsDataSet.ProductsDataTable GetDataTable()
    {        
        ProductsDataSet.ProductsDataTable datatable = new ProductsDataSet.ProductsDataTable();
        ProductsTableAdapter adapter = new ProductsTableAdapter();
        adapter.Fill(datatable);
        return datatable;
    }
}

それをクライアント側のアプリで取得すると GetLong は null を返しますので null が返ってき
たら "N/A" と表示すれば良いはずです。

GetDataTable は DataTable を返しますが、DB で NULL になっているとその行・列のデータは
DBNull 型になっているので、その場合は "N/A" とすればよいはずです。

以下のその例を示します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;

namespace ConsoleAppWebService
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceReference1.NorthwindProductsWebServiceSoapClient client = 
                new ServiceReference1.NorthwindProductsWebServiceSoapClient();

            long? value = client.GetLong();
            Console.WriteLine("Result of GetLong: {0}", (value == null) ? "N/A" : value.ToString());

            ServiceReference1.ProductsDataSet.ProductsDataTable table = client.GetDataTable();
            for (int i = 0; i < 5; i++)
            {
                string categoryId = (table[i][table.CategoryIDColumn] is DBNull) ? 
                    "N/A" : table[i][table.CategoryIDColumn].ToString();

                Console.WriteLine("Name: {0}, SupplierID: {1}, CategoryID: {2}",
                    table[i].ProductName, table[i].SupplierID, categoryId);
            }

            // 結果は:
            // Result of GetLong: N/A
            // Name: Chai, SupplierID: 1, CategoryID: N / A
            // Name: Chang, SupplierID: 1, CategoryID: 1
            // Name: Aniseed Syrup, SupplierID: 1, CategoryID: 2
            // Name: Chef Anton's Cajun Seasoning, SupplierID: 2, CategoryID: 2
            // Name: Chef Anton's Gumbo Mix, SupplierID: 2, CategoryID: 2
        }
    }
}

[ 親 87907 / □ Tree ] 返信 編集キー/

▲[ 87920 ] / ▼[ 87945 ] ▼[ 87946 ]
■87943 / 2階層)  Re[2]: Webサービスからのタグなし項目を取得時の挙動
□投稿者/ 雪だるま (2回)-(2018/07/17(Tue) 01:09:42)
WebSurferさん
PANG2さん

返信が遅くなり申し訳ございません。
また、情報と前提が抜けているようで本当に申し訳ございません。

開発環境の情報と現状の処理イメージを追加させていただきます。

【前提】
Webサービス側のソースは提供してもらえない。
Webサービスは他社が提供しているため修正は難しい
→Webサービス側としては、タグなしとタグありで見分けられる筈だとのことです。

バージョン
OS:Windows10
.NET:NET Framework 3.5
IIS:IIS10.0
ブラウザ:IE11(エンタープライズモード(IE8互換))

-----レスポンスイメージ(通常時)-----
<tns:Status>
<tns:Status_Code>000</tns:Status_Code>
</tns:Status>
<tns:RESPONSE>
<tns:STR1>hoge</tns:STR1>
<tns:LNG1>1000</tns: LNG1>
<tns:LNG2>2000</tns:LNG2>
</tns:RESPONSE>
-------------------------------------------------------

-----レスポンスイメージ(STR1、LNG2がタグなし)-----
<tns:Status>
<tns:Status_Code>000</tns:Status_Code>
</tns:Status>
<tns:Response>
<tns:LNG1>1111</tns:LNG1>
</tns:Response>
-------------------------------------------------------

----------------------WSDL(抜粋)--------------------
<xsd:element minOccurs="0" name="STR1" type="xsd:string" />
<xsd:element minOccurs="0" name="LNG1" type="xsd:long" />
<xsd:element minOccurs="0" name="LNG2" type="xsd:long" />
<xsd:element minOccurs="0" name="LNG3" type="xsd:long" />
-------------------------------------------------------
---------------------------ソース(抜粋)---------------------------
'検索条件の設定
Dim result As New HogeSystem.HogeSerch.HogeSerch応答
sercInput(0) = New App_HogeSerch.HogeSerchRequestInput()
sercInput(0).KEY = 12345

’検索処理
result = webService.HogeSerch(sercInput)

'検索結果の取得
Dim str1 As Object = result.HogeSystem(0).SERCH_HOGE(0).STR1)
Dim lng1 As Object = result.HogeSystem(0).SERCH_HOGE(0).LNG1)
'タグあり:2000、タグなし:0が取得されている
Dim lng2 As Object = result.HogeSystem(0).SERCH_HOGE(0).LNG2)

’Nullの置換処理
If str1 Is Nothing Then
str1 = "N/A"
End If

If lng1 Is Nothing Then
lng1 = "N/A"
End If

If lng2 Is Nothing Then
lng2 = "N/A"
End If
----------------------------------------------------------------------------

No87920 (WebSurfer さん) に返信
> ■No87907 (雪だるま さん) に返信
>>環境はVisual Studio 2010でVBです。
>
> PANG2 さんのレスから想像を膨らませてみました。
>
> xml 上で NULL を表すのが既定では要素が存在しないということになるそうですが、それを「Web
> サービスからタグなしで返却」と言っていたのだと理解します。
>
> 以下の Web サービスの GetLong メソッドの戻り値は long? 型でこの例では null を返します。
> GetDataTable は SQL Server DB のテーブルの全レコードを DataTable に取得して返しますが、
> その最初のレコードの CategoryID が NULL になっています。
>
> <%@ WebService Language="C#" Class="NorthwindProductsWebService" %>
>
> using System;
> using System.Web;
> using System.Web.Services;
> using System.Web.Services.Protocols;
> using NorthwindProducts;
> using NorthwindProducts.ProductsDataSetTableAdapters;
>
> [WebService(Namespace = "http://tempuri.org/")]
> [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
> public class NorthwindProductsWebService : System.Web.Services.WebService
> {
> [WebMethod]
> public long? GetLong()
> {
> return null;
> }
>
> [WebMethod]
> public ProductsDataSet.ProductsDataTable GetDataTable()
> {
> ProductsDataSet.ProductsDataTable datatable = new ProductsDataSet.ProductsDataTable();
> ProductsTableAdapter adapter = new ProductsTableAdapter();
> adapter.Fill(datatable);
> return datatable;
> }
> }
>
> それをクライアント側のアプリで取得すると GetLong は null を返しますので null が返ってき
> たら "N/A" と表示すれば良いはずです。
>
> GetDataTable は DataTable を返しますが、DB で NULL になっているとその行・列のデータは
> DBNull 型になっているので、その場合は "N/A" とすればよいはずです。
>
> 以下のその例を示します。
>
> using System;
> using System.Collections.Generic;
> using System.Linq;
> using System.Text;
> using System.Threading.Tasks;
> using System.Data;
>
> namespace ConsoleAppWebService
> {
> class Program
> {
> static void Main(string[] args)
> {
> ServiceReference1.NorthwindProductsWebServiceSoapClient client =
> new ServiceReference1.NorthwindProductsWebServiceSoapClient();
>
> long? value = client.GetLong();
> Console.WriteLine("Result of GetLong: {0}", (value == null) ? "N/A" : value.ToString());
>
> ServiceReference1.ProductsDataSet.ProductsDataTable table = client.GetDataTable();
> for (int i = 0; i < 5; i++)
> {
> string categoryId = (table[i][table.CategoryIDColumn] is DBNull) ?
> "N/A" : table[i][table.CategoryIDColumn].ToString();
>
> Console.WriteLine("Name: {0}, SupplierID: {1}, CategoryID: {2}",
> table[i].ProductName, table[i].SupplierID, categoryId);
> }
>
> // 結果は:
> // Result of GetLong: N/A
> // Name: Chai, SupplierID: 1, CategoryID: N / A
> // Name: Chang, SupplierID: 1, CategoryID: 1
> // Name: Aniseed Syrup, SupplierID: 1, CategoryID: 2
> // Name: Chef Anton's Cajun Seasoning, SupplierID: 2, CategoryID: 2
> // Name: Chef Anton's Gumbo Mix, SupplierID: 2, CategoryID: 2
> }
> }
> }
[ 親 87907 / □ Tree ] 返信 編集キー/

▲[ 87943 ] / 返信無し
■87945 / 3階層)  Re[3]: Webサービスからのタグなし項目を取得時の挙動
□投稿者/ Hongliang (661回)-(2018/07/17(Tue) 11:06:26)
LNG1というプロパティとともに、LNG1Specifiedというプロパティが自動生成されていませんか?
LNG1要素の有無はこのLNG1Specifiedプロパティで判定できそうですが。
[ 親 87907 / □ Tree ] 返信 編集キー/

▲[ 87943 ] / 返信無し
■87946 / 3階層)  Re[3]: Webサービスからのタグなし項目を取得時の挙動
□投稿者/ WebSurfer (1559回)-(2018/07/17(Tue) 14:04:40)
No87943 (雪だるま さん) に返信

> Webサービス側のソースは提供してもらえない。

それが分からないと、ここに書いてあること以外は知り得ない第三者が答えられることは限られて
くると思います。

普通に、Web Service (.asmx) を作って、クライアントアプリでサービス参照を追加して .asmx の
メソッドを呼べば、Web Service のメソッドが null を返せば、クライアント側でも null になるは
ずなのですが・・・

ただ、質問者さんがアップされた WSDL や応答の XML は、自分の環境で自分が考える「普通に」作
ったものとは異なります。

そのあたりの違いが、クライアント側で期待に反して null ではなく 0 (ゼロ) が取得されるという
結果につながっているのではなかろうかと想像してます。(もちろん単なる想像で、確証があるわけ
ではありませんが)

質問者さんが利用している Web Service のメソッドを想像して検証用のコードを作ってみたので、そ
のコードと、それが返す WDSL, 応答 XML を参考にアップしておきます。

自分の環境は、ASP.NET Web Forms アプリ、Windows 10 Pro 64-bit, ローカル IIS、.NET 4.6.1,
Visual Studio Comunity 2015 Update 3 です。

【Web Service】

<%@ WebService Language="C#" Class="NorthwindProductsWebService" %>

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using NorthwindProducts;
using NorthwindProducts.ProductsDataSetTableAdapters;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class NorthwindProductsWebService  : System.Web.Services.WebService
{
    [WebMethod]
    public SampleClass GetSampleClass(string s, long? l1, long? l2, long? l3)
    {
        return new SampleClass { STR1 = s, LNG1 = l1, LNG2 = l2, LNG3 = l3 };
    }
}

[Serializable]
public class SampleClass
{
    public string STR1 { get; set; }
    public long? LNG1 { get; set; }
    public long? LNG2 { get; set; }
    public long? LNG3 { get; set; }
}

【WDSL (抜粋)】

<s:element name="GetSampleClass">
  <s:complexType>
    <s:sequence>
      <s:element minOccurs="0" maxOccurs="1" name="s" type="s:string" />
      <s:element minOccurs="1" maxOccurs="1" name="l1" nillable="true" type="s:long" />
      <s:element minOccurs="1" maxOccurs="1" name="l2" nillable="true" type="s:long" />
      <s:element minOccurs="1" maxOccurs="1" name="l3" nillable="true" type="s:long" />
    </s:sequence>
  </s:complexType>
</s:element>
<s:element name="GetSampleClassResponse">
  <s:complexType>
    <s:sequence>
      <s:element minOccurs="0" maxOccurs="1" name="GetSampleClassResult" type="tns:SampleClass" />
    </s:sequence>
  </s:complexType>
</s:element>
<s:complexType name="SampleClass">
  <s:sequence>
    <s:element minOccurs="0" maxOccurs="1" name="STR1" type="s:string" />
    <s:element minOccurs="1" maxOccurs="1" name="LNG1" nillable="true" type="s:long" />
    <s:element minOccurs="1" maxOccurs="1" name="LNG2" nillable="true" type="s:long" />
    <s:element minOccurs="1" maxOccurs="1" name="LNG3" nillable="true" type="s:long" />
  </s:sequence>
</s:complexType>


【クライアントアプリ】

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;

namespace ConsoleAppWebService
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceReference1.NorthwindProductsWebServiceSoapClient client = 
                new ServiceReference1.NorthwindProductsWebServiceSoapClient();

            sample = client.GetSampleClass(null, null, 2000L, null);
            Console.WriteLine("STR1: {0}, LNG1: {1}, LNG2: {2}, LNG3: {3}",
                sample.STR1, sample.LNG1, sample.LNG2, sample.LNG3);
        }
    }
}


【応答 XML】

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <GetSampleClassResponse xmlns="http://tempuri.org/">
      <GetSampleClassResult>
        <LNG1 xsi:nil="true" />
        <LNG2>2000</LNG2>
        <LNG3 xsi:nil="true" />
      </GetSampleClassResult>
    </GetSampleClassResponse>
  </soap:Body>
</soap:Envelope>

[ 親 87907 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -