C
C#•4mo ago
Rem

How do I do a HTTP request in C#?

public static async Task<string> MessageAI(string user, string system)
{
HttpClient client = new();
client.BaseAddress = new("http://localhost:1234");
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = @"{
""messages"": [
{
""role"": ""user"",
""content"": user
},
{
""role"": ""system"",
""content"": system
}
],
""temperature"": 0.7,
""max_tokens"": 80,
""stream"": false
}";

var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");

var response = await client.PostAsync("http://localhost:1234/v1/chat/completions", content);
var responseContent = await response.Content.ReadAsStringAsync();

return responseContent;
}
public static async Task<string> MessageAI(string user, string system)
{
HttpClient client = new();
client.BaseAddress = new("http://localhost:1234");
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = @"{
""messages"": [
{
""role"": ""user"",
""content"": user
},
{
""role"": ""system"",
""content"": system
}
],
""temperature"": 0.7,
""max_tokens"": 80,
""stream"": false
}";

var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");

var response = await client.PostAsync("http://localhost:1234/v1/chat/completions", content);
var responseContent = await response.Content.ReadAsStringAsync();

return responseContent;
}
I get bad request?
65 Replies
Saber
Saber•4mo ago
probably because your passing invalid json
Rem
Rem•4mo ago
Hmm...
mtreit
mtreit•4mo ago
Get it working via something like PostMan first
Saber
Saber•4mo ago
put a breakpoint and validate json contains what you think it should
Rem
Rem•4mo ago
What's postman?
Pobiega
Pobiega•4mo ago
""content"": system
guaranteed to be broken
Rem
Rem•4mo ago
I see
mtreit
mtreit•4mo ago
It's a tool for making web requests
Pobiega
Pobiega•4mo ago
you are not actually adding the user/system to the body you are hardcoding in the word user and system without quotes
Rem
Rem•4mo ago
felt like it How do I put variables into json?
Pobiega
Pobiega•4mo ago
interpolated string
Rem
Rem•4mo ago
I know it works on the server side
mtreit
mtreit•4mo ago
One way is to create a C# object that you then serialize to the JSON rather than hand-building the string
Pobiega
Pobiega•4mo ago
var user = "steve";
var system = "windows";

var json =
$$"""
{
"messages": [
{
"role": "user",
"content": "{{user}}",
},
{
"role": "system",
"content": "{{system}}"
}
],
"temperature": 0.7,
"max_tokens": 80,
"stream": false
}
""";
var user = "steve";
var system = "windows";

