WCF ServiceContract 名前空間にプレフィックスを追加するにはどうすればよいですか
質問
WCF で UPnP MediaServer を実装しようとしています。徐々に目標に向かって進んでいますが、今は壁にぶち当たっています。ServiceContract 名前空間にプレフィックスを追加する必要があります。現在、私には次のようなものがあります。
[ServiceContract(Namespace = "urn:schemas-upnp-org:service:ContentDirectory:1")]
public interface IContentDirectory
{
[OperationContract(Action = "urn:schemas-upnp-org:service:ContentDirectory:1#Browse")]
void Browse(string ObjectID, string BrowseFlag, string Filter, ulong StartingIndex, ulong RequestedCount, string SortCriteria, out string Result, out ulong NumberReturned, out ulong TotalMatches, out ulong UpdateID);
}
これにより、正しいソープメッセージがリッスンされます。ただし、最初に石鹸本体が必要です
<u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
WCF は現在以下をリッスンしています。
<Browse xmlns="urn:schemas-upnp-org:service:ContentDirectory:1">
そこにプレフィックスを取得するにはどうすればよいですか?関係ありますか?それともパラメータが Browse メソッドに渡されない別の理由があるのでしょうか?
アップデート追加情報は次のとおりです。次のメッセージは、実際の UPnP コントロール ポイントによって送信されます。パラメータは次のとおりです。 ない Browse メソッドに渡されます。
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://XXXXX:8731/ContentDirectory</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">urn:schemas-upnp-org:service:ContentDirectory:1#Browse</Action>
</s:Header>
<s:Body>
<u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
<ObjectID>0</ObjectID>
<BrowseFlag>BrowseDirectChildren</BrowseFlag>
<Filter>*</Filter>
<StartingIndex>0</StartingIndex>
<RequestedCount>15</RequestedCount>
<SortCriteria />
</u:Browse>
</s:Body>
</s:Envelope>
これは、WCF テスト クライアントによって生成される要求です。ここでパラメータが Browse メソッドに渡されます。
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://XXXXXX:8731/ContentDirectory</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">urn:schemas-upnp-org:service:ContentDirectory:1#Browse</Action>
</s:Header>
<s:Body>
<Browse xmlns="urn:schemas-upnp-org:service:ContentDirectory:1">
<ObjectID>0</ObjectID>
<BrowseFlag>BrowseMetadata</BrowseFlag>
<Filter>*</Filter>
<StartingIndex>0</StartingIndex>
<RequestedCount>0</RequestedCount>
<SortCriteria i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
</Browse>
</s:Body>
</s:Envelope>
解決
示した 2 つの要求 (1 つは UPnP コントロール ポイントによるもの、もう 1 つは WCF テスト クライアントによるもの) は次のとおりです。 等価ではない. 。最初の要求 (UPnP) の Browse 要素の子の名前空間は空 ("") の名前空間ですが、2 番目の要求 (WCF TC) では "urn:schemas-upnp-org:service:ContentDirectory:1" です。空のプレフィックスは、別の名前空間にバインドされていない限り、空の名前空間にバインドされ、WCF 要求ではリバウンドしますが、UPnP 要求ではリバウンドしません。
ここで、操作のパラメーターの名前空間を操作自体の名前空間と異なるものにしたい場合は、メッセージ コントラクトを使用する必要があります。これにより、WCF によって送信される要求が同等になります (モジュロ プレフィックス)。 UPnP コントロール ポイントによって送信されるリクエスト。以下のコードは、コントロール ポイントに対して示したものと同等のリクエストを生成するためにメッセージ コントラクトを定義する方法を示しています。
public class StackOverflow_2495195
{
[MessageContract(WrapperName="Browse", WrapperNamespace="urn:schemas-upnp-org:service:ContentDirectory:1", IsWrapped=true)]
public class BrowseRequest
{
[MessageBodyMember(Namespace = "", Order = 0)]
public string ObjectID;
[MessageBodyMember(Namespace = "", Order = 1)]
public string BrowseFlag;
[MessageBodyMember(Namespace = "", Order = 2)]
public string Filter;
[MessageBodyMember(Namespace = "", Order = 3)]
public ulong StartingIndex;
[MessageBodyMember(Namespace = "", Order = 4)]
public ulong RequestedCount;
[MessageBodyMember(Namespace = "", Order = 5)]
public string SortCriteria;
}
[MessageContract(WrapperName = "BrowseResponse", WrapperNamespace = "urn:schemas-upnp-org:service:ContentDirectory:1", IsWrapped = true)]
public class BrowseResponse
{
[MessageBodyMember(Namespace = "", Order = 0)]
public string Result;
[MessageBodyMember(Namespace = "", Order = 1)]
public ulong NumberReturned;
[MessageBodyMember(Namespace = "", Order = 2)]
public ulong TotalMatches;
[MessageBodyMember(Namespace = "", Order = 3)]
public ulong UpdateID;
}
[ServiceContract(Namespace = "urn:schemas-upnp-org:service:ContentDirectory:1")]
public interface IContentDirectory
{
[OperationContract(Action = "urn:schemas-upnp-org:service:ContentDirectory:1#Browse")]
//void Browse(string ObjectID, string BrowseFlag, string Filter, ulong StartingIndex, ulong RequestedCount, string SortCriteria, out string Result, out ulong NumberReturned, out ulong TotalMatches, out ulong UpdateID);
BrowseResponse Browse(BrowseRequest request);
}
public class Service : IContentDirectory
{
//public void Browse(string ObjectID, string BrowseFlag, string Filter, ulong StartingIndex, ulong RequestedCount, string SortCriteria, out string Result, out ulong NumberReturned, out ulong TotalMatches, out ulong UpdateID)
//{
// Result = null;
// NumberReturned = 0;
// TotalMatches = 0;
// UpdateID = 0;
//}
public BrowseResponse Browse(BrowseRequest request)
{
return new BrowseResponse { NumberReturned = 0, Result = null, TotalMatches = 0, UpdateID = 0 };
}
}
static Binding GetBinding()
{
return new CustomBinding(
new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, Encoding.UTF8),
new HttpTransportBindingElement());
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IContentDirectory), GetBinding(), "");
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
host.Open();
Console.WriteLine("Host opened");
ChannelFactory<IContentDirectory> factory = new ChannelFactory<IContentDirectory>(GetBinding(), new EndpointAddress(baseAddress));
IContentDirectory proxy = factory.CreateChannel();
//string result;
//ulong ul1, ul2, ul3;
//proxy.Browse(null, null, null, 0, 0, null, out result, out ul1, out ul2, out ul3);
proxy.Browse(new BrowseRequest { BrowseFlag = null, Filter = null, ObjectID = null, RequestedCount = 0, SortCriteria = null, StartingIndex = 0 });
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
これで、WCF によって送信される要求は XML と同等になりますが、プレフィックスは依然として異なります。John Saunders 氏が述べたように、それは重要ではないため、WCF メッセージに書き込まれる要素のプレフィックスを設定できる単純なノブは WCF にはありません。ただし、カスタム エンコーダーを使用すると、まさにそれを行うことができます。少し前にそれについて投稿しました http://blogs.msdn.com/b/carlosfigueira/archive/2010/06/13/changing-prefixes-in-xml-responses.aspx - この例を使用して、プレフィックスを期待どおりに設定するカスタム エンコーダーを作成できます。
他のヒント
なぜあなたは、特定の接頭辞が必要なのでしょうか?あなたは、プレフィックスに依存し、いくつかのソフトウェアを使用していますか?
それがそうなら、、その後、ソフトウェアが壊れています。あなたが与えてくれた2「のxmlns」の例は、これまでXMLを懸念していると同じです。違いを気がひどく破壊され、XMLを学ぶために必要されていること。
すべてのソフトウェア