Body is not deserialize from powershell call - powershell

I have an error with powershell api call.
This is my powershell code :
$body='[{"Criteres":[{"Nom":"Code","Valeur":"lyon"},{"Nom":"Libellé","Valeur":"lyon test"}],"Nom":"X_Site_Geogr","Pseudo":"Site Géographique"}]'
$url="http://localhost/api/OccObjets/"
$Responseappli = Invoke-WebRequest -URI $url -Method "PUT" -Body $body -ContentType "text/json" -UseDefaultCredentials
Write-Output $Responseappli.Content
This is controller method :
[HttpPut]
public IHttpActionResult Put([FromBody] IEnumerable<TOObjetAvecCriteres> listeOccurrence)
If i use the same body on Postman or swagger, it works perfectly but with powershell, my list is null.
I add a handler to get raw body with that :
var bodyStream = new StreamReader(HttpContext.Current.Request.InputStream);
bodyStream.BaseStream.Seek(0, SeekOrigin.Begin);
var bodyText = bodyStream.ReadToEnd();
var test = JsonConvert.DeserializeObject<IEnumerable<TOObjetAvecCriteres>>(bodyText);
body powershell :
"[{\"Criteres\":[{\"Nom\":\"Code\",\"Valeur\":\"lyon\"},{\"Nom\":\"Libell�\",\"Valeur\":\"lyon test\"}],\"Nom\":\"X_Site_Geogr\",\"Pseudo\":\"Site G�ographique\"}]"
body swagger :
"[{\"Criteres\":[{\"Nom\": \"Code\",\"Valeur\": \"lyon\"},{\"Nom\": \"Libellé\",\"Valeur\": \"lyon test\"}],\"Nom\": \"X_Site_Geogr\",\"Pseudo\": \"Site Géographique\"}]"
Deserialization in handler works whith both powershell and swagger but in my controller function, listeOccurrence variable is null with powershell.
I aslo try to write body like this an convert to json but it doesn't work :
$body=#(
#{
"Nom"="X_Site_Geogr"
"Pseudo"="Site Géographique"
"Criteres"= #(
#{
"Nom"="Code"
"Valeur"="lyon"
}
#{
"Nom"="Libellé"
"Valeur"="lyon test2"
}
)
}
)
Do you have any idea ?
Thanks for your help

Related

Purview API Create glossary terms

I am trying to reference the following page
https://learn.microsoft.com/en-us/rest/api/purview/catalogdataplane/glossary/create-glossary-term?tabs=HTTP
$glossarytermcreateendpoint = 'https://pv-chn-asiabi-sea-dev.purview.azure.com/catalog/api/atlas/v2/glossary'
$Glossaryterm = #{
qualifiedName = "sample"
name= "sample"
longDescription = "sample"
shortDescription = "sample"
status = "Draft"
}
$jsonbody = $Glossaryterm | ConvertTo-Json
$Responsepost = Invoke-WebRequest -Uri $glossarytermcreateendpoint -Method Post -headers $headers -Body $jsonbody -ContentType 'application/json'
I am ok to get status 200
however in the Purview workspace , I can't find the new term is created
Questions
How to make it works? Able to search ?
How to create a glossary term under specific term template .?
$glossarytermcreateendpoint = 'https://pv-chn-asiabi-sea-dev.purview.azure.com/catalog/api/atlas/v2/glossary'
From your script, I noticed that the API you called is to create a glossary, not a term, so you can't find the new term you created.
The right API to create a term is to append /term to the end of your current API:
$glossarytermcreateendpoint = 'https://pv-chn-asiabi-sea-dev.purview.azure.com/catalog/api/atlas/v2/glossary/term'
Let me know if this solves your problem.

(400) Bad Request when trying to post simple value to an API