var json =
$$"""
{
"messages": [
{
"role": "user",
"content": "{{user}}",
},
{
"role": "system",
"content": "{{system}}"
}
],
"temperature": 0.7,
"max_tokens": 80,
"stream": false
}
""";
Rem
Rem•4mo ago
Seems easier than what I just did lol
Pobiega
Pobiega•4mo ago
I still usually prefer mtreits suggestion of setting up actual types that reflect your structure and letting the system handle the json encoding
Rem
Rem•4mo ago
hmm
Pobiega
Pobiega•4mo ago
but this is fine, if verbose
Rem
Rem•4mo ago
thanks! Hmm.. It still seem to not work... I can do it via curl
curl http://localhost:1234/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "Always answer in rhymes." },
{ "role": "user", "content": "Introduce yourself." }
],
"temperature": 0.7,
"max_tokens": -1,
"stream": false
}'
curl http://localhost:1234/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "Always answer in rhymes." },
{ "role": "user", "content": "Introduce yourself." }
],
"temperature": 0.7,
"max_tokens": -1,
"stream": false
}'
but not in c#?
Pobiega
Pobiega•4mo ago
woops, no quotes around the values
Rem
Rem•4mo ago
hmm
Pobiega
Pobiega•4mo ago
updated
Rem
Rem•4mo ago
I see well I actually didn't use the values but I still can't get it to work properly?
Pobiega
Pobiega•4mo ago
set a breakpoint, verify that the body looks okay
Rem
Rem•4mo ago
I'm not sure what a breakpoint is
Pobiega
Pobiega•4mo ago
$debug
MODiX
MODiX•4mo ago
Tutorial: Debug C# code and inspect data - Visual Studio (Windows)
Learn features of the Visual Studio debugger and how to start the debugger, step through code, and inspect data in a C# application.
Pobiega
Pobiega•4mo ago
time to learn 🙂
Rem
Rem•4mo ago
breakpoint at the variable?
Pobiega
Pobiega•4mo ago
after the json variable is set, ye
mtreit
mtreit•4mo ago
This is why I suggest using Postman. That verifies you are actually building a request the server accepts. Then you can compare what Postman sends over the wire with what your C# code does
Rem
Rem•4mo ago
It says that json is null? should there be two dollar signs? okay I think I let it execute smart..
"{\r\n\"messages\": [\r\n {\r\n \"role\": \"user\",\r\n \"content\": NPC name: Old Man,\r\n },\r\n {\r\n \"role\": \"system\",\r\n \"content\": Generate a description for this NPC.\r\n }\r\n ],\r\n\"temperature\": 0.7,\r\n\"max_tokens\": 80,\r\n\"stream\": false\r\n}"
"{\r\n\"messages\": [\r\n {\r\n \"role\": \"user\",\r\n \"content\": NPC name: Old Man,\r\n },\r\n {\r\n \"role\": \"system\",\r\n \"content\": Generate a description for this NPC.\r\n }\r\n ],\r\n\"temperature\": 0.7,\r\n\"max_tokens\": 80,\r\n\"stream\": false\r\n}"
this is the value of json should there be \r?
Pobiega
Pobiega•4mo ago
\r is carriage return \r\n is a windows style newline
Rem
Rem•4mo ago
I see What should I look out for?
leowest
leowest•4mo ago
or just do proper classes to serialize instead of fighting text to fit
Pobiega
Pobiega•4mo ago
if the start and end quotes are there, thats probably why also uh this is super invalid
Rem
Rem•4mo ago
I see
Pobiega
Pobiega•4mo ago
"{
"messages": [
{
"role": "user",
"content": NPC name: Old Man,
},
{
"role": "system",
"content": Generate a description for this NPC.
}
],
"temperature": 0.7,
"max_tokens": 80,
"stream": false
}"
"{
"messages": [
{
"role": "user",
"content": NPC name: Old Man,
},
{
"role": "system",
"content": Generate a description for this NPC.
}
],
"temperature": 0.7,
"max_tokens": 80,
"stream": false
}"
thats what you are sending
Rem
Rem•4mo ago
hmm probably incorrect yes
Pobiega
Pobiega•4mo ago
wdym probably lol
Rem
Rem•4mo ago
nothing lol
Pobiega
Pobiega•4mo ago
json validity is a boolean state 😄
Rem
Rem•4mo ago
I didn't know you could turn classes into json?
Pobiega
Pobiega•4mo ago
thats how you normally do it
Rem
Rem•4mo ago
😔 guess they need to invent those quantum computers soon so I can have a probably valid json hmm
leowest
leowest•4mo ago
var chat = new Chat
{
Messages =
[
new Message
{
Role = "user",
Content = user
},
new Message
{
Role = "system",
Content = system
},
],
Temperature = 0.7,
MaxTokens = 80,
stream = false
};

public class Chat
{
[JsonPropertyName("messages")]
public List<Message> Messages { get; set; }

[JsonPropertyName("temperature")]
public double Temperature { get; set; }

[JsonPropertyName("max_tokens")]
public long MaxTokens { get; set; }

[JsonPropertyName("stream")]
public bool Stream { get; set; }
}

public class Message
{
[JsonPropertyName("role")]
public string Role { get; set; }

[JsonPropertyName("content")]
public string Content { get; set; }
}
var chat = new Chat
{
Messages =
[
new Message
{
Role = "user",
Content = user
},
new Message
{
Role = "system",
Content = system
},
],
Temperature = 0.7,
MaxTokens = 80,
stream = false
};

public class Chat
{
[JsonPropertyName("messages")]
public List<Message> Messages { get; set; }

[JsonPropertyName("temperature")]
public double Temperature { get; set; }

[JsonPropertyName("max_tokens")]
public long MaxTokens { get; set; }

[JsonPropertyName("stream")]
public bool Stream { get; set; }
}

public class Message
{
[JsonPropertyName("role")]
public string Role { get; set; }

[JsonPropertyName("content")]
public string Content { get; set; }
}
then just serialize chat instead 🙂
Rem
Rem•4mo ago
uhuh...
leowest
leowest•4mo ago
so it would literally just be
var json = JsonSerializer.Serialize(chat);
var json = JsonSerializer.Serialize(chat);
Pobiega
Pobiega•4mo ago
or use JsonContent
leowest
leowest•4mo ago
with System.Text.Json
Pobiega
Pobiega•4mo ago
or PostAsJsonAsync
leowest
leowest•4mo ago
yep that works too and sorry to interrupt mid journey 🙂
Rem
Rem•4mo ago
😂 it's no mid journey
Pobiega
Pobiega•4mo ago
record RootObject(
List<Message> Messages,
double Temperature,
[property: JsonPropertyName("max_tokens")]
int MaxTokens,
bool Stream);

