问题描述
我想在WCF实现一个的UPnP媒体服务器。我慢慢变有,但现在我已经撞南墙。我需要添加一个前缀的的ServiceContract命名空间。现在,我有以下几点:
[的ServiceContract(命名空间=瓮:架构 - UPnP的组织:服务:内容目录:1 )]
公共接口IContentDirectory
{
[OperationContract的(动作=瓮:架构 - UPnP的组织:服务:内容目录:1#浏览)]
无效浏览(字符串对象ID,字符串BrowseFlag,串过滤,ULONG StartingIndex,ULONG RequestedCount,串SortCriteria,串出结果,出ULONG NumberReturned,出ULONG TotalMatches,出ULONG UpdateID);
}
这听正确的肥皂消息。不过,我需要皂体开始与
< U:浏览的xmlns:U =瓮:架构 - 的UPnP -org:服务:内容目录:1>
和WCF现在听:
<浏览的xmlns =瓮:架构 - UPnP的组织:服务:内容目录:1>
我怎么前缀呢?有关系吗? ?或者是有原因的参数不传递到浏览方法的另一个原因
更新
下面是一些额外的信息:以下消息由一个实UPnP控制点发送。该参数的不可以传递到浏览方法
< S:信封小号:encodingStyle的= http://schemas.xmlsoap.org/soap/encoding/的xmlns:S =http://schemas.xmlsoap.org/soap/envelope/>
< S:页眉和GT;
<到S:的mustUnderstand =1的xmlns =http://schemas.microsoft.com/ws/2005/05/addressing/none>的http:// XXXXX:8731 /内容目录< /到大于
<的Action:mustUnderstand属性=1的xmlns =http://schemas.microsoft.com/ws/2005/05/addressing/none>金塔:架构 - UPnP的组织:服务:内容目录:1#浏览< /作用>
< / S:页眉和GT;
< S:身体与GT;
< U:浏览的xmlns:U =瓮:架构 - UPnP的组织:服务:内容目录:1>
<对象ID> 0℃; /对象ID>
< BrowseFlag> BrowseDirectChildren< / BrowseFlag>
<滤光器> * LT; /滤光器>
将; StartingIndex大于0&下; / StartingIndex>
将; RequestedCount→15&下; / RequestedCount>
< SortCriteria />
< / U:浏览>
< / S:身体与GT;
< / S:信封>
这是一个由WCF测试客户端产生的请求。现在,参数传递到浏览方式:
< S:信封的xmlns:S =HTTP://模式。 xmlsoap.org/soap/envelope/\">
< S:页眉和GT;
<到S:的mustUnderstand =1的xmlns =http://schemas.microsoft.com/ws/2005/05/addressing/none>的http:// XXXXXX:8731 /内容目录< /到大于
<的Action:mustUnderstand属性=1的xmlns =http://schemas.microsoft.com/ws/2005/05/addressing/none>金塔:架构 - UPnP的组织:服务:内容目录:1#浏览< /作用>
< / S:页眉和GT;
< S:身体与GT;
<浏览的xmlns =瓮:架构 - UPnP的组织:服务:内容目录:1>
<对象ID> 0℃; /对象ID>
< BrowseFlag> BrowseMetadata< / BrowseFlag>
<滤光器> * LT; /滤光器>
将; StartingIndex大于0&下; / StartingIndex>
将; RequestedCount大于0&下; / RequestedCount>
< SortCriteria我:无=真的xmlns:I =http://www.w3.org/2001/XMLSchema-instance/>
< /浏览>
< / S:身体与GT;
< / S:信封>
这两个要求,你表现(一个由UPnP控制点和一个通过WCF测试客户端)的不等于。在第一(UPnP)的浏览元素的子元素的名称空间是空的()命名空间,而在第二个请求(WCF TC),它的瓮:架构 - UPnP的组织:服务:内容目录:1 - 空前缀被绑定到空的命名空间,除非它绑定到另一个命名空间,它在WCF请求,但没有对UPnP的一个篮板。
现在,如果你想操作的参数的名称空间会比手术本身的命名不同,你必须使用一个消息合同 - 这会得到通过WCF发送的请求是等价的(模前缀)被发送的请求UPnP控制点。下面的代码演示了如何留言合同将被定义生成请求相当于一个你表现出对控制点。
公共类StackOverflow_2495195
{
[MessageContract(WrapperName =浏览,WrapperNamespace =瓮:架构 - UPnP的组织:服务:内容目录:1,IsWrapped = TRUE)]
公共类BrowseRequest
{
[MessageBodyMember(命名空间=,令= 0)
公共字符串对象ID;
[MessageBodyMember(命名空间=,令= 1)]
公共字符串BrowseFlag;
[MessageBodyMember(命名空间=,令= 2)]
公共字符串过滤器;
[MessageBodyMember(命名空间=,令= 3)
公共ULONG StartingIndex;
[MessageBodyMember(命名空间=,令= 4)]
公共ULONG RequestedCount;
[MessageBodyMember(命名空间=,令= 5)]
公共字符串SortCriteria;
}
[MessageContract(WrapperName =BrowseResponse,WrapperNamespace =瓮:架构 - UPnP的组织:服务:内容目录:1,IsWrapped = TRUE)]
公类BrowseResponse
{
[MessageBodyMember(命名空间=,令= 0)
公共字符串结果;
[MessageBodyMember(命名空间=,令= 1)]
公共ULONG NumberReturned;
[MessageBodyMember(命名空间=,令= 2)]
公共ULONG TotalMatches;
[MessageBodyMember(命名空间=,令= 3)
公共ULONG UpdateID;
}
[的ServiceContract(命名空间=瓮:架构 - UPnP的组织:服务:内容目录:1)]
公共接口IContentDirectory
{
〔OperationContract的(动作=瓮:架构 - UPnP的组织:服务:内容目录:1#浏览)]
//无效浏览(字符串对象ID,字符串BrowseFlag,串过滤,ULONG StartingIndex,ULONG RequestedCount,串SortCriteria,串出结果,出ULONG NumberReturned,出ULONG TotalMatches,出ULONG UpdateID);
BrowseResponse浏览(BrowseRequest要求);
}
公共类服务:IContentDirectory
{
//公共无效浏览(字符串对象ID,字符串BrowseFlag,串过滤,ULONG StartingIndex,ULONG RequestedCount,串SortCriteria,出字符串结果,出ULONG NumberReturned,出ULONG TotalMatches,出ULONG UpdateID)
// {
//结果= NULL;
// NumberReturned = 0;
// TotalMatches = 0;
// UpdateID = 0;
//}
公共BrowseResponse浏览(BrowseRequest要求)
{
返回新BrowseResponse {NumberReturned = 0,结果= NULL,TotalMatches = 0,UpdateID = 0};
}
}
静态绑定GetBinding()
{
返回新CustomBinding(
新TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10,Encoding.UTF8),
新HttpTransportBindingElement());
}
公共静态无效测试()
{
串baseAddress =HTTP://+ Environment.MachineName +:8000 /服务;
ServiceHost的主机=新的ServiceHost(typeof运算(服务),新的URI(baseAddress));
host.AddServiceEndpoint(typeof运算(IContentDirectory),GetBinding(),);
host.Description.Behaviors.Add(新的ServiceMetadataBehavior {HttpGetEnabled =真});
host.Open();
Console.WriteLine(主机开);
&的ChannelFactory LT; IContentDirectory>厂=新的ChannelFactory< IContentDirectory>(GetBinding(),新的EndpointAddress(baseAddress));
IContentDirectory代理= factory.CreateChannel();
//字符串结果;
// ULONG UL1,UL2,UL3;
//proxy.Browse(null,NULL,NULL,0,0,空,出结果,出UL1,UL2出来,出来UL3);
proxy.Browse(新BrowseRequest {BrowseFlag = NULL,过滤器= NULL,对象ID = NULL,RequestedCount = 0,SortCriteria = NULL,StartingIndex = 0});
((IClientChannel)代理).Close();
factory.Close();
Console.Write(按ENTER关闭主机);
到Console.ReadLine();
host.Close();
}
}
现在,由WCF发送的请求是XML当量的其他,但是前缀仍然不同。这正如约翰·桑德斯提到的,它不应该的问题,所以有没有简单的旋钮,WCF,让您为写在WCF消息中的元素的前缀。你可以,但是,使用自定义的编码来这样做。我张贴关于它的,而回的 - 你可以用这个例子来创建自定义编码器,将前缀设置为你所期望的那样。
I'm trying to implement an UPnP MediaServer in WCF. I'm slowly getting there, but now I've hit a brick wall. I need to add a prefix to the ServiceContract namespace. Right now I have the following:
[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);
}
This listens to the correct soap-messages. However, I need the soap-body to begin with
<u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
and WCF is now listening to:
<Browse xmlns="urn:schemas-upnp-org:service:ContentDirectory:1">
How do I get the prefix there? Does it matter? Or is there another reason why the parameters are not passed into the Browse method?
UPDATEHere's some extra info: The following message is sent by a real UPnP control point. The parameters are not passed into the Browse method.
<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>
This is the request that is generated by the WCF test client. Now the parameters are passed into the Browse method:
<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>
The two requests which you showed (one by the UPnP control point and one by the WCF Test Client) are not equivalent. The namespace of the children of the Browse element in the first (UPnP) is the empty ("") namespace, while in the second request (WCF TC) it's "urn:schemas-upnp-org:service:ContentDirectory:1" - the empty prefix is bound to the empty namespace unless it's bound to another namespace, and it's rebound in the WCF request but not on the UPnP one.
Now, if you want the namespace of the parameters of an operation to be different than the namespace of the operation itself, you'll have to use a message contract - that'll get the request sent by WCF to be equivalent (modulo prefixes) to the request sent by the UPnP control point. The code below shows how a message contract would be defined to generate a request equivalent to the one you showed for the control point.
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();
}
}
Now, the request that is sent by WCF is XML-equivalent, but the prefixes are still different. It As John Saunders mentioned, it shouldn't matter, so there's no simple knob in WCF to let you set the prefix for the elements written in the WCF messages. You can, however, use a custom encoder to do exactly that. I posted about it a while back at http://blogs.msdn.com/b/carlosfigueira/archive/2010/06/13/changing-prefixes-in-xml-responses.aspx - you can use that example to create a custom encoder which will set the prefixes to what you expect them to be.
这篇关于我如何添加一个前缀一个WCF的ServiceContract命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!