I have this LoansController for a web api
[Route("api/[controller]")]
[ApiController]
public class LoansController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// POST api/loans
[HttpPost]
public void Post([FromBody] string value)
{
}
}
In PowerShell I can call
Invoke-WebRequest http://localhost:1113/api/loans -Body $postParams -Method Get
and it works fine (I get value1 and value2)
But when I try
$postParams = "{'value':'123'}"
Invoke-WebRequest http://localhost:1113/api/loans -Body $postParams -Method Post # -ContentType 'Application/json'
I just keep getting
Invoke-WebRequest : The remote server returned an error: (400) Bad Request.
What am I doing wrong?
I tried adding -ContentType 'Application/json' but it made no difference
What am I missing?
I also tried Invoke-RestMethod but with the same results..
Next I removed [FromBody] from the value param but value now comes in as null
Reason
It just happens because your action method is expecting a plain string from HTTP request's Body:
[HttpPost]
public void Post([FromBody] string value)
{
}
Here a plain string is a sequence of characters which is quoted by "". In other words, to represent the string, you need include the quotes before and after these characters when sending request to this action method.
If you do want to send the json string {'value':'123'} to server, you should use the following payload :
POST http://localhost:1113/api/loans HTTP/1.1
Content-Type: application/json
"{'value':'123'}"
Note : We have to use doublequoted string ! Don't send string without the ""
How to fix
To send a plain string, simply use the following PowerShell scripts :
$postParams = "{'value':'123'}"
$postParams = '"'+$postParams +'"'
Invoke-WebRequest http://localhost:1113/api/loans -Body $postParams -Method Post -ContentType 'application/json'
Or if you would like to send the payload with json, you could create a DTO to hold the value property:
public class Dto{
public string Value {get;set;}
}
and change your action method to be :
[HttpPost]
public void Post(Dto dto)
{
var value=dto.Value;
}
Finally, you can invoke the following PowerShell scripts to send request :
$postParams = '{"value":"123"}'
Invoke-WebRequest http://localhost:1113/api/loans -Body $postParams -Method Post -ContentType 'application/json'
These two approaches both work flawlessly for me.
Try to add headers
$url = 'http://localhost:1113/api/loans'
$head = #{'ContentType'='Application/json'}
Invoke-WebRequest -Uri $url -Body $postParams -Method Post -Headers $head
First, try using ConvertTo-Json in the powershell command:
$postParams = #{ "value": "123"} | ConvertTo-Json
Invoke-WebRequest http://localhost:1113/api/loans -Body $postParams -Method Post -ContentType "application/json"
If it still doesn't work I suggest creating a model (data transfer object) and using model binding to bind your string value. Edit the controller Post method as below:
public class MyModelDto {
public string Value { get; set; }
}
// POST api/loans
[HttpPost]
public void Post([FromBody] MyModelDto model)
{
string value = model.Value;
}

Syntax for groovy to duplicate PowerShell Invoke-RestMethod

I'm trying to duplicate the PowerShell Invoke-RestMethod to something similar in Groovy (groovy is standard we use in our coded pipeline).
I've done a lot of searching without success. I was wondering if I can get some help or suggestions on a possible alternative if there isn't a similar call?
The 3 three lines of PowerShell I'm trying to duplicate in Groovy are:
$tokenrequest = #{ "grant_type" = "password"; "username" = "adminuser"; "password" = "adminpassword" }
$token = Invoke-RestMethod -Uri "http://abcd.com/executionmanager/api/Token" -ContentType application/x-www-form-urlencoded -Headers #{ Authorization = ("OAuth2")} -Method POST -Body $tokenrequest
$token = $token.access_token
there are a lot of libraries to do that
the following one quite unknown
//download dependency from maven repository
#Grab(group='acme.groovy', module='acmehttp', version='20180403')
import groovyx.acme.net.AcmeHTTP
def ctx = AcmeHTTP.post(
url: "https://httpbin.org/post", //the url could be used for tests
//define body as map as soon as we are sending it as www-form
body: [ "grant_type": "password", "username": "adminuser", "password": "adminpassword" ],
headers:[
"content-type":"application/x-www-form-urlencoded",
"Authorization": "OAuth2"
],
)
assert ctx.response.code==200
//the url https://httpbin.org/post always returns json
assert ctx.response.contentType =~ "/json"
assert ctx.response.body instanceof Map
println ctx.response.body
//i guess your token should be accessible like this:
//println ctx.response.body.access_token

Powershell HTTP POST method within same session

