如何使用 WCF HTTP REST 服务支持带或不带命名空间的 XML [英] How can I support XML with or without namespace, with my WCF HTTP REST service

查看:24
本文介绍了如何使用 WCF HTTP REST 服务支持带或不带命名空间的 XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a series of objects that look like this:

namespace MyNamespace
{
  [DataContract(Namespace="")]
  public class MyClass1
  {
    [DataMember]
    public string MyProperty {get;set;}
  }
}

我有一个方法可以公开看起来像这样的 WebInvoke(非常简化,因为它现在实际上什么都不做,但仍然适用于这个测试)

I have a method which exposes the WebInvoke that looks like this (very simplified as this actually does nothing right now, but still works for this test)

[WebInvoke(UriTemplate = "", Method="POST")]
public MyNamespace.MyClass1 GetItem(MyClass1 postedItem) { return postedItem; }

我真的希望能够接受如下所示的 XML:

I would really like to be able to accept XML that looks like this:

<MyClass1>
  <MyProperty>1</MyProperty>
</MyClass1>

或者这个:

<MyClass1 xmlns:"http://schemas.datacontract.org/2004/07/MyNamespace">
  <MyProperty>1</MyProperty>
</MyClass1>

但到目前为止,我的研究似乎表明这是不可能的.我现在唯一的想法是使用 IDispatchMessageInspector 并使用消息,删除 xmlns 命名空间,然后允许 WCF 继续处理消息.然而,我对此并不走运,因为一旦我使用了消息,WCF 就不再可以使用和反序列化了.

But so far my research seems to indicate this is not possible. My only idea right now is to use a IDispatchMessageInspector and consume the message, remove the xmlns namespace, and then allow WCF to continue processing the message. I have not had a lot of luck with this however, because once I consume the message it is no longer available for WCF to consume and deserialize.

有更简单的方法吗?有没有更好的办法?

Is there an easier way? Is there a better way?

推荐答案

您可以使用调度程序,但是一旦您使用了消息,您将需要在从方法返回之前重新创建它.下面的代码显示了一个例子.

You can use the dispatcher, but once you consume the message, you'll need to recreate it before returning from the method. The code below shows an example of it.

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();
    }
}

这篇关于如何使用 WCF HTTP REST 服务支持带或不带命名空间的 XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