- PR -

.NETでの、Webサービスの戻り値について

1
投稿者投稿内容
Katsu
会議室デビュー日: 2007/02/23
投稿数: 4
投稿日時: 2007-02-23 11:44
katsuと申します。宜しくお願い致します。

現在、VisualStudio2005にてVB.NETを使用して、PDAか
らWebサービス経由でDBにデータ検索を行う処理を作成
していますが、Webサービスの戻り値を取得する部分で
困っています。

[問題の内容]
・Webサービスよりユーザ定義のクラスをObject配列に格納して戻しているが、
 Objectクラスを展開する際にInvalidCastExceptionが発生する。
・毎回発生するわけではなく、幾度かリビルドを行うと正常に返ってくる事がある。

[開発環境]
・VisualStudio2005(SP1)
・VB.NET

・サーバ環境
 Windows2003 Server(.NET Framework 2.0)
・クライアント環境
 Windows Mobile 5.0(.NET CompactFramework 2.0)

少々長くて恐縮ですが、下記に実際のソースを記述しております。
具体的には下から11行目のDirectCastにてExceptionが発生します。

rtn.Params(0)をToStringでログに出力すると、
正常に動作する場合:wsvPda.LineData
InvalidCastException発生の場合:System.Object
と帰ってきます。

Object配列にユーザ定義を入れて返す場合、他に注意する点、
足りていない処理等がありますでしょうか。


'[戻り値用のクラス]
Public Class WebParams

  Private _params() As Object
  Private _msgCategory As Integer
  Private _message As String

  Public Sub New()
    _msgCategory = 0
    _message = Nothing
  End Sub

  Public Property Params() As Object()
    Get
      Return _params
    End Get
    Set(ByVal value() As Object)
      _params = value
    End Set
  End Property

End Class


Public Class LineData
  Inherits Object

  Private _groupId As Integer
  Private _lineGroupId As Integer

  Public Property GroupID() As Integer
    Get
      Return _groupId
    End Get
    Set(ByVal value As Integer)
      _groupId = value
    End Set
  End Property

  Public Property LineGroupID() As Integer
    Get
      Return _lineGroupId
    End Get
    Set(ByVal value As Integer)
      _lineGroupId = value
    End Set
  End Property
End Class


'[Webサービス部分]
<WebMethod()> _
<System.Xml.Serialization.XmlInclude(GetType(LineData))> _
Public Function GetLineID(ByVal id As String, ByVal lineNo As Integer) As WebParams

  '戻り値
  Dim rtn As WebParams = New WebParams
  Dim ld As LineData = New LineData

  Dim getLine As ChangeLineDAO = New ChangeLineDAO()

  '↓下のメソッドでDBアクセスを行います。第3引数がByRefになっていて、結果が戻ってきます。
  ' 業務ロジックとしての結果判定が正常である場合は戻り値にTrueが返されます。
  If getLine.GetLineId(id, lineNo.ToString, ld) Then  
    ReDim rtn.Params(0)
    rtn.Params(0) = ld
  Else
    '検索結果0件メッセージ
    rtn.MessageCategory = Windows.Forms.MessageBoxIcon.Exclamation
    rtn.Message = "ラインNoが存在しません。"
  End If

  Return rtn

End Function


'[クライアント側]
'※Web参照は「wsvPda」という名前で参照しています。
Private Sub GetLineInfomation()

  'Webサービス
  Dim ws As wsvPda.Service = New wsvPda.Service

  Dim rtn As wsvPda.WebParams = New wsvPda.WebParams
  Dim ld As wsvPda.LineData

  'Webサービスへ接続
  Try
    rtn = ws.GetLineID(MyBase.lineId, Int32.Parse(MyBase.InputAreaText))
  Catch se As System.Web.Services.Protocols.SoapException
    Common.Utils.LogUtils.PutExceptionLog( _
      se, _
      System.Reflection.Assembly.GetExecutingAssembly.GetModules(0).FullyQualifiedName, _
    )
    Throw se
  Catch ex As Exception
    Throw New Exception(System.Reflection.Assembly.GetExecutingAssembly.GetModules(0).FullyQualifiedName, ex)
  End Try

  '戻り値が存在している場合は取得する
  If rtn.Params.Length >= 1 Then
    Try
      'ライン情報の格納
      '※※※ 下のDirectCastでエラーが発生します。
      ld = DirectCast(rtn.Params(0), wsvPda.LineData)
    Catch ice As InvalidCastException
      Throw ice

    Catch ex As Exception
      Throw ex

    End Try
  End If

