【问题标题】:Using complex objects via a Web Service from Powershell?通过 Powershell 的 Web 服务使用复杂对象?
【发布时间】:2015-09-17 05:11:50
【问题描述】:

我一直在尝试通过 Powershell 使用供应商提供的 Web 服务系统(我正在运行 4.0)。 以下是我用来设置代理以使用服务的代码:

$uri = http://somehost.employer.net:9999/AdministrationService?wsdl
$webSvc = New-WebServiceProxy -Uri $uri -namespace WebServiceProxy -Credential $TestCreds_NonPriv

目前,我对服务公开的两种方法感兴趣,“SaveAttributes”和“GetAllAttributes”, wsdl 定义如下:

  <xsd:element name="SaveAttributes">
   <xsd:complexType>
    <xsd:sequence>
     <xsd:element minOccurs="0" name="Id" nillable="true" type="xsd:string"/>
     <xsd:element minOccurs="0" name="attributes" nillable="true" type="q5:ArrayOfKeyValueOfstringstring"/>
    </xsd:sequence>
   </xsd:complexType>
  </xsd:element>

  <xsd:element name="GetAllAttributes">
   <xsd:complexType>
    <xsd:sequence>
     <xsd:element minOccurs="0" name="Id" nillable="true" type="xsd:string"/>
    </xsd:sequence>
   </xsd:complexType>
  </xsd:element>

  <xsd:element name="GetAllAttributesResponse">
   <xsd:complexType>
    <xsd:sequence>
     <xsd:element minOccurs="0" name="GetAllAttributesResult" nillable="true" type="q2:ArrayOfKeyValueOfstringstring"/>
    </xsd:sequence>
   </xsd:complexType>
  </xsd:element>

我已通过以下方式成功使用 GetAllAttributes 函数:

$websvc.GetAllAttributes('someid')

这会返回一个对象,它是一个键值对数组,如下所示:

Key         Value
---         -----
ID          01
PERSONA     godeater@stackoverflow.com
NAME        GodEater's real name

如果我想在 Web 服务上创建一个新对象,我必须调用“SaveAttributes”函数 两个参数,一个作为字符串的新“ID”和一个用于其余属性的键/值对数组, 这就是我难过的地方。我无法创建成功序列化的 powershell 对象 到服务。我尝试的是这样的:

[WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring[]]$newentity = @(
    @{Key='PERSONA';Value='someone_else@stackoverflow.com'},
    @{Key='NAME';Value='Someone Elses Real Name'}
  )
$WebSvc.SaveAttributes('02',$newentity)

但我得到的是这个相当令人困惑的错误:

Cannot convert argument "attributes", with value: "WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring[]", for "SaveAttributes" to type
  "WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring[]": "Cannot convert the "WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring" value of type
  "WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring" to type "WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring"."
  At line:1 char:1
  + $WebSvc.SaveAttributes('02',$newentity)
  + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

现在,看看 GetAllAttributes 返回给我的内容,它应该是与我相同的对象 尝试输入 SaveAttributes 方法的“属性”参数,它似乎稍微序列化 与我自己构建的对象不同。

序列化时 GetAllAttributes 的结果:

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
    <Obj RefId="0">
      <TN RefId="0">
        <T>WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring[]</T>
        <T>System.Array</T>
        <T>System.Object</T>
      </TN>
      <LST>
        <Obj RefId="1">
          <TN RefId="1">
            <T>WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring</T>
            <T>System.Object</T>
          </TN>
          <ToString>WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring</ToString>
          <Props>
            <S N="Key">ID</S>
            <S N="Value">01</S>
          </Props>
        </Obj>
        <Obj RefId="2">
          <TNRef RefId="1" />
          <ToString>WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring</ToString>
          <Props>
            <S N="Key">PERSONA</S>
            <S N="Value">godeater@stackoverflow.com</S>
          </Props>
        </Obj>
        <Obj RefId="3">
          <TNRef RefId="1" />
          <ToString>WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring</ToString>
          <Props>
            <S N="Key">NAME</S>
            <S N="Value">GodEater's real name</S>
          </Props>
        </Obj>
      </LST>
    </Obj>
  </Objs>

虽然我创建的对象序列化为此:

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
    <Obj RefId="0">
      <TN RefId="0">
        <T>System.Collections.Hashtable</T>
        <T>System.Object</T>
      </TN>
      <DCT>
        <En>
          <S N="Key">PERSONA</S>
          <S N="Value"></S>
        </En>
      </DCT>
    </Obj>
  </Objs>
  <Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
    <Obj RefId="0">
      <TN RefId="0">
        <T>System.Collections.Hashtable</T>
        <T>System.Object</T>
      </TN>
      <DCT>
        <En>
          <S N="Key">NAME</S>
          <S N="Value">Someone Elses Real Name</S>
        </En>
      </DCT>
    </Obj>
  </Objs>

这似乎缺乏对数组成员的环绕,而是似乎 将数组中的每个项目作为独立对象。

有人有什么想法吗?

【问题讨论】:

    标签: arrays web-services powershell


    【解决方案1】:

    在 Powershell 中将复杂的自定义类型传递给 Web 服务方法似乎是一个常见问题。 在这里,他们建议将“-Class”参数添加到 New-WebServiceProxy: https://groups.google.com/forum/#!msg/microsoft.public.windows.powershell/JWB5yueLtrg/k0zeUUxAkTMJ

    在我的情况下它没有帮助 - 似乎这个解决方案也不稳定。 我终于不得不使用自动生成的命名空间来避免这个问题。

    Web 服务代理应该在没有命名空间的情况下创建:

    $webSvc = New-WebServiceProxy -Uri $uri
    

    然后你在自动生成的命名空间中创建你的数组:

            $newentity = New-Object -TypeName ($webSvc.GetType().Namespace + '.ArrayOfKeyValueOfstringstringKeyValueOfstringstring[]') -ArgumentList 2
            $newentity[0] = New-Object -TypeName ($webSvc.GetType().Namespace + '.ArrayOfKeyValueOfstringstringKeyValueOfstringstring')
            $newentity[0].Key  = 'key0'
            $newentity[0].Value = 'value0'
    
            $newentity[1] = New-Object -TypeName ($webSvc.GetType().Namespace + '.ArrayOfKeyValueOfstringstringKeyValueOfstringstring')
            $newentity[1].Key = 'key1'
            $newentity[1].Value = 'value1'
    
            $WebSvc.SaveAttributes('02',$newentity)
    

    看起来很笨拙,但至少它对我有用。

    【讨论】:

    • 这看起来类似于 beatcracker 的解决方案,不同之处在于他使用循环将键/值对作为服务所需类型的显式实例。我选择了他的回答 - 但感谢您抽出宝贵时间回答。
    【解决方案2】:

    尝试强制键/值对为WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring 类型:

    $Properties = @(
        @{Key='PERSONA';Value='someone_else@stackoverflow.com'},
        @{Key='NAME';Value='Someone Elses Real Name'}
    )
    
    [WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring[]]$newentity = $Properties | ForEach-Object {
        New-Object -TypeName 'WebServiceProxy.ArrayOfKeyValueOfstringstringKeyValueOfstringstring' -Property $_
    }
    
    $WebSvc.SaveAttributes('02',$newentity)
    

    【讨论】:

    • 这非常有效。我不知道为什么你必须这样做——但在这一点上我不在乎——我只需要它工作!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    • 1970-01-01
    • 2012-12-19
    相关资源
    最近更新 更多