xml - 如何使用我的 WCF HTTP REST 服务支持带有或不带有命名空间的 XML

标签 xml wcf serialization

我有一系列看起来像这样的对象:

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/

相关文章:

java - XStream实体缩写解析

java - menuitem - 开关未显示在 ActionBar 上

c# - .NET 分布式分层应用程序

wcf - WCF 自托管应用程序可以使用 app.config 自动创建 ServiceHost 吗?

java - 我该如何反序列化?有人可以帮我做这个吗?我无法反序列化

java - Android:无法启动 Activity ComponentInfo{/com.}:android.view.InflateException:二进制 XML 文件第 6 行:膨胀类时出错

wcf - 何时使用双工服务?

json - WCF 服务速度慢 - 有选项吗?

xml - 有没有办法让 XSLT 回显支持它的 XML?

html - 什么是 HTML 实体 '&#13;' ?