End Sub


長々とすみませんが、何卒ご教授の程宜しくお願い致します。

/******
Katsu
*******/
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-02-23 12:32
引用:

・Webサービスよりユーザ定義のクラスをObject配列に格納して戻しているが、
 Objectクラスを展開する際にInvalidCastExceptionが発生する。



Object 型の配列ではなく、ユーザ定義クラスの配列を返すのでは駄目なんでしょうか?

引用:

・毎回発生するわけではなく、幾度かリビルドを行うと正常に返ってくる事がある。



Web サービスとクライアントで、バイナリや型情報に「ずれ」があるとか。

Web サービスをリビルドした後に必ず、クライアント側で Web サービスのプロクシを再作成しても状況に変化は無いんでしょうか?

[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2007-02-23 13:07 ]
Katsu
会議室デビュー日: 2007/02/23
投稿数: 4
投稿日時: 2007-02-23 13:39
ご返信ありがとうございます。Katsuです。


> Object 型の配列ではなく、ユーザ定義クラスの配列を返すのでは駄目なんでしょうか?

問題が解決できない場合は、ご指摘の通りユーザ定義クラスそのも
のにしようと考えているのですが、出来れば他のユーザ定義型のク
ラスも戻り値として返したいので、今の問題を解決できないかと
悩んでいます。

元々はサーバ側で行ったチェック結果をクライアントのPDAに表示
してあげたく、「Object型を継承したクラス+チェック結果」とい
う形をクライアントに戻してあげられるようにと考えていました。


> Web サービスとクライアントで、バイナリや型情報に「ずれ」があるとか。
>
> Web サービスをリビルドした後に必ず、クライアント側で Web サービスのプロクシを再作成しても状況に変化は無いんでしょうか?

ご指摘頂いて、下記の手順で再構築してみたのですが、
やはり結果はキャストエラーが発生しました。

[確認した手順]
ユーザ定義クラスのリビルド→Webサービスのリビルド
→Webサーバへ配置→Web参照を削除→Web参照を作成

念の為、上記の手順でユーザ定義クラスの配列に直して確認してみ
たのですが、正常に動作する事を確認しました。

やはり可能性としては、型情報がずれているパターンが高いのでしょうか。
念の為、もう一度他に見落としが無いか、考えて見ます。

お手数をお掛けして申し訳ございませんが、何かちょっとした事で
も更なるご指摘をいただけませんでしょうか。

宜しくお願い致します。


/*****
かつ
*****/
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-02-23 14:16
引用:

出来れば他のユーザ定義型のクラスも戻り値として返したいので、今の問題を解決できないかと悩んでいます。



型厳密性を避けるということは、実行時エラーの発生を許容することになるので、個人的には感心しない設計です。

他の型を返す可能性があるならメソッドを分けたり、戻りのデータを XML にしてしまうなどのアプローチの方がよかったりしないでしょうか?

引用:

やはり可能性としては、型情報がずれているパターンが高いのでしょうか。



キャストに失敗するということなので、型情報の認識にずれがあるか、配列に想定と異なる型あるいは NULL が紛れ込んでいる、なんてのがすぐに思いつくパターンです。

エラーになる時とならない時で、テストパターン(=Webサービス呼び出しの引数)は同じなんですよね?

エラーになる時とならない時で、Webサービスの応答をキャプチャして比較してみてはどうですか?



[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2007-02-23 14:46 ]
Katsu
会議室デビュー日: 2007/02/23
投稿数: 4
投稿日時: 2007-02-23 15:13
お世話になっております。

引用:

型厳密性を避けるということは、実行時エラーの発生を許容することになるので、個人的には感心しない設計です。

他の型を返す可能性があるならメソッドを分けたり、戻りのデータを XML にしてしまうなどのアプローチの方がよかったりしないでしょうか?



確かに、今回は解決出来たとして、この先の可能性を考えると
Object配列で戻すのは危険に感じてきました。


引用:

キャストに失敗するということなので、型情報の認識にずれがあるか、配列に想定と異なる型あるいは NULL が紛れ込んでいる、なんてのがすぐに思いつくパターンです。

