- - PR -
.NETでの、Webサービスの戻り値について
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 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 *******/ | ||||||||
|
投稿日時: 2007-02-23 12:32
Object 型の配列ではなく、ユーザ定義クラスの配列を返すのでは駄目なんでしょうか?
Web サービスとクライアントで、バイナリや型情報に「ずれ」があるとか。 Web サービスをリビルドした後に必ず、クライアント側で Web サービスのプロクシを再作成しても状況に変化は無いんでしょうか? [ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2007-02-23 13:07 ] | ||||||||
|
投稿日時: 2007-02-23 13:39
ご返信ありがとうございます。Katsuです。
> Object 型の配列ではなく、ユーザ定義クラスの配列を返すのでは駄目なんでしょうか? 問題が解決できない場合は、ご指摘の通りユーザ定義クラスそのも のにしようと考えているのですが、出来れば他のユーザ定義型のク ラスも戻り値として返したいので、今の問題を解決できないかと 悩んでいます。 元々はサーバ側で行ったチェック結果をクライアントのPDAに表示 してあげたく、「Object型を継承したクラス+チェック結果」とい う形をクライアントに戻してあげられるようにと考えていました。 > Web サービスとクライアントで、バイナリや型情報に「ずれ」があるとか。 > > Web サービスをリビルドした後に必ず、クライアント側で Web サービスのプロクシを再作成しても状況に変化は無いんでしょうか? ご指摘頂いて、下記の手順で再構築してみたのですが、 やはり結果はキャストエラーが発生しました。 [確認した手順] ユーザ定義クラスのリビルド→Webサービスのリビルド →Webサーバへ配置→Web参照を削除→Web参照を作成 念の為、上記の手順でユーザ定義クラスの配列に直して確認してみ たのですが、正常に動作する事を確認しました。 やはり可能性としては、型情報がずれているパターンが高いのでしょうか。 念の為、もう一度他に見落としが無いか、考えて見ます。 お手数をお掛けして申し訳ございませんが、何かちょっとした事で も更なるご指摘をいただけませんでしょうか。 宜しくお願い致します。 /***** かつ *****/ | ||||||||
|
投稿日時: 2007-02-23 14:16
型厳密性を避けるということは、実行時エラーの発生を許容することになるので、個人的には感心しない設計です。 他の型を返す可能性があるならメソッドを分けたり、戻りのデータを XML にしてしまうなどのアプローチの方がよかったりしないでしょうか?
キャストに失敗するということなので、型情報の認識にずれがあるか、配列に想定と異なる型あるいは NULL が紛れ込んでいる、なんてのがすぐに思いつくパターンです。 エラーになる時とならない時で、テストパターン(=Webサービス呼び出しの引数)は同じなんですよね? エラーになる時とならない時で、Webサービスの応答をキャプチャして比較してみてはどうですか? [ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2007-02-23 14:46 ] | ||||||||
|
投稿日時: 2007-02-23 15:13
お世話になっております。
確かに、今回は解決出来たとして、この先の可能性を考えると Object配列で戻すのは危険に感じてきました。
テストパターンはまったく同じものを使用しています。結果として Webサービス側が用意する戻り値も同じ値になるようにテストを行っ ています。 Webサービスの応答をキャプチャなのですが、テストに使用してい るWebサーバに、私が特定フォルダにデプロイする以外の権限がな いので、試行できるまで少し時間がかかりそうです。 (クライアントはWindowsMobileなのですが、Mobileでも簡単に キャプチャ出来るものなのでしょうか・・・) 少し気がついて、同じコードをPCにて利用してみました。 結果としては、Object型の配列でも正しく値が戻ってきました。 業務アプリへの実装はユーザ定義型そのものを使用する事にして、 今回の要因については少し整理をして、改めて追求してみます。 度重なるご返答、本当にありがとうございました。 [ メッセージ編集済み 編集者: Katsu 編集日時 2007-02-23 15:14 ] | ||||||||
|
投稿日時: 2007-02-23 15:44
探せばありそうですが、最近は WindowsMobile な開発をしていないので心当たりが無いです…
うーん、.NET Compact Frame の XML シリアライズ周りに何か問題があるんですかね? あるいは、Windows Mobile のメモリ制限によって何か目に見えないトコで不具合が起きていたりするのでしょうか。 | ||||||||
|
投稿日時: 2007-02-23 16:21
がんふぃーるどです。お世話様です。
Object型を使用するしないはさておいて、通信内容はどのようになっているのでしょうか? 例外が発生した際の通信内容が分かれば、どのようなことが起こっているか分かるかもしれません。 # 通信内容はFiddlerなどを使用すれば分かります。 | ||||||||
|
投稿日時: 2007-02-23 17:31
お世話になります。Katsuです。
ご返信ありがとうございます。 早速ご提示頂いたツールを使用して内容を確認してみました。 PCから実行した結果ですが、下記に引用致します。
内容にOrganizationIDとLineNoが増えていますが、他のメンバと同じく LinDataに定義しているInteger型のメンバです。 内容を確認していても、特に違和感を感じないのですが・・・。どうでしょうか。。 # 同じWebサービスで、PDAとPCでレスポンスの違いがあったりするでしょうか。 現在テストサーバの管理者に、当該ツールのインストール及び使用許可申請を 提出しています。 許可が下り次第、PDAから試行して結果をご提示するように致します。 (というか実際に例外発生時の内容じゃないとあまり参考になりませんよね。失礼致しました。) |
1