In my company we have a API that's very tricky to handle. I managed to make a successful PUT Request using Postman
and now I want to build this same http request in C# using a simple Console application.
Here is the postman request:
The 2nd key has to be named exactly like that. The entry
Json I can use via file or directly as value.
Here are the headers:
Only important one is the Authorization Header.
I don't know how to actually create this complicated request in C# since I'm very new to this language and couldn't find a solution to my specific problem.
I tried with the normal httpclient from C# and RestSharp
but wasn't able to make this request.
Here is what I have so far:
{
class Program
{
static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
using var multipart = new MultipartFormDataContent();
var jsonBytes = JsonSerializer.SerializeToUtf8Bytes(new { Metadata = "abc" });
// Need to add my json file or the json direct here somewhere
// This is how the JSON looks like
/*
{
"values": {
"z1D_WorklogDetails": "very new workinfo 3",
"z1D_View_Access": "Internal",
"z1D Action": "MODIFY",
"z2AF_Act_Attachment_1": "UID Liste.xlsx"
}
}
*/
multipart.Add(new ByteArrayContent(jsonBytes), "entry");
using var fs = File.OpenRead(@"C:\myFile.txt");
multipart.Add(new StreamContent(fs), "attach-z2AF_Act_Attachment_1");
multipart.Headers.Add("Authorization", "//my token here");
using var resp = await client.PostAsync("**/entry/HPD:IncidentInterface/INC000001479529|INC000001479529", multipart);
resp.EnsureSuccessStatusCode();
}
}
}
So how can I make this complicated request like the on shown in Postman exactly the same in C#? The API Admins told me the attachment in attach-z2AF_Act_Attachment_1
has to come Base64 encrypted
For anyone that is interested what this call actually does:
It adds a new Worklog to an existing ticket in our ticket system (BMC Remedy) and also adds an attachment to this new worklog entry.
Thank you very much.
Please look at the code below, please test it at your environment.
The point is that you can set content types manually.
Another point is that you set Authorization header wrong.
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
string url = "https://localhost/";
string token = "token_here";
//Prepare json data
string json = JsonSerializer.Serialize(new { Metadata = "abc" });
StringContent jsonContent = new StringContent(json, Encoding.UTF8, MediaTypeNames.Application.Json);
StreamContent streamContent;
bool base64 = false;
//Prepare octet-stream data
if (base64)
{
//For base-64 encoded message
using FileStream inputFile = new FileStream(@"2.txt", FileMode.Open, FileAccess.Read, FileShare.None,
bufferSize: 1024 * 1024, useAsync: true);
using CryptoStream base64Stream = new CryptoStream(inputFile, new ToBase64Transform(), CryptoStreamMode.Read);
streamContent = new StreamContent(base64Stream);
streamContent.Headers.Add("Content-Type", MediaTypeNames.Application.Octet);
await SendRequest(jsonContent, streamContent, url, token);
}
else
{
//For plain message
using FileStream file = File.OpenRead("2.txt");
streamContent = new StreamContent(file);
streamContent.Headers.Add("Content-Type", MediaTypeNames.Application.Octet);
await SendRequest(jsonContent, streamContent, url, token);
}
async Task SendRequest(StringContent stringContent, StreamContent streamContent, string url, string token)
{
// Add json and octet-stream to multipart content
MultipartFormDataContent multipartContent = new MultipartFormDataContent();
multipartContent.Add(stringContent, "entry");
multipartContent.Add(streamContent, "attach-z2AF_Act_Attachment_1");
//Create request
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Put, url);
//Here is the right setting of auth header value, sheme is on the left side
request.Headers.Authorization = new AuthenticationHeaderValue("AR-JWT", token);
request.Content = multipartContent;
//Last step - sending request
HttpClient http = new HttpClient();
HttpResponseMessage resp = await http.SendAsync(request);
resp.EnsureSuccessStatusCode();
}
With my approach i got this request:
Headers:
{
"content-length": "6538",
"authorization": "AR-JWT token_here",
"content-type": "multipart/form-data; boundary=\"02600173-b9af-49f4-8591-e7edf2c0b397\""
}
Body:
--02600173-b9af-49f4-8591-e7edf2c0b397
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name=entry
{"Metadata":"abc"}
--02600173-b9af-49f4-8591-e7edf2c0b397
Content-Type: application/octet-stream
Content-Disposition: form-data; name=attach-z2AF_Act_Attachment_1
OCTET DATA HERE
--02600173-b9af-49f4-8591-e7edf2c0b397--
Is it correct?
Update: I've made a base-64 encoded version of attachment.
Simply set base64
to true.
Request with base64 approach:
Headers:
{
"content-length": "354",
"authorization": "AR-JWT token_here",
"content-type": "multipart/form-data; boundary=\"7572d1e8-7bd7-4f01-9c78-ce5b624faab3\""
}
Body:
--7572d1e8-7bd7-4f01-9c78-ce5b624faab3
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name=entry
{"Metadata":"abc"}
--7572d1e8-7bd7-4f01-9c78-ce5b624faab3
Content-Type: application/octet-stream
Content-Disposition: form-data; name=attach-z2AF_Act_Attachment_1
MjIyMg==
--7572d1e8-7bd7-4f01-9c78-ce5b624faab3--