PoshCode Logo PowerShell Code Repository

New-ODataServiceProxy by Joel Bennett 18 months ago (modification of post by Joel Bennett view diff)
View followups from Joel Bennett | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/2043"></script>download | new post

A wrapper for DataSvcUtil to generate web service proxies in-memory for OData services like NetFlix (which are not handled correctly by PowerShell’s built-in New-WebServiceProxy).

Also includes a type cache, because if you call it again with the same url it was throwing an error. NOTE: calling it with the same URL will generate a NEW context object (this is important to know if you start really working with this — we’re not caching the context, just the type information).

This release fixed a minor compile issue if your host is reporting $PSVersionTable.CLRVersion.Major is 4 ;-)

REQUIRES AT LEAST .Net 3.5 SP1 with the Data Services Update for Windows 7/2008 R2 or Windows XP/Vista/Server 2003/2008

Note that this ships in the box with .Net Framework 4, but unless you’ve modified PoweShell ISE’s app.config, or are using PoshConsole, you can’t really use that, so you’ll need the latest 3.5 SP1 plus the Data Services Update.

  1. function New-ODataServiceProxy {
  2. #.Synopsis
  3. #  Creates a proxy class for an odata web service
  4. #  YOU NEED TO BE VERY CAREFUL NOT TO OUTPUT THE PROXY OBJECT TO THE POWERSHELL HOST!
  5. #.Description
  6. #  Uses the data service client utility (DataSvcUtil.exe) to generate a proxy class (and types for all objects) for an OData web service.
  7. #  WARNING: Outputting this object to the PowerShell host will result in queriying all the object collections on the service.
  8. #.Parameter URI
  9. #  The URI for the web service
  10. #.Parameter Passthru
  11. #  Causes the method to output all of the types defined by the service metadata as well as the actual service object.
  12. #.Example
  13. #  $proxy = New-ODataServiceProxy http://odata.netflix.com/Catalog/
  14. #  $AdventuresInOdyssey = $proxy.Titles.AddQueryOption('$filter',"substringof('Adventures in Odyssey',Name)")
  15. #  $AdventuresInOdyssey | Format-List Name, ReleaseYear, Url, Synopsis
  16. #.Example
  17. # function Get-Films {
  18. # param($Name)
  19. #    $proxy = New-ODataServiceProxy http://odata.netflix.com/Catalog/
  20. #    if($Name -match "\*") {
  21. #       $sName = $Name -replace "\*"
  22. #       # Note the substring PLUS a Where -like filter to pull off wildcard matching which isn't supported by NetFlix
  23. #       $Global:Films = $proxy.Titles.AddQueryOption('$filter',"substringof('$sName',Name)") | Where { $_.Name -like $Name }
  24. #    } else {
  25. #       $Global:Films = $proxy.Titles.AddQueryOption('$filter',"'$Name' eq Name")
  26. #    }
  27. #    $Films | Format-List Name, ReleaseYear, AverageRating, Url, Synopsis
  28. #    Write-Host "NOTE: This data is cached in `$Films" -Fore Yellow
  29. # }
  30. #
  31. # C:\PS>Get-Films Salt
  32. #
  33. #.Link http://msdn.microsoft.com/en-us/library/ee383989.aspx
  34. #.Notes
  35. #  I can't stress enough that you should not output the object or any property that returns a System.Data.Services.Client.DataServiceQuery[T] without a filter unless you're sure that's what you want.
  36. #
  37. #  ADO.NET Data Service Client Utility http://msdn.microsoft.com/en-us/library/ee383989.aspx
  38. #  AddQueryOption http://msdn.microsoft.com/en-us/library/cc646860.aspx
  39. #  NetFlix Catalog http://developer.netflix.com/docs/oData_Catalog
  40. #  Data Services Update for .Net 3.5 SP1 http://support.microsoft.com/kb/982307
  41. #
  42. #  VERSION HISTORY:
  43. #  v1.0    - 2010 Aug 02 - First Version http://poshcode.org/2039
  44. #  v1.1    - 2010 Aug 03 - Simple Caching http://poshcode.org/2040
  45. #          - Added a type cache to make it easier to find proxies you've already compiled (because we can't recompile them)
  46. #  v1.2    - 2010 Aug 03 - Examples
  47. #          - Added additional examples
  48. #  v1.3    - 2010 Aug 03 - This Version
  49. #          - Removed the -Language parameter from Add-Type when on .Net4 (setting it explicitly results in downgrading to 3, and having multiple assembly references!?)
  50. param( $URI = "http://odata.netflix.com/Catalog/", [switch]$Passthru )
  51.  
  52. if(!(Test-Path Variable::Global:ODataServices)){
  53.    ## You can only use this on .Net 4 or .Net 3.5 SP1
  54.    ## For .Net 3.5 SP1 you need to download http://support.microsoft.com/kb/982307
  55.    ## If you don't have it, this won't succeed
  56.    [Reflection.Assembly]::Load("System.Data.Services.Client, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") | Out-Null
  57.    $global:ODataServices = @{}
  58. }
  59.  
  60. $normalized = ([uri]$URI).AbsoluteUri.TrimEnd("/")
  61.  
  62. if($global:ODataServices.ContainsKey($normalized)) {
  63.    New-Object $global:ODataServices.$normalized.ContextType $URI
  64.    if($Passthru) {
  65.       $global:ODataServices.$normalized.OtherTypes
  66.    }
  67.    return
  68. }
  69.  
  70. ## Find the right DataSvcUtil for this version of .Net
  71. switch($PSVersionTable.ClrVersion.Major) {
  72.    4 { # PoshConsole and modded .Net4 PowerShell_ISE etc.
  73.       Set-Alias Get-ODataServiceDefinition (Get-ChildItem ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory())  DataSvcUtil.exe)
  74.       break
  75.    }
  76.    2 { # PowerShell.exe and everyone else
  77.       $FrameworkPath = [System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory() | Split-Path
  78.       Set-Alias Get-ODataServiceDefinition (Get-ChildItem $FrameworkPath\v3.5\DataSvcUtil.exe)
  79.       break
  80.    }
  81.    default { throw "The script is out of date, please fix it and upload a new one to PoshCode!" }  
  82. }
  83. ## Get the service definition into a string via a temp file
  84. $temp = [IO.Path]::GetTempFileName()
  85. Get-ODataServiceDefinition -out:$temp -uri:$URI -nologo | Out-Null
  86. $code = @(Get-Content $temp) -join "`n" # -Delim ([char]0)
  87. Remove-Item $temp
  88.  
  89. switch($PSVersionTable.ClrVersion.Major) {
  90.    4 {
  91.          $Types = Add-Type $code -Reference "System.Data.Services.Client, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.Core" -Passthru
  92.    }
  93.    2 {
  94.          $Types = Add-Type $code -Reference "System.Data.Services.Client, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" -Passthru -Language CSharpVersion3
  95.    }
  96.    default { throw "The script is out of date, please fix it and upload a new one to PoshCode!" }  
  97. }
  98.  
  99. if(!$Types) { return }
  100.  
  101. $ContextType = $Types | Where-Object { $_.BaseType -eq [System.Data.Services.Client.DataServiceContext] }
  102. $global:ODataServices.$normalized = New-Object PSObject -Property @{ContextType=$ContextType; OtherTypes=$([Type[]]($Types|Where-Object{$_.BaseType -ne [System.Data.Services.Client.DataServiceContext]}))}
  103. $ctx = new-object $ContextType $URI
  104. Write-Output $ctx
  105. if($Passthru) { Write-Output $types }
  106. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me