record Message(string Role, string Content);

public static async Task<string> MessageAI(string user, string system)
{
var obj = new RootObject([new Message("user", user), new Message("system", system)], 0.7d, 80, false);

HttpClient client = new();
client.BaseAddress = new("http://localhost:1234");
client.DefaultRequestHeaders
.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var response = await client.PostAsJsonAsync("http://localhost:1234/v1/chat/completions", obj);
var responseContent = await response.Content.ReadAsStringAsync();

return responseContent;
}
record RootObject(
List<Message> Messages,
double Temperature,
[property: JsonPropertyName("max_tokens")]
int MaxTokens,
bool Stream);

record Message(string Role, string Content);

public static async Task<string> MessageAI(string user, string system)
{
var obj = new RootObject([new Message("user", user), new Message("system", system)], 0.7d, 80, false);

HttpClient client = new();
client.BaseAddress = new("http://localhost:1234");
client.DefaultRequestHeaders
.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var response = await client.PostAsJsonAsync("http://localhost:1234/v1/chat/completions", obj);
var responseContent = await response.Content.ReadAsStringAsync();

return responseContent;
}
Rem
Rem•4mo ago
looks more complicated
Pobiega
Pobiega•4mo ago
but it works
Rem
Rem•4mo ago
looks good then
Pobiega
Pobiega•4mo ago
unlike your 10+ attempts at doing it yourself 🙂 manually writing json is a mess
leowest
leowest•4mo ago
he just made a onliner out of my classes into a record
Pobiega
Pobiega•4mo ago
avoid when possible
leowest
leowest•4mo ago
in terms of how different it is but yes create DTOs to represent your json it will save your life
Pobiega
Pobiega•4mo ago
this is the "shortest" way to do it properly, but it also means you will get chunked transfer encoding if the webserver doesnt support that, there are workarounds. as I found out the hard way at work a few days ago 😄
Rem
Rem•4mo ago
well I want to use leowest's example but the class is not a string nor httpcontent? wait- I forgot the other part
leowest
leowest•4mo ago
you have to create the objets then serialize it or use the method pobi said above PostAsJsonAsync with what u have it would be something like this
var json = JsonSerializer.Serialize(chat);
var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
var json = JsonSerializer.Serialize(chat);
var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
with what pobi suggested it would be just
var response = await client.PostAsJsonAsync("v1/chat/completions", chat);
var response = await client.PostAsJsonAsync("v1/chat/completions", chat);
you choose whichever u feel more confortable with
Pobiega
Pobiega•4mo ago
and you can mix and match you could use the classes, but still use PostAsJson I would normally add a helper method with records like thesee
record Message(string Role, string Content);

record RootObject(
List<Message> Messages,
double Temperature,
[property: JsonPropertyName("max_tokens")]
int MaxTokens,
bool Stream)
{
public static RootObject Create(string user, string system, double temperature, int maxTokens,
bool stream = false) =>
new([new Message("user", user), new Message("system", system)], temperature, maxTokens, stream);
}

public static async Task<string> MessageAI(string user, string system)
{
var obj = RootObject.Create(user, system, 0.7d, 80);

HttpClient client = new();
client.BaseAddress = new("http://localhost:1234");
client.DefaultRequestHeaders
.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var response = await client.PostAsJsonAsync("http://localhost:1234/v1/chat/completions", obj);
var responseContent = await response.Content.ReadAsStringAsync();

return responseContent;
}
record Message(string Role, string Content);

record RootObject(
List<Message> Messages,
double Temperature,
[property: JsonPropertyName("max_tokens")]
int MaxTokens,
bool Stream)
{
public static RootObject Create(string user, string system, double temperature, int maxTokens,
bool stream = false) =>
new([new Message("user", user), new Message("system", system)], temperature, maxTokens, stream);
}

public static async Task<string> MessageAI(string user, string system)
{
var obj = RootObject.Create(user, system, 0.7d, 80);

HttpClient client = new();
client.BaseAddress = new("http://localhost:1234");
client.DefaultRequestHeaders
.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var response = await client.PostAsJsonAsync("http://localhost:1234/v1/chat/completions", obj);
var responseContent = await response.Content.ReadAsStringAsync();

return responseContent;
}
the method itself becomes very clean and easy to use then the records you can "hide" in some other file somewhere 😄