エラーになる時とならない時で、テストパターン(=Webサービス呼び出しの引数)は同じなんですよね?

エラーになる時とならない時で、Webサービスの応答をキャプチャして比較してみてはどうですか?



テストパターンはまったく同じものを使用しています。結果として
Webサービス側が用意する戻り値も同じ値になるようにテストを行っ
ています。

Webサービスの応答をキャプチャなのですが、テストに使用してい
るWebサーバに、私が特定フォルダにデプロイする以外の権限がな
いので、試行できるまで少し時間がかかりそうです。
(クライアントはWindowsMobileなのですが、Mobileでも簡単に
キャプチャ出来るものなのでしょうか・・・)

少し気がついて、同じコードをPCにて利用してみました。
結果としては、Object型の配列でも正しく値が戻ってきました。

業務アプリへの実装はユーザ定義型そのものを使用する事にして、
今回の要因については少し整理をして、改めて追求してみます。

度重なるご返答、本当にありがとうございました。


[ メッセージ編集済み 編集者: Katsu 編集日時 2007-02-23 15:14 ]
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-02-23 15:44
引用:

(クライアントはWindowsMobileなのですが、Mobileでも簡単に
キャプチャ出来るものなのでしょうか・・・)



探せばありそうですが、最近は WindowsMobile な開発をしていないので心当たりが無いです…

引用:

少し気がついて、同じコードをPCにて利用してみました。
結果としては、Object型の配列でも正しく値が戻ってきました。

業務アプリへの実装はユーザ定義型そのものを使用する事にして、
今回の要因については少し整理をして、改めて追求してみます。



うーん、.NET Compact Frame の XML シリアライズ周りに何か問題があるんですかね?
あるいは、Windows Mobile のメモリ制限によって何か目に見えないトコで不具合が起きていたりするのでしょうか。
がんふぃーるど
ベテラン
会議室デビュー日: 2006/06/05
投稿数: 58
お住まい・勤務地: さいたま
投稿日時: 2007-02-23 16:21
がんふぃーるどです。お世話様です。

Object型を使用するしないはさておいて、通信内容はどのようになっているのでしょうか?
例外が発生した際の通信内容が分かれば、どのようなことが起こっているか分かるかもしれません。

# 通信内容はFiddlerなどを使用すれば分かります。
Katsu
会議室デビュー日: 2007/02/23
投稿数: 4
投稿日時: 2007-02-23 17:31
お世話になります。Katsuです。

引用:

例外が発生した際の通信内容が分かれば、どのようなことが起こっているか分かるかもしれません。



ご返信ありがとうございます。
早速ご提示頂いたツールを使用して内容を確認してみました。
PCから実行した結果ですが、下記に引用致します。

コード:
//ここからリクエストデータです。
<?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>
      <GetLineID xmlns="http://tempuri.org/">
        <organizationID>14</organizationID>
        <lineNo>4</lineNo>
      </GetLineID>
    </soap:Body>
  </soap:Envelope>


//ここからResponseデータです

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Fri, 23 Feb 2007 08:02:26 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Length: 541

<?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>
      <GetLineIDResponse xmlns="http://tempuri.org/">
        <GetLineIDResult>
          <Params>
            <anyType xsi:type="LineData">
              <OrganizationID>14</OrganizationID>
              <LineNo>4</LineNo>
              <GroupID>5</GroupID>
              <LineGroupID>4</LineGroupID>
            </anyType>
          </Params>
          <MessageCategory>0</MessageCategory>
        </GetLineIDResult>
      </GetLineIDResponse>
    </soap:Body>
  </soap:Envelope>

※任意に改行と半角空白を挿入しています。



内容にOrganizationIDとLineNoが増えていますが、他のメンバと同じく
LinDataに定義しているInteger型のメンバです。

内容を確認していても、特に違和感を感じないのですが・・・。どうでしょうか。。
# 同じWebサービスで、PDAとPCでレスポンスの違いがあったりするでしょうか。

現在テストサーバの管理者に、当該ツールのインストール及び使用許可申請を
提出しています。

許可が下り次第、PDAから試行して結果をご提示するように致します。
(というか実際に例外発生時の内容じゃないとあまり参考になりませんよね。失礼致しました。)
1

スキルアップ/キャリアアップ(JOB@IT)