Response
There are multiple ways to return data to the client :
- By default, the return of method is serialized and automatically sent to the client.
- However, you can also manipulate the response property for fine-grained control.
- You want to send raw bytes, that's possible too.
Default
By default, the return of the method will be serialized to json using the JsonEngine. It will also use compression (gzip, br...) dependings on the encoding types supported by the client.
The following example illustrates the object return type :
using System;
using System.Net;
using SimpleW;
namespace Sample {
class Program {
static void Main() {
var server = new SimpleWServer(IPAddress.Any, 2015);
server.AddDynamicContent("/api");
server.Start();
Console.WriteLine("server started at http://localhost:2015/");
Console.ReadKey();
}
}
public class TestController : Controller {
[Route("GET", "/test")]
public object Test() {
return new {
message = "Hello World !",
current = DateTime.Now,
i = 0,
enable = true,
d = new Dictionary<string, string>() { { "Foo", "Bar" } }
};
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
A request to http://localhost:2015/api/test will result in :
{
"message": "Hello World !",
"current": "2024-03-01T13:17:29.1249399+01:00",
"i": 0,
"enable": true,
"d": {"Foo":"Bar"}
}Any return type (object, List, Dictionary, String...) will be serialized and sent as json to the client.
The following example illustrates different return types :
using System;
using System.Net;
using SimpleW;
namespace Sample {
class Program {
static void Main() {
// listen to all IPs port 2015
var server = new SimpleWServer(IPAddress.Any, 2015);
// find all Controllers classes and serve on the "/api/" endpoint
server.AddDynamicContent("/api");
server.Start();
Console.WriteLine("server started at http://localhost:2015/");
// block console for debug
Console.ReadKey();
}
}
public class TestController : Controller {
[Route("GET", "/test1")]
public object Test1() {
// return: { "hello": "world", "date": "2023-10-23T00:00:00+02:00", "result": true }
return new {
hello = "world",
date = new DateTime(2023, 10, 23),
result = true
};
}
[Route("GET", "/test2")]
public object Test2() {
// return: ["hello", "world"]
return new string[] { "hello", "world" };
}
}
public class UserController : Controller {
[Route("GET", "/users")]
public object Users() {
// return: [{"Email":"user1@localhost","FullName":"user1"},{"Email":"user2@localhost","FullName":"user2"}]
var users = new List<User>() {
new User() { Email = "user1@localhost", FullName = "user1" },
new User() { Email = "user2@localhost", FullName = "user2" },
};
return users;
}
}
// example class
public class User {
// these public properties will be serialized
public string Email { get; set; }
public string FullName { get ;set; }
// private will not be serialized
private bool Enabled = false;
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
NOTE
There is no need to specify the exact type the method will return. Most of the time, object is enough and will be passed to a IJsonEngine.Serialize(object).
Response Property
The Response property allows a fine-grained control over the data sent to the client.
The following example illustrates how a custom response can be forged easily :
using System;
using System.Net;
using SimpleW;
namespace Sample {
class Program {
static void Main() {
var server = new SimpleWServer(IPAddress.Any, 2015);
server.AddDynamicContent("/api");
server.Start();
Console.WriteLine("server started at http://localhost:2015/");
Console.ReadKey();
}
}
public class TestController : Controller {
[Route("GET", "/html")]
public object Html() {
return MakeCustomResponse(200, "<p>Hello, World</p>", "text/html");
}
[Route("GET", "/json")]
public object Json() {
return MakeCustomResponse(200, """{ "message": "Hello World !" }""", "application/json");
}
[Route("GET", "/plaintext")]
public object Plaintext() {
return MakeCustomResponse(200, "Hello World !", "text/plain");
}
/// <summary>
/// My Custom Response
/// </summary>
/// <param name="code">the http code</param>
/// <param name="content">the content</param>
/// <param name="contentType">the Content-Type header value</param>
/// <returns></returns>
private object MakeCustomResponse(int code, string content, string contentType) {
Response.Clear();
Response.SetBegin(code);
Response.SetHeader("Content-Type", contentType);
Response.SetBody(content);
return Response;
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
NOTE
See the HttpResponse for details of its methods.
Helpers
Even though it’s easy to build a custom response, it’s also possible to reduce the amount of code for common responses.
The following example illustrates some built-in helpers.
using System;
using System.Net;
using SimpleW;
namespace Sample {
class Program {
static void Main() {
var server = new SimpleWServer(IPAddress.Any, 2015);
server.AddDynamicContent("/api");
server.Start();
Console.WriteLine("server started at http://localhost:2015/");
Console.ReadKey();
}
}
public class TestController : Controller {
[Route("GET", "/test1a")]
public object Test1a() {
// status code 200
// the contentType is default to "application/json"
// body : the object will be serialized to json string
// the compression is disabled by default
return Response.MakeResponse(new { message = "Hello World !" });
}
[Route("GET", "/test1b")]
public object Test1b() {
// status code 200
// change the contentType to "text/plain"
// body : set the string
// set the decompression to "gzip"
return Response.MakeResponse("Hello World !", contentType: "text/plain", compress: new string[] { "gzip" });
}
[Route("GET", "/test1c")]
public object Test1c() {
// status code 200
// the contentType is default to "application/json"
// body : the object will be serialized to json string
// the compression is disabled by default
// add a new header "Date" which contains the current datetime
return Response.MakeResponse(new { message = "Hello, World !" }, addHeaders: new Dictionary<string, string>() { { "Date", DateTime.UtcNow.ToString("o") } });
}
[Route("GET", "/test2")]
public object Test2() {
try {
throw new Exception("test2");
}
catch (Exception ex) {
// set message exception as body of the HttpReponse
// and a mimetype text
// with a status code 500
return Response.MakeInternalServerErrorResponse(ex.Message);
}
}
[Route("GET", "/test3")]
public object Test3() {
try {
throw new KeyNotFoundException("test3");
}
catch (Exception ex) {
// set message exception as body of the HttpReponse
// and a mimetype text
// with a status code 404
return Response.MakeNotFoundResponse(ex.Message);
}
}
[Route("GET", "/test4")]
public object Test4() {
try {
throw new UnauthorizedAccessException("test4");
}
catch (Exception ex) {
// set message exception as body of the HttpReponse
// and a mimetype text
// with a status code 401
return Response.MakeUnAuthorizedResponse(ex.Message);
}
}
[Route("GET", "/test5")]
public object Test5() {
var content = "download text content";
// will force download a file "file.txt" with content
return MakeDownloadResponse(content, "file.txt");
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
Send Raw Bytes
The Session.SendResponseBody() method is the lower level, and it basically consists of sending bytes to the client.
using System;
using System.Net;
using SimpleW;
namespace Sample {
class Program {
static void Main() {
var server = new SimpleWServer(IPAddress.Any, 2015);
server.AddDynamicContent("/api");
server.Start();
Console.WriteLine("server started at http://localhost:2015/");
Console.ReadKey();
}
}
public class TestController : Controller {
[Route("GET", "/raw")]
public void Raw() {
// as the string will be convert to byte without following the http response format
// browser may show a warning when display this response
Session.SendResponseBody("raw");
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
NOTE
These methods should be used carefully for your possible edge case.
Json Engine
This JsonEngine property defines the Json engine used in server and controllers to serialize, deserialize and populate objects. The default engine is System.Text.Json initialized with recommanded options.
There is an additionnal SimpleW.Newtonsoft nuget package which provide an alternative Json engine, the awesome Newtonsoft.Json.
To change the Json Engine for Newtonsoft
$ dotnet add package SimpleW.NewtonsoftAnd then
using System.Net;
using SimpleW;
using SimpleW.Newtonsoft;
namespace Sample {
class Program {
static void Main() {
// listen to all IPs on port 2015
var server = new SimpleWServer(IPAddress.Any, 2015);
// 1. set Newtonsoft as the json engine
server.JsonEngine = new NewtonsoftJsonEngine();
// or
// 2. set Newtonsoft as the json engine with custom settings
server.JsonEngine = new NewtonsoftJsonEngine(
(action) => {
Newtonsoft.Json.JsonSerializerSettings settings = new();
// you can customize settings dependings the IJsonEngine method called
if (action == nameof(IJsonEngine.Serialize)) {
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
}
return settings;
}
);
// find all Controllers classes and serve on the "/api" endpoint
server.AddDynamicContent("/api");
// start non blocking background server
server.Start();
Console.WriteLine("server started at http://localhost:2015/");
// block console for debug
Console.ReadKey();
}
}
// inherit from Controller
public class SomeController : Controller {
// use the Route attribute to target a public method
[Route("GET", "/test")]
public object SomePublicMethod() {
// the Request property contains all data (Url, Headers...) from the client Request
var url = Request.Url;
// the return will be serialized to json and sent as response to client
return new {
message = Message()
};
}
private string Message() {
return "Hello World !";
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
NOTE
You can create your own JsonEngine by implementing the IJsonEngine interface.
