【问题标题】:passing collection or array type input parameter wcf service传递集合或数组类型输入参数 wcf 服务
【发布时间】:2011-06-14 05:03:36
【问题描述】:

我编写了一个 WCf 服务,它有一个 Collection 类型的输入主体参数和另一个参数作为查询字符串,如下所示:

[WebInvoke(Method = "PUT", UriTemplate = "users/role/{userID}",BodyStyle=WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
public bool AssignUserRole(int userID,Collection<int> roleIDs)
{
    //do something
    return restult;
}

现在,当我尝试传递此参数时,我遇到了反序列化错误。我尝试了以下格式:

<AssignUserRole xmlns="http://tempuri.org/">
 <roleIDs>
  <roleID>7</roleID>
 </roleIDs>
</AssignUserRole>

<AssignUserRole xmlns="http://tempuri.org/">
 <ArrayOfroleID>
  <roleID>7</roleID>
 </ArrayOfroleID>
</AssignUserRole>

<AssignUserRole xmlns="http://tempuri.org/">
 <ArrayOfint> 
  <int>7</int>
 </ArrayOfint>
</AssignUserRole>

有人可以帮我如何传递这个数组(集合类型正文参数)吗?

谢谢。

【问题讨论】:

    标签: wcf rest parameter-passing webinvoke


    【解决方案1】:

    正确的格式是这样的:

    <AssignUserRole xmlns="http://tempuri.org/">
      <roleIDs xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">     
        <a:int>7</a:int>
        <a:int>8</a:int>
      </roleIDs>
    </AssignUserRole>
    

    找出特定操作的预期格式的一种简单方法是使用具有相同合同的 WCF 客户端,使用它发送消息并使用 Fiddler 查看操作。下面的程序就是这样做的。

    public class StackOverflow_6339286
    {
        [ServiceContract]
        public interface ITest
        {
            [WebInvoke(Method = "PUT", UriTemplate = "users/role/{userID}", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
            [OperationContract]
            bool AssignUserRole(string userID, Collection<int> roleIDs);
        }
        public class Service : ITest
        {
            public bool AssignUserRole(string userID, Collection<int> roleIDs)
            {
                return true;
            }
        }
        public static void Test()
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
            host.Open();
            Console.WriteLine("Host opened");
    
            WebChannelFactory<ITest> factory = new WebChannelFactory<ITest>(new Uri(baseAddress));
            ITest proxy = factory.CreateChannel();
    
            proxy.AssignUserRole("1234", new Collection<int> { 1, 2, 3, 4 });
    
            ((IClientChannel)proxy).Close();
            factory.Close();
    
            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }
    

    还要注意 UriTemplate 中存在问题:路径变量 {userId} 不能是 int 类型(它必须是字符串)。这在上面的示例代码中得到了修复。

    还有一点:如果您不想为集合/数组使用默认命名空间,您可以使用[CollectionDataContract] 类来更改它。如果您使用下面的类而不是使用 Collection,那么您尝试的第一个主体应该可以工作:

    [CollectionDataContract(Namespace = "http://tempuri.org/", ItemName = "roleID")]
    public class MyCollection : Collection<int> { }
    

    【讨论】:

    • 嗨 carlosfigueira,我也试过这个,但没有用。我收到异常“无法使用 DataContractSerializer 反序列化具有根名称 'AssignUserRole' 和根命名空间 'tempuri.org' 的 XML 正文(用于操作 'AssignUserRole' 和合同('IRoleService','tempuri.org/'))。确保类型对应的 XML 被添加到服务的已知类型集合中。”
    • 我建议你按照我在我拥有的代码中所做的事情(效果很好,你可以尝试运行它) - 使用 WCF 创建一个客户端使用相同的合同 i>(这很重要),调用服务并查看客户端发送的内容。这应该让您了解需要更改的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 2011-10-10
    • 2014-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多