Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用我的WCF HTTP REST服务支持带或不带命名空间的XML_Xml_Wcf_Serialization - Fatal编程技术网

如何使用我的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.

谢谢,这正是我需要的。我将执行你的建议。