I have a limited understanding in html, i am trying to automate a form filling like the following:
$JSONLOGIN = #'
{"#type":"login",
"email":"xxx#xxx.com",
"password":"xxxx"
}
'#
$response = Invoke-RestMethod -Uri "http://xxxxxxx/api/users/login" -Method Post -Body $JSONLOGIN -ContentType "application/json"
$response
$JSONADDRATE = #'
{
"#type":"add",
"supplierRef":"S020893",
"buyerRef":"520170509082555",
"fiRef":"7769",
"rateDate":"2017-09-15T14:11:04.684Z",
"rateType":"fixedRate",
"spFee":2,
"comFee":1,
"fiMarginOver":3,
"ttofc":0,"isTtofc":false,
"fixedRate":2,"primeLiborRate":0,
"oneWTenorRate":0,
"oneMTenorRate":0,
"twoMTenorRate":0,
"threeMTenorRate":0,
"sixMTenorRate":0,
"nineMTenorRate":0,
"oneYTenorRate":0}
'#
$response2 = Invoke-RestMethod -Uri "http://xxxxxxx/api/ubiq/rates/add" -Method Post -Body $JSONADDRATE -ContentType "application/json"
$response2
The responses are returning like that:
$response
isSessionValid : True
data : #{email=xxx#xxxx.com; id=5988ad267520a62df46af0a4; name=xxx Back Office}
isSuccessful : True
isError : False
isAllowed : True
message
$response2
isSessionValid : False
data :
isSuccessful : False
isError : False
isAllowed : False
message
Obviously the login session is being lost when jumping into the second link (Hence isSessionValid: false), how can i keep the session alive?
The -SessionVariable parameter creates a Web Request Session Object basically saving your session in the current PowerShell session.
In order to take advantage of that try this:
In the first Request add a -SessionVariable parameter and give it a string
(any string without the preceding $) then in second Request pass that string
(this time with a preceding $) to the -WebSession parameter.

Corrupt Documents in new DocuSign envelope

I'm doing a POC to demonstrate DocuSign programmatically creating and routing an envelope containing a simple document. I'm using PowerShell and the JSON API. Login and the Create Envelope work without complaint, but the resulting Word doc routed to me for signature contains gibberish. I believe I have the base64 encoding and headers right. Any thoughts about what I'm doing wrong?
The entire POC is pasted below. I've just removed the ID, Password, Integrator Key, etc. Thanks!
function boundry {
[System.Guid]::NewGuid().ToString()
}
###this is the corrected code###
function encodeFile {
param ([string]$fileName)
[System.Convert]::ToBase64String([IO.File]::ReadAllBytes((Resolve-Path $fileName).ProviderPath))
}
function logonParams {
[string] $userName = 'DocuSign user name'
[string] $password = 'DocuSign password'
[string] $integratorKey = 'DocuSign Integrator Key'
#"
{
"Username" : "$userName",
"Password" : "$password",
"IntegratorKey" : "$integratorKey"
}
"#
}
function logon {
[string] $loginURL = 'https://demo.docusign.net/restapi/v2/login_information'
$headers =
#{
"X-DocuSign-Authentication"=$(logonParams);
"accept"="application/json";
"content-type"="application/json";
}
$r = Invoke-WebRequest -uri $loginURL -headers $headers -method GET
$responseInfo = $r.content | ConvertFrom-Json
$baseURL = $responseInfo.loginAccounts.baseURL
#return the base URL for the next call
$baseURL
}
function createEnvelope {
param ([string]$file1,
[string]$baseURL
)
[string]$boundry = boundry
$headers =
#{
"X-DocuSign-Authentication"=$(logonParams);
"accept"="application/json";
"content-type"="multipart/form-data; boundary=$boundry";
}
[string]$formData = #"
--$boundry
Content-Type: application/json
{
"status":"sent",
"emailBlurb":"Please sign.",
"emailSubject": "Contract $(date)",
"documents": [{
"name": "$file1",
"documentId":"1",
"order":"1"
}],
"recipients": {
"signers" : [{
"email": "recipient#somecompany.com",
"name": "Recipient Name",
"recipientId":"1",
}]
}
}
--$boundry
Content-Type: application/msword
Content-Transfer-Encoding: base64
Content-Disposition: file; filename="$file1";documentid=1
$(encodeFile $file1)
--$boundry--
"#
$envelopeURL = "$baseURL/envelopes"
Invoke-WebRequest -uri $envelopeURL -headers $headers -body $formData -method POST
}
$baseURL = logon
createEnvelope "test.doc" $baseURL
Try changing your Content-Type header value. I'm not sure if application/msword works here, I think the proper mime-type for .docx is
application/vnd.openxmlformats-officedocument.wordprocessingml.document
See this previous SO post for a more complete list of mime-types:
What is a correct mime type for docx, pptx etc?
I solved it with assistance from the DocuSign support team. You can enable server side logging in DocuSign which is very helpful. From the old UI (not available in new UI as of June '15) choose Preferences from the dropdown next to your ID/photo. Then select Permissions under Member Options on the left. Check "Enable API Request Logging." After you run your test, the Download API Request Logs button becomes active.
It was pretty clear from the logs that my encoding was wrong. Here's the correct version:
function encodeFile {
param ([string]$fileName)
[System.Convert]::ToBase64String([IO.File]::ReadAllBytes((Resolve-Path $fileName).ProviderPath))
}
I've updated this in the original code with the question so feel free to use it.