0

I want to use custom serialization for my Nancy Modules, which uses the requested URL as part of its inputs.

I've seen that you need to register dependencies that use the context in an override of the ConfigureRequestContainer (as answered in C# IOC and Request State in NancyFX)

public class NancyBootstrapper : DefaultNancyBootstrapper
{
    protected override void ConfigureRequestContainer(
        TinyIoCContainer container, 
        NancyContext context)
    {
        container.Register<JsonSerializer>(new CustomJsonSerializer(context));
    }
}

And I've seen that you can specify a different serialiser for Nancy using the IRegistrations interface (as answered in Configuring JsonNetSerializer and JsonNetBodyDeserializer using Nancy TinyIoC)

public class JsonRegistration : IRegistrations
{
    public IEnumerable<TypeRegistration> TypeRegistrations
    {
        get
        {
           yield return new TypeRegistration(typeof(JsonSerializer), typeof(CustomJsonSerializer));
        }
    }

    public IEnumerable<CollectionTypeRegistration> CollectionTypeRegistrations { get; protected set; }
    public IEnumerable<InstanceRegistration> InstanceRegistrations { get; protected set; }
}

If I register my serializer the first way, I can't get Nancy to use it for JSON serialization.

If I register it the second way, I can't inject a copy of the current NancyContext and get access to the request - it tries to create an instance of the serialiser before the ConfigureRequestContainer method is even called.

What am I missing here?

Community
  • 1
  • 1
perfectionist
  • 4,256
  • 1
  • 23
  • 34

1 Answers1

1

Assuming that you are interested in the "serialization" part - i.e. returning your model as json, did you consider to extend your model to carry the needed information trough the pipeline, and then the serializer to strip it?

The following code makes the assumption that the custom serializer is smart enough to not serialize null properties.

Get["/somedata"] = _ => new MyModelEx
   { 
      WhateverRealProperty = "some data",
      RequestUri = this.Context.Request.Uri
   };

public class MyModelEx : MyModel, IModelWithRequestUri
{
    public string RequestUri {get; set;}
}

And in your serializer you can test for this "extra" data element, grab whatever you need from it, strip it off (set it to null??) and serialize the rest.

Or variations of the above, where you can have some "container" generic model like

public class ExtendedModel<T>
{
    public T Model {get; set;}
    public string RequestUri {get;set;} // or even pass the whole context if u need to
}

Some variations of the above would be the simplest implementation.

I would prefer a different approach, where I would create some form of a per-request "bag", in which to hold the current context, and inject that bag into the serializer (of course, this will require the serializer to be registered per-request as well).

Check this answer for ideas.

Community
  • 1
  • 1
Sunny Milenov
  • 21,990
  • 6
  • 80
  • 106