Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom serializer options for WebApiModule #467

Closed
simohr opened this issue Mar 13, 2020 · 3 comments · Fixed by #469
Closed

Custom serializer options for WebApiModule #467

simohr opened this issue Mar 13, 2020 · 3 comments · Fixed by #469
Labels
area:web-api Issue with WebApiModule and/or related classes. regression v3.x
Milestone

Comments

@simohr
Copy link

simohr commented Mar 13, 2020

Is your feature request related to a problem? Please describe.
Hello, since upgrading to embedio version 3.4.3 from version 3.3.3 we have problems with serialization in web controllers. In 3.3.3 we serialize the objects and return them:

public class PersonController : WebApiController
{
    public class Person
    {
        public string Name { get; set; }
    }

    [Route(HttpVerbs.Get, "/person")]
    public string GetPerson()
    {
        return serializer.Serialize(new Person() { Name = "SomeName"});
    }
}

However in 3.4.3 the controller has automatic serialization and we no longer need to use our own. This is a problem for us because the JSON objects created are not what we have defined. For example all properties appear with capital letters and slashes are escaped (''):
Now:

{"Name" : "SomeName"}
{"Url":"http:/\/\localhost:/\port"}

Before:

{"name" : "SomeName"}
{"url":"http:\\localhost:port"}

Describe the solution you'd like
Is there a way to stop the automatic serialization or a way to configure its' settings.

@rdeago
Copy link
Collaborator

rdeago commented Mar 13, 2020

Hello @simohr, thanks for using EmbedIO!

While we assess where the bug lies exactly (JSON serialization is part of SWAN, so we may need to open an issue there) here's how to return any given string from a Web API method:

    [Route(HttpVerbs.Get, "/person")]
    public void GetPerson()
    {
        Response.ContentType = MimeType.Json;
		using (var writer = HttpContext.OpenResponseText(Encoding.UTF8, true))
        {
            writer.Write(serializer.Serialize(new Person() { Name = "SomeName"}));
        }
    }

Notice that the method has a void return type, to signal that it produces no data to serialize automatically. If you need it to be an async method, return Task instead.

If you omit the second parameter to OpenResponseText:

  • the response will not be buffered in memory;
  • no Content-Length header will be sent;
  • chunked transfer encoding will be used.

This will be usually fine if your client is a browser, but can cause problems if the client relies on the presence of a Content-Length header.

@rdeago rdeago added area:web-api Issue with WebApiModule and/or related classes. regression v3.x labels Mar 13, 2020
@simohr
Copy link
Author

simohr commented Mar 13, 2020

After a little more research we found an alternative solution using the ResponseSerializerCallback. We defined our own callback with the needed settings. Thank you for the response. Here is the solution:
In the code where you define your WithWebApiModule :

 webServer.WithWebApi("/api", SerializationCallback, m => m.WithController(() => new CustomWebApiController(webModule)));

And the SerializationCallback :

        public static async Task SerializationCallback(IHttpContext context, object? data)
        {
            Validate.NotNull(nameof(context), context).Response.ContentType = MimeType.Json;
            using var text = context.OpenResponseText(new UTF8Encoding(false));
            await text.WriteAsync(JsonSerializer.Serialize(data, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })).ConfigureAwait(false);
        }

@rdeago
Copy link
Collaborator

rdeago commented Mar 13, 2020

Well done @simohr! It's refreshing to see someone taking advantage of the customizability of EmbedIO v3.

If you want to squeeze out a little more performance, store your serializer options in a static readonly field, so they're ready to use every time. 😉

@rdeago rdeago changed the title WebController serialization question Custom serializer options for WebApiModule Mar 13, 2020
@rdeago rdeago added this to the 4.0.0 milestone Mar 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:web-api Issue with WebApiModule and/or related classes. regression v3.x
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants