As already described on elsewhere on the Internet and on Microsoft Connect, the new Invoke-WebRequest Cmdlet, that comes with PowerShell v3, handles form fields incorrectly.
Instead of referring to the name attributes of input elements within a form the Fields Collection stores the ids of the attributes under the ‘key’ property. As in the following example you see the text input field has an id ‘idTextField’ and a name Attribute ‘frmTextField’:
<input id="idTextField" name="frmTextField" type="text" />
The corresponding Fields collection might then (incorrectly) look like this:
$WebResponse = Invoke-WebRequest -Uri 'http://example.com/someForm.html'; $WebResponse.Forms[1].Fields Key Value --- ----- idTextField Some Text
The problem occurs when you later try to send the form back to the web server as the ids of the elements get transferred instead of the form names. The web server then will probably not recognise the data you sent.
There is a Workaround by manually converting the form fields to their proper names:
function ConvertTo-InputIdFromFieldName($wr, $string) { return ($wr.InputFields | Where { $_.name -eq $string }).id; } function ConvertTo-FieldNameInputIdFrom($wr, $string) { return ($wr.InputFields | Where { $_.id -eq $string }).name; } $f = $wr.Forms.Item('SomeForm'); $ht = @{}; foreach($field in $f.Fields.GetEnumerator()) { $fieldName = $null; $fieldName = ConvertTo-FieldNameInputIdFrom $wr $field.Key; "{0}`t{1}`t{2}" -f $field.Key, $fieldName, $field.Value; if($fieldName) { $ht.Add($fieldName, $field.Value); } } # foreach $f.Fields.Clear(); foreach($e in $ht.GetEnumerator()) { #if($f.Fields.Contains($e.Name) { $f.Fields.Remove($e.Name); } $f.Fields.Add($e.Name, $e.Value); } # foreach
You can then send the request as usual to the web server:
$WebResponse = Invoke-WebRequest -Uri ("http://exameple.com/{0}" -f $f.Action) -Method $f.Method -Body $f.Fields;