Important Update: Archer Community Scheduled Maintenance on November 23–24 - New Community Launching Soon! Learn More..
2019-01-16 04:00 PM
I am writing a function in C# to logout an Archer session using the RESTful API POST method.
public async Task PostLogoutAsync(string sessionToken)
{
string logoutPath = "platformapi/core/security/logout";
string logoutBody = "{\"Value\":\"" + sessionToken + "\"}";
HttpResponseMessage httpResponseMessage = await this.httpClient.PostAsJsonAsync<string>(logoutPath, logoutBody);
}
The HttpClient object is configured like this:
httpClient = new HttpClient
{
BaseAddress = new Uri(baseUrl)
};
httpClient.DefaultRequestHeaders.Add("Accept", "application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
httpClient.DefaultRequestHeaders.Add("Authorization", "Archer session-id=" + sessionToken);
The request method object looks like this in Visual Studio (The Uri is correct in the request message):
{Method: POST, RequestUri: 'https://Archer/RSAarcher/platformapi/core/security/logout', Version: 1.1, Content: System.Net.Http.ObjectContent`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Headers:{ Accept: application/json Accept: text/html Accept: application/xhtml+xml Accept: application/xml; q=0.9 Accept: */*; q=0.8 Authorization: Archer session-id=A8A190D5E8536E2D921CF1F23C77E36A Content-Type: application/json; charset=utf-8 Content-Length: 46}}
The body content value is rendered like this in the request message object:
{"Value":"A8A190D5E8536E2D921CF1F23C77E36A"}
Everything looks correct in the request message. However, I am receiving a 400: Bad Request when the logout function runs. The w3wp log entry gives the following message, "The data in the request body could not be deserialized as a StringWrapper."
What does that mean? I did not have this issue with the login function which serialized a custom type object into the request body. This is simply stringified JSON. What should I do?
2019-01-17 04:58 PM
This is my solution:
public async Task<bool> PostLogoutAsync(string sessionToken)
{
string logoutPath = "platformapi/core/security/logout";
string logoutBody = @"{'Value':'" + sessionToken + "'}";
JObject bodyValue = JObject.Parse(logoutBody);
try
{
HttpResponseMessage httpResponseMessage = await httpClient.PostAsJsonAsync<JObject>(logoutPath, bodyValue);
if (!httpResponseMessage.IsSuccessStatusCode)
{
throw new HttpClientRequestFailedException();
}
else
{
return true;
}
}
catch (Exception exception)
{
throw exception;
}
}
I parse the logoutBody string to a JObject and the body of the request is deserialized by the Archer API. For some reason the formatting done on a plain string by PostAsJsonAsync could not be deserialized by the API. The more complicated API requests will be easier to build as JObjects anyway, so I am going to use this solution going forward.
2019-01-16 04:17 PM
Bradley, I think you need quotes around the session token in the header, this line:
httpClient.DefaultRequestHeaders.Add("Authorization", "Archer session-id=" + sessionToken);
From the https://community.rsa.com/docs/DOC-97463
Request Header
Accept: application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Authorization: Archer session-id="session token ID from login"
Content-Type: application/json
Advisory Consultant
2019-01-16 04:17 PM
I've seen it a few different ways:
Here's 1 -
var logoutRequest = client.BuildRequest("core/security/logout")
.WithSession(session)
.WithValue(new StringContainer { Value = session.SessionToken });
var logoutResponse = await client.PostAsync<StringContainer, ArcherResponse<bool>>(logoutRequest);
I have not seen the PostAsJsonAsync.
I don't know that you need that.
The response you get is Json and if you need to, you can parse, but if successful, I wouldn't think you'd need any info.
But, you said you're doing the same thing to log in... so, not sure why it works for one and not the other.
2019-01-16 05:57 PM
The StringWrapper is the POCO (Plain Old C# Object) that the API code is using to represent the request body for the logout resource.
public WebApiRequestResult<bool> Logout(StringWrapper sessionToken)
It has a single property called Value which, in this case, is intended to hold the session token. So the JSON should look like this:
{"Value":"5D090B29BFA8E5D7E08B334164454C02"}
2019-01-17 10:25 AM
Get it to work?
2019-01-17 04:58 PM
This is my solution:
public async Task<bool> PostLogoutAsync(string sessionToken)
{
string logoutPath = "platformapi/core/security/logout";
string logoutBody = @"{'Value':'" + sessionToken + "'}";
JObject bodyValue = JObject.Parse(logoutBody);
try
{
HttpResponseMessage httpResponseMessage = await httpClient.PostAsJsonAsync<JObject>(logoutPath, bodyValue);
if (!httpResponseMessage.IsSuccessStatusCode)
{
throw new HttpClientRequestFailedException();
}
else
{
return true;
}
}
catch (Exception exception)
{
throw exception;
}
}
I parse the logoutBody string to a JObject and the body of the request is deserialized by the Archer API. For some reason the formatting done on a plain string by PostAsJsonAsync could not be deserialized by the API. The more complicated API requests will be easier to build as JObjects anyway, so I am going to use this solution going forward.