Передача входного параметра коллекции или типа массива wcf service - PullRequest
2 голосов
/ 14 июня 2011

Я написал службу 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;
}

Теперь, когда я пытаюсь передать этот параметр, я получаю ошибку de serialization,Я пробовал следующий формат:

<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>

Может ли кто-нибудь помочь мне, как я могу передать этот массив (параметр типа тела коллекции)?

Спасибо.

1 Ответ

2 голосов
/ 14 июня 2011

Правильный формат был бы такой:

<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> { }
...