Moodle rest post returning error with feature core_user_get_users_by_field - web-services

Hi I'm new with moodle and I'm getting an error when calling the webservice.
Currently I'm trying to retrieve a user from moodle with the following function core_user_get_users_by_field and I'm using rest service to do so. I already managed to create a user thus I am authenticated to use the service.
the error that I'm receiving is
Missing required key in single structure: field
The bellow is the code was used to create a User. the issue that I got from the error is that the parameter that I need to send for the post is not formatted well. Does anyone know how to search correctly with this method or any other method.
String token = "token";
String postData = "username=username";
string createRequest = string.Format("http://domain/webservice/rest/server.php?wstoken={0}&wsfunction={1}&moodlewsrestformat=json", token, "core_user_get_users_by_field");
// Call Moodle REST Service
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(createRequest);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
// Encode the parameters as form data:
byte[] formData =
UTF8Encoding.UTF8.GetBytes(postData);
req.ContentLength = formData.Length;
// Write out the form Data to the request:
using (Stream post = req.GetRequestStream())
{
post.Write(formData, 0, formData.Length);
}
// Get the Response
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream resStream = resp.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
string contents = reader.ReadToEnd();
// Deserialize
JavaScriptSerializer serializer = new JavaScriptSerializer();
if (contents.Contains("exception"))
{
// Error
MoodleException moodleError = serializer.Deserialize<MoodleException>(contents);
}
else
{
// Good
}

The webservice core_user_get_users_by_field needs an associative array given as parameter with the following key:values
'field': 'id'
'values': array of integers (must be an array, possibly with just one value)
In PHP it would be, for example:
$parameters = array('field' => 'id', 'values' => array(13));
It means: the user whose 'id' has the value of 13. Of course, you can use other parameters as well: ('field'=>'lastname', 'values'=> array('Smith'))
The parameters you can choose are the fields of the Moodle 'user' table.
Try to build these parameters in your postData variable.

Here's URL that work with my put this url in postman and set http method to post method
hostname/webservice/rest/server.php?wstoken=any_token&wsfunction=core_user_get_users_by_field&field=email&values[0]=h#fci.com
&moodlewsrestformat=json

Related

Accessing a Record from API Source with Power Query (Custom Connector)

This is a follow up to my issue at API Pagination in JSON Body (not Header) - How to Access with Power Query in Custom Connector?
I have built a custom connector for an API that sends its pagination data back in the body of the response, rather than the header. The way to use GetNextLink using header is documented in the GitHub custom connector example:
https://github.com/microsoft/DataConnectors/blob/master/samples/Github/github.pq
GetNextLink = (response, optional request) =>
let
// extract the "Link" header if it exists
link = Value.Metadata(response)[Headers][#"Link"]?,
links = Text.Split(link, ","),
splitLinks = List.Transform(links, each Text.Split(Text.Trim(_), ";")),
next = List.Select(splitLinks, each Text.Trim(_{1}) = "rel=""next"""),
first = List.First(next),
removedBrackets = Text.Range(first{0}, 1, Text.Length(first{0}) - 2)
in
try removedBrackets otherwise null;
Getting to the pagination data from the body of the response should be easier than the header, I've learned. But I am stumped. In the images, you can see the record I am trying to access that comes back through Web.Contents()
This is my code for the GetNextLink function. I am trying to get the "next" record above.
GetNextLink = (response) =>
// response is data already run through Web.Contents()
let
Source = Lines.FromBinary(response),
nextPage = Record.Field(Source[paging], "next")
in
try nextPage otherwise null;
I get the error back "We cannot convert a value of type Record to type Text". I feel like I am not getting the 'Source" correctly? I could certainly use help as I am a PowerQuery newbie!
Thanks!
GetNextLink = (response) =>
// response is data already run through Web.Contents()
let Source = Lines.FromBinary(response),
nextpage = try Source[paging][next] otherwise null
in nextpage
or
GetNextLink = (response) =>
// response is data already run through Web.Contents()
let Source = Lines.FromBinary(response)
nextpage = try Record.Field(Source[paging],"next") otherwise null
in nextpage

Does anyone know how to send API calls to an application using a __RequestVerificationToken? (Error: The cookie and the form field were swapped)

I'm trying to test out Anti Forgery tokens with API calls using VS2019 (C#) and RestSharp. What i'm doing is doing a GET to our login page to get 4 tokens/ cookies, then attaching these to a POST, with the Username and password, to try to log on. The first call succeeds and gives me a HTTP 200 and 4 cookies/ tokens back (ASP.NET_SessionId, XSRF-TOKEN, XSRF-COOKIE and a __RequestVerificationToken - all get attached as cookies (in the cookiecontainer) to the POST API call), the 2nd call however, fails with an HTTP 500 with this message: "Validation of the provided anti-forgery token failed. The cookie "__RequestVerificationToken" and the form field "__RequestVerificationToken" were swapped.". I'm including this token twice in my POST call - once as a cookie and once as part of the request body. Here is my code - can anyone shed any light on how to fix this error?
Thanks,
Jamie.
public void LogIn(string userName, string password)
{
// 1st call to get the cookies and tokens.
CommonProperties.Client = new RestClient { CookieContainer = new CookieContainer() };
CommonProperties.Client.BaseUrl = new Uri($"https://localhost:50000/Account/Login");
var request = new RestRequest(Method.GET);
request.AddParameter("ReturnUrl", "%2F", ParameterType.QueryString);
CommonProperties.Response = CommonProperties.Client.Execute(request);
CommonProperties.Client.BaseUrl = new Uri($"https://localhost:50000/Account/Login");
var requestToken = CommonProperties.Response.Cookies.Single(c => c.Name ==
"__RequestVerificationToken");
// 2nd call to log in.
request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Accept-Encoding", "gzip, deflate, br");
request.AddHeader("Accept", "*/*");
request.AddHeader("Referer", $"https://localhost:50000/Account/Login");
request.AddParameter("undefined", $"__RequestVerificationToken=
{requestToken.Value}&UserName=userName&Password=password_321", ParameterType.RequestBody);
CommonProperties.Response = CommonProperties.Client.Execute(request);
}
I just solved this issue myself, so hopefully this answer helps anyone else who comes looking.
When you originally load the page with the GET it will return the cookie with the name of __RequestVerificationToken PLUS a form field with the same name. That form field will have a different value to the cookie's value, and in your POST you must set the body field for __RequestVerificationToken to have that form field's value, and the value of the cookie with the same name must match the cookie from the GET response.
If you have the same value for both the form field and the cookie, you get that rather misleading error that suggests the values are "swapped". They are not actually swapped, they're just matching, which is incorrect.

Grapevine RestClient Json Body

I'm having difficulty putting together a request by sending a json content, can not find anything in the 4.x documentation it's completely different from version 3.x
RestClient client = new RestClient();
client.Host = "localhost";
client.Port = 8080;
RestRequest request = new Grapevine.Client.RestRequest("/route1");
request.HttpMethod = HttpMethod.POST;
RestResponse response = client.Execute(request) as RestResponse;
Somewhere in your code - prior to sending your request - you need to set the body (or payload) of your request.
request.Payload = "send this data";
The payload is just a string, so it's up to you to serialize your objects to a JSON string before making the assignment (and set the ContentType property appropriately). The Json.NET library is widely used to accomplish this. You can also do this by hand:
request.ContentType = ContentType.JSON;
request.Payload = "{\"key\":\"value\"}";

Why am I not recieving facebook graph entity_id value from http get request?

if I do a simple HTTP GET request with e.g. POSTMAN then in the response there's an element called 'entity_id'.
e.g. https://www.facebook.com/yourFacebookName
If however, I do the request from a simple C# app then the following code doesnt return the 'entity_id' element in the response and I cant figure out why?
Code from app:
string html = string.Empty;
string url = string.Format("https://www.facebook.com/{0}", "yourFBName");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.GZip;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
html = reader.ReadToEnd();
}
if (html.Contains("entity_id"))
{
//do some stuff
}
Anyone know why its dropping the 'entity_id' element, but returning it when hitting that url from POSTMAN etc?

How to get Request property in SOAP UI for REST service test

I created a simple project in SOAP UI, and now am trying to extract some test suit properties using Setup Script. Only thing is, RawRequest and Request properties are empty, but I want to display them. Request does exist, but request and raw request properties are null. This is only case with REST services.
def tcaseList = testSuite.getTestCaseList();
// for each testCase
def countTestCases = tcaseList.size();
for(tc = 0;tc<countTestCases;tc++){
def countTestSteps = tcaseList[tc].getTestStepList().size();
for(i=0;i<countTestSteps;i++)
{// get testStep
def testStep = tcaseList[tc].getTestStepAt(i);
runner = tcaseList[tc].run(new com.eviware.soapui.support.types.StringToObjectMap(), false);
def request = testStep.getPropertyValue("RawRequest");
log.info(request.toString())
Any ideas why this property is null, and how to extract request and display it.
In REST Request on SOAPUI the RawRequest property is only available on REST Request which use POST which sends data not only parameters, in REST Request which use GET the RawRequest is empty. If you want instead to get the value of the GET parameters you can use this in your code:
...
def paramValue = testStep.getPropertyValue("parameterName");
...
In REST Request which use POST and sends data you're already doing correctly with your code:
def request = testStep.getPropertyValue("RawRequest");
I add the follow images to illustrate what I'm explaining:
POST with not empty Request:
GET with empty Request:
UPDATE
So if you want to get all the parameters from your REST Requests you can add the follow groovy snippet to your code:
// your for loop...
for(i=0;i<countTestSteps;i++){// get testStep
def testStep = tcaseList[tc].getTestStepAt(i)
...
// code to get REST Request parameters and log to the console
// to avoid errors if you've testSteps which doesn't are RestTestSteps (i.e groovy...)
if(testStep instanceof com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep){
// ? is groovy operator to avoid NPE
def parameters = testStep?.getTestRequest()?.getParams()
// loop through the map parameters
parameters.each { k,v ->
// for each params print the name and the value
log.info "$k : ${v.getValue()}"
}
}
...
If you need more info take a look at RestTestRequestStep API.
Hope this helps,