- PR -

[WebMethod] attribute と element

投稿者投稿内容
ひざらがい
会議室デビュー日: 2001/10/13
投稿数: 6
投稿日時: 2001-12-11 22:46
ASP.NET(beta2) の WebService で SOAP メソッドコールの
element と attribute の両方の値を受け取るには、どうすればよいでしょうか?

UDDI 2.0 API に find_business というメソッドコールがあるのですが、
xml-element と xml-attribute の両方の引数を取ります。

 <soap:Body>
  <find_business maxRows="10"
          generic="2.0"
          xmlns="urn:uddi-org:api_v2" >
   <name>service corp</name>
  </find_business>
 </soap:Body>

これの Web Service 側で maxRows の値"10"と、<name> の値"service corp"を
受け取りたいのです。

以下のように、ASP.NET(C#,beta2) で XmlAttribute を使ってみたのですが、
maxRows の値をまったく拾えていません。(戻り値はいい加減)

 [WebMethod]
 public string find_business(
   string name,
   [XmlAttribute("maxRows")]int maxRows )
 {
   ....
 }

いったいどのようにすれば、maxRows の値を取ってこれるのか、
情報をお持ちの方はいらっしゃいませんでしょうか?

では、よろしくお願いします。
--
けい
常連さん
会議室デビュー日: 2001/09/12
投稿数: 48
投稿日時: 2001-12-12 04:44
私のとこ(同じくC#,beta2)では、
[WebMethod]
public string HelloWorld([System.Xml.Serialization.XmlAttribute("valueofattribute")]int valueofattribute,int valueofelement)
{
 return "valueofattribute is " + valueofattribute + "valueofelement" + valueofelement;
}

ってすると、
<s:element name="HelloWorld">
 <s:complexType>
  <s:sequence>
   <s:element minOccurs="1" maxOccurs="1" name="valueofelement" type="s:int" />
  </s:sequence>
  <s:attribute name="valueofattribute" type="s:int" />
 </s:complexType>
</s:element>

というWSDLが生成されて、実行もきちんとされてるようですが...

#[]の中って名前の最後のAttributeが省略されるんですね...
#最初、[System.Xml.XmlAttribute]をつけようとしていて、
#そんなのはないと言われて、パニクりました(^^;
#(上で付けてるのは System.Xml.Serialization.XmlAttributeAttributeクラス)
ひざらがい
会議室デビュー日: 2001/10/13
投稿数: 6
投稿日時: 2001-12-12 22:18
遅くなってすみません。実は上手くいってないです。

確かに WSDL は、きれいに出ているようです。クライアントプロクシーも作成できました。
System.Xml.Serialization.XmlAttributeAttribute を使うのは、間違ってないようです。

しかし、実際に実行してみるとダメです。
int だと、暗黙の初期化で 0 が入ってくるように見えますが、string にしてみると、空文字列( String.Empty )になってしまっています。
つまり、値が取れてきていないことになります。
# 私の環境のせいかなぁ...

Web Service 側のメソッドの引数の順番も関係あるかも知れないと思い、2引数での4通りを試してみました。
クライアントからは、第1引数に文字列 "foo" 、第2引数に文字列 "bar" が乗るようにプログラムします。

(基本)
using System.Xml.Serialization;
[WebMethod] public string AttrElem(
              string first,
              string second )
      {
        return first + "+" + second;
      }

(1)
public string AttrElem(
    [XmlElement]string first,
    [XmlElement]string second )

  戻り値:<AttrElemResult>foo+bar</AttrElemResult>
   当たり前に上手くいってます。

(2)
public string AttrElem(
    [XmlAttribute]string first,
    [XmlElement]string second )

  戻り値:<soap:Fault>.. サーバーは要求を読み取れませんでした
   なんと HTTP 500

(3)
public string AttrElem(
    [XmlElement]string first,
    [XmlAttribute]string second )

  戻り値:<AttrElemResult>foo+</AttrElemResult>
   attribute の値が採れてない

(4)
public string AttrElem(
    [XmlAttribute]string first,
    [XmlAttribute]string second )

  戻り値:<AttrElemResult>+</AttrElemResult>
   attribute の値が両方とも採れてない


泥沼にはまっているようです。
すみません、追試していただけませんか?

--
けい
常連さん
会議室デビュー日: 2001/09/12
投稿数: 48
投稿日時: 2001-12-13 15:15
昨日は、サーバ側だけ作って、テスト用ページからのメソッド呼び出しで、
答えが返ってきていたので、動いているようだと思ったのですが、
あのページからだと、GETでとっているのでテストになってなかったようです。

クライアントを作って(1)-(4)を呼び出したら、確かにうまく行かず、
ほぼ同じような結果になりました。
#デバッグオプションつけたままコンパイルしたので、(2)ではデバッガが上がってきてしまいましたが。
けい
常連さん
会議室デビュー日: 2001/09/12
投稿数: 48
投稿日時: 2001-12-13 15:40
ちなみに、手で接続して、

引用:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<HelloWorld valueofattribute="int" xmlns="http://localhost/test/WebService1">
<valueofelement>int</valueofelement>
</HelloWorld>
</soap:Body>
</soap:Envelope>



をPOSTすると、

引用:

HTTP/1.1 100 Continue
Server: Microsoft-IIS/5.0
Date: Thu, 13 Dec 2001 06:16:04 GMT
HTTP/1.1 500 内部サーバー エラーです。
Server: Microsoft-IIS/5.0
Date: Thu, 13 Dec 2001 06:16:04 GMT
Cache-Control: private
Content-Type: text/xml; charset=utf-8
Content-Length: 1054
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>System.Web.Services.Protocols.SoapException: <文字化け> ---> System.Exception: XML <文字化け>(5,8) <文字化け>---> System.IndexOutO
fRangeException: <文字化け>System.IndexOutOfRangeException <文字化け>
at n2499d7d93ffa468fbd8861780677ee41.XmlSerializationReader1.Read1_HelloWorl
d()
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faul
tstring>
<detail />
</soap:Fault>
</soap:Body>
</soap:Envelope>


ってのがかえってきました。
引数の読み込みっぽいところ(ReadParameters)で例外が発生しているようですが...
私はお手上げ状態ですが、何かの参考になるでしょうか?
文字化けのとこが読めればもう少し情報になりそうなのですが...telnetのせいかな?


[ メッセージ編集済み 編集者: けい 編集日時 2001-12-13 15:41 ]
ひざらがい
会議室デビュー日: 2001/10/13
投稿数: 6
投稿日時: 2001-12-13 21:44
う〜〜ん。ダメでしたか。
私の環境だけではないとわかって、ちょっと安心です。(いや安心しちゃいけないのか)

soap:Fault の文字化けの部分は、UTF-8 で以下のようになります。

  <soap:Fault>
   <faultcode>soap:Client</faultcode>
   <faultstring>System.Web.Services.Protocols.SoapException: System.Web.Services.Protocols.SoapException: サーバーは要求を読みとれませんでした。 ---> System.Exception: XML ドキュメント (5,8) でエラーが発生しました。 ---> System.IndexOutOfRangeException: 種類 System.IndexOutOfRangeException の例外がスローされました。
  at n2499d7d93ffa468fbd8861780677ee41.XmlSerializationReader1.Read1_AttrElem()
  at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
  at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
  at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
  at System.Web.Services.Protocols.WebServiceHandler.Invoke()
  at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faultstring>
   <detail />
  </soap:Fault>

Request の5行8桁目とは、多分、element 引数のタグ名の始まりです。
namespace がいるのかとも思い、いろいろ付けてみましたが、結局ダメでした。
何のインデックスが溢れているのでしょうか。さっぱりわかりません。


私もこれ以上こればっかりに関わってはいられないので、あきらめるとします。
お客さまには、「attribute に使うものは、それほど重要ではない」とか言って、先に進ませて貰いましょう。
「ダメだ」と言われたら、apache.axis に行くかな。

お付き合いいただき、ありがとうございました。
--
NothingBut.NETFX
大ベテラン
会議室デビュー日: 2001/09/13
投稿数: 102
投稿日時: 2001-12-21 18:12
いまさら、ですが...

System.Web.Services.Protocols.SoapParameterStyleが関係しています。ASP.NETのデフォルトであるSoapDocumentMethodのParameterStyleのデフォルトはSoapParameterStyle.Wrappedです。つまり、soap:Body直下の要素は価値ある情報と解釈されません。この場合、<find_business>要素は、単にメソッド実装へのルーティング情報でしかないことになります。

soap:Body直下の要素を意味あるものとして扱うには、SoapParameterStyle.Bareを指定しなければなりません。さて、ではこれでいけるかというと、
コード:
[WebMethod]
[SoapDocumentMethod(ParameterStyle=SoapParameterStyle.Bare)]
public string AttrElem([XmlAttribute]string first, [XmlAttribute]string second) { 
	return first + "+" + second; 
} 


は、次のようなエラーになります。
XmlAttribute をパラメータで使ったり戻り値にすることはできません。
ちゃんちゃん。

どうしても<find_business>みたいなものをASP.NETで扱いたい場合は、SoapExtensionを使って、属性を要素にしてしまうとか送られたSOAPメッセージ全体をさらにくるむとか、そういう処理を実装する必要がありそうです。たとえば、MicrosoftのUDDI SDKはそうしていますね。
ひざらがい
会議室デビュー日: 2001/10/13
投稿数: 6
投稿日時: 2002-01-08 19:25
あぁ、まったく気づかずに休みに入ってしまい、失礼しました。

私のほうも、あきらめの宣言をしましたが、ちょっと踏ん切りがつかずまだいじくっていて、System.Web.Services.Protocols.SoapDocumentMethodAttribute にたどり着きました。

しかし結果は、NothingBut.NETFW さんが実験してくださったように、

  XmlAttribute をパラメータで使ったり戻り値にすることはできません。

でした。

.NET で言うところの System.Web.Services.Protocols.SoapParameterStyle.Bare とは、特に System.Web.Services.Description.SoapBindingUse.Literal と組み合わせたとき

  <soap:Body>
   <parameter1>element1</parameter1>
   <parameter2>element2</parameter2>
   <parameter3>element1</parameter3>
  </soap:Body>

のように、soap:Body 直下に並ぶ xml エレメントを、適当な WebMethod 名で受け取るための物のようです。

ここで例えば、

   <parameter1 attr="foo">element1</parameter1>
   <parameter2 attr="bar">element2</parameter2>

とあったとき、attr アトリビュートは、parameter1 に属するのか、parameter2 に属するのか、WebMethod の方では、なかなか区別がつかないと言うことみたいです。
しょうがないような気もしますが、天下の MS ですから、何とかしてほしい気もします。


私の UDDI サービスは結局どうしたかというと、本来の asmx による Web サービスは、あきらめて、ASP.NET(aspx) の System.Web.UI.Page を継承して、HTTP メッセージをSOAP ごとゴッソリ xml ストリームで取得することにしました。
soap:Enviroment からオブジェクトクラスを作成して、XmlSerializer にかけるという、ちょっと強引な方法です。
UDDI の API ごとに自分で switch-case しないといけないので、あまりきれいじゃありません。
まだ中身を何も作ってないのですが、結構めんどくさそうです。


SOAP や UDDI の仕様的にはどうなのか?
のちほど、別に投稿しようと思います。
--

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