Skip to content
This repository has been archived by the owner on Apr 26, 2020. It is now read-only.

Custom serializer doesn't run #55

Closed
sakopov opened this issue Nov 25, 2016 · 7 comments
Closed

Custom serializer doesn't run #55

sakopov opened this issue Nov 25, 2016 · 7 comments

Comments

@sakopov
Copy link

sakopov commented Nov 25, 2016

    public sealed class CustomJsonSerializer : JsonSerializer
    {
        public CustomJsonSerializer()
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver();
            NullValueHandling = NullValueHandling.Ignore;
            DefaultValueHandling = DefaultValueHandling.Ignore;
        }
    }
    public class CustomApiBootstrapper : DefaultNancyBootstrapper
    {
        protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
        {
            base.ConfigureRequestContainer(container, context);

            container.Register<JsonSerializer, CustomJsonSerializer>();
        }
    }

The CustomJsonSerializer constructor never executes. The JSON response still has null properties.

{
  "data": {
    "application": "myApp",
    "version": "1.0",
    "links": {
      "self": {
        "href": "/api"
      }
    }
  },
  "message": null,
  "status": "success"
}

What's missing?

@thecodejunkie
Copy link
Member

Nancy consumes 'ISerializer' instances. You need to implement that in order for Nancy to discover and use it

@sakopov
Copy link
Author

sakopov commented Nov 25, 2016

That breaks it even more.

Added to bootstrap.

container.Register<ISerializer, JsonNetSerializer>();
container.Register<JsonSerializer, CustomJsonSerializer>();

The JSON looks like:

{
  "Data": {
    "Application": "myApp",
    "Version": "1.0",
    "Links": {
      "self": {
        "Href": "/api"
      }
    }
  },
  "Message": null,
  "Status": "success"
}

Lost camel casing, null values are not ignored.

Also noticed that JSON.Net version that's referenced by Nancy.Serialization.JsonNet is very, very old.

@sakopov
Copy link
Author

sakopov commented Nov 25, 2016

It seems like i'm having problems with everything that Nancy is supposed to magically pick up and run. (i.e. I'm using FluentValidation with Nancy which also had the same problem until i explicitly added it to dependency registration). So this makes me wonder if the problem is in how i'm running Nancy? I'm using Topshelf and Nancy.Hosting.Self to host it in a windows service.

Update 1
Tried this package on another Nancy API project hosted using OWIN. As soon as i introduced a custom serializer with settings as show in previous post, I noticed that Nancy stopped applying default serialization rules but it also never applied mine. I also never had to explicitly add any registration to see this behavior when running on OWIN. So different hosting types definitely have a profound effect. Second day wasted on this and I feel completely stumped.

Update 2
Oh God, I was adding registrations by overriding the ConfigureRequestContainer instead of ConfigureApplicationContainer.

protected override void ConfigureApplicationContainer(TinyIoCContainer container)
        {
            base.ConfigureApplicationContainer(container);

            container.Register<ISerializer, JsonNetSerializer>();
            container.Register<IBodyDeserializer, JsonNetBodyDeserializer>();
            container.Register<JsonSerializer, CustomJsonSerializer>();
        }

This is working! Rookie mistake. Sorry I'm new to Nancy :(

@ryanulit
Copy link

ryanulit commented Aug 17, 2017

@sakopov that registration is literally the ONLY way it will work for me using the Nancy.Bootstrappers.Autofac bootstrapper on a 64 bit windows machine. Thank you.

@YuriGal
Copy link

YuriGal commented Dec 2, 2019

@ryanulit I know it's been a while but could you please show an example
how custom JsonSerializer is configured in Nancy.Bootstrappers.Autofac bootstrapper ?

@ryanulit
Copy link

ryanulit commented Dec 2, 2019

@YuriGal here's what worked for me, but this is 2+ years old so there may be a better way now:

public class ApiBootstrapper : AutofacNancyBootstrapper
{
    protected override void ConfigureApplicationContainer(ILifetimeScope existingContainer)
    {
        base.ConfigureApplicationContainer(existingContainer);

        existingContainer.Update(builder =>
        {
            builder.RegisterType<JsonNetSerializer>().As<ISerializer>();
            builder.RegisterType<JsonNetBodyDeserializer>().As<IBodyDeserializer>();
            builder.RegisterType<CustomJsonSerializer>().As<JsonSerializer>();
        });
    }
}

And the CustomJsonSerializer class:

public class CustomJsonSerializer : JsonSerializer
{
    public CustomJsonSerializer()
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver();
        NullValueHandling = NullValueHandling.Ignore;
        Converters.Add(new StringEnumConverter(true));
    }
}

And here's my packages.config for version references:

<package id="Nancy" version="1.4.5" targetFramework="net471" />
<package id="Nancy.Bootstrappers.Autofac" version="1.4.1" targetFramework="net471" />
<package id="Nancy.Serialization.JsonNet" version="1.4.1" targetFramework="net471" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net471" />

@YuriGal
Copy link

YuriGal commented Dec 2, 2019

@ryanulit Thank you so much for the prompt response! I figured it as far as builder.RegisterType( ) but was missing the .As( ) part. Thanks again!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants