如何使用我的WCF HTTP REST服务支持带或不带命名空间的XML
我有一系列看起来像这样的对象:如何使用我的WCF HTTP REST服务支持带或不带命名空间的XML,xml,wcf,serialization,Xml,Wcf,Serialization,我有一系列看起来像这样的对象: namespace MyNamespace { [DataContract(Namespace="")] public class MyClass1 { [DataMember] public string MyProperty {get;set;} } } <MyClass1> <MyProperty>1</MyProperty> </MyClass1> 我有一个公开WebI
namespace MyNamespace
{
[DataContract(Namespace="")]
public class MyClass1
{
[DataMember]
public string MyProperty {get;set;}
}
}
<MyClass1>
<MyProperty>1</MyProperty>
</MyClass1>
我有一个公开WebInvoke的方法,它看起来像这样(非常简单,因为它现在实际上什么都不做,但仍然适用于此测试)
我非常希望能够接受如下所示的XML:
namespace MyNamespace
{
[DataContract(Namespace="")]
public class MyClass1
{
[DataMember]
public string MyProperty {get;set;}
}
}
<MyClass1>
<MyProperty>1</MyProperty>
</MyClass1>
1.
或者这个:
<MyClass1 xmlns:"http://schemas.datacontract.org/2004/07/MyNamespace">
<MyProperty>1</MyProperty>
</MyClass1>
1.
但到目前为止,我的研究似乎表明这是不可能的。我现在唯一的想法是使用IDispatchMessageInspector并使用消息,删除xmlns命名空间,然后允许WCF继续处理消息。然而,我在这方面运气不太好,因为一旦我使用了消息,WCF就无法再使用它并进行反序列化
有没有更简单的方法?有更好的方法吗?您可以使用dispatcher,但是一旦您使用了消息,您需要在从该方法返回之前重新创建它。下面的代码显示了一个示例
public class StackOverflow_7506072
{
[DataContract(Name = "MyClass1", Namespace = "")]
public class MyClass1
{
[DataMember]
public string MyProperty { get; set; }
}
[ServiceContract]
public class Service
{
[WebInvoke(UriTemplate = "", Method = "POST")]
public MyClass1 GetItem(MyClass1 postedItem) { return postedItem; }
}
public class MyInspector : IEndpointBehavior, IDispatchMessageInspector
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
}
public void Validate(ServiceEndpoint endpoint)
{
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
MemoryStream ms = new MemoryStream();
XmlWriter w = XmlWriter.Create(ms);
request.WriteMessage(w);
w.Flush();
ms.Position = 0;
XElement element = XElement.Load(ms);
if (element.Name.NamespaceName == "http://schemas.datacontract.org/2004/07/MyNamespace")
{
element.Name = XName.Get(element.Name.LocalName, "");
foreach (XElement child in element.Descendants())
{
if (child.Name.NamespaceName == "http://schemas.datacontract.org/2004/07/MyNamespace")
{
child.Name = XName.Get(child.Name.LocalName, "");
}
}
element.Attribute("xmlns").Remove();
}
XmlReader r = element.CreateReader();
Message newRequest = Message.CreateMessage(r, int.MaxValue, request.Version);
newRequest.Properties.CopyProperties(request.Properties);
request = newRequest;
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(Service), new WebHttpBinding(), "");
endpoint.Behaviors.Add(new WebHttpBehavior());
endpoint.Behaviors.Add(new MyInspector());
host.Open();
Console.WriteLine("Host opened");
WebClient c = new WebClient();
c.Headers[HttpRequestHeader.ContentType] = "text/xml";
string xml = "<MyClass1><MyProperty>123</MyProperty></MyClass1>";
Console.WriteLine(c.UploadString(baseAddress + "/", xml));
c = new WebClient();
c.Headers[HttpRequestHeader.ContentType] = "text/xml";
xml = "<MyClass1 xmlns=\"http://schemas.datacontract.org/2004/07/MyNamespace\"><MyProperty>123</MyProperty></MyClass1>";
Console.WriteLine(c.UploadString(baseAddress + "/", xml));
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
公共类StackOverflow_7506072
{
[DataContract(Name=“MyClass1”,Namespace=”“)]
公共课MyClass1
{
[数据成员]
公共字符串MyProperty{get;set;}
}
[服务合同]
公务舱服务
{
[WebInvoke(UriTemplate=”,Method=“POST”)]
公共MyClass1 GetItem(MyClass1 postedItem){return postedItem;}
}
公共类MyInspector:IEndpointBehavior,IDispatchMessageInspector
{
public void AddBindingParameters(ServiceEndpoint端点、BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint端点、ClientRuntime ClientRuntime)
{
}
公共无效ApplyDispatchBehavior(ServiceEndpoint端点、EndpointDispatcher端点Dispatcher)
{
endpointDispatcher.DispatcheRuntime.MessageInspectors.Add(此);
}
公共void验证(ServiceEndpoint)
{
}
接收请求后的公共对象(ref消息请求、IClientChannel通道、InstanceContext InstanceContext)
{
MemoryStream ms=新的MemoryStream();
XmlWriter w=XmlWriter.Create(ms);
请求.书面信息(w);
w、 冲洗();
ms.Position=0;
XElement元素=XElement.荷载(ms);
如果(element.Name.NamespaceName==”http://schemas.datacontract.org/2004/07/MyNamespace")
{
element.Name=XName.Get(element.Name.LocalName,“”);
foreach(element.subjections()中的XElement子元素)
{
如果(child.Name.NamespaceName==”http://schemas.datacontract.org/2004/07/MyNamespace")
{
child.Name=XName.Get(child.Name.LocalName,“”);
}
}
element.Attribute(“xmlns”).Remove();
}
XmlReader r=element.CreateReader();
Message newRequest=Message.CreateMessage(r,int.MaxValue,request.Version);
newRequest.Properties.CopyProperties(request.Properties);
请求=新请求;
返回null;
}
SendReply之前的公共无效(参考消息回复,对象关联状态)
{
}
}
公共静态无效测试()
{
string baseAddress=“http://“+Environment.MachineName+”:8000/服务”;
ServiceHost主机=新ServiceHost(类型(服务),新Uri(基地址));
ServiceEndpoint=host.AddServiceEndpoint(typeof(Service),新的WebHttpBinding(),“”);
添加(新的WebHttpBehavior());
添加(新的MyInspector());
host.Open();
Console.WriteLine(“主机已打开”);
WebClient c=新的WebClient();
c、 标题[HttpRequestHeader.ContentType]=“text/xml”;
字符串xml=“123”;
WriteLine(c.UploadString(baseAddress+“/”,xml));
c=新的WebClient();
c、 标题[HttpRequestHeader.ContentType]=“text/xml”;
xml=“123”;
WriteLine(c.UploadString(baseAddress+“/”,xml));
控制台。写入(“按ENTER键关闭主机”);
Console.ReadLine();
host.Close();
}
}
这是一个可怕的想法。您将XML视为标准无关紧要
中的元素MyClass1
”http://schemas.datacontract.org/2004/07/MyNamespace“
名称空间与默认名称空间中的元素MyClass
不同。您还可以使用WcfRestContrib插入支持此行为的自定义XmlSerializer。使用总是完全忽略名称空间的XmlSerializer的示例如下。您需要了解如何更新XmlSerializer,以可选地支持名称空间进行反序列化。如果将服务的名称空间设置为空,则不需要传递xmlns。但您需要根xml标记与方法名匹配,即
<GetItem>
<MyClass1>
<MyProperty>1</MyProperty>
</MyClass1>
</GetItem>
1.
谢谢,这正是我需要的。我将执行你的建议。