我有一系列看起来像这样的对象:
namespace MyNamespace
{
[DataContract(Namespace="")]
public class MyClass1
{
[DataMember]
public string MyProperty {get;set;}
}
}
我有一个公开 WebInvoke 的方法,看起来像这样(非常简化,因为现在实际上什么都不做,但仍然适用于此测试)
[WebInvoke(UriTemplate = "", Method="POST")]
public MyNamespace.MyClass1 GetItem(MyClass1 postedItem) { return postedItem; }
我真的很希望能够接受如下所示的 XML:
<MyClass1>
<MyProperty>1</MyProperty>
</MyClass1>
或者这个:
<MyClass1 xmlns:"http://schemas.datacontract.org/2004/07/MyNamespace">
<MyProperty>1</MyProperty>
</MyClass1>
但到目前为止,我的研究似乎表明这是不可能的。我现在唯一的想法是使用 IDispatchMessageInspector 并使用消息,删除 xmlns 命名空间,然后允许 WCF 继续处理消息。然而,我在这方面运气不佳,因为一旦我使用了消息,WCF 就无法再使用它来使用和反序列化。
有没有更简单的方法?有没有更好的办法?
最佳答案
您可以使用调度程序,但是一旦您使用了消息,您需要在从方法返回之前重新创建它。下面的代码显示了它的一个例子。
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();
}
}
关于xml - 如何使用我的 WCF HTTP REST 服务支持带有或不带有命名空间的 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7506072/