horsdal / Nancy.Linker

Simple URI builder for named Nancy routes
MIT License
13 stars 2 forks source link

Simplify the API #2

Closed lijunle closed 9 years ago

lijunle commented 9 years ago

Just want to use the linker in such a way:

using Nancy.Linker; // use as NancyModule extension

public class MyModule : NancyModule
{
    public MyModule ()
    {
        string url = this.Context.MakeRelativeUrl("Named Route", parameters); // return a string directly

        // use URL here...
    }
}

There is no need to pollute module constructor.

lijunle commented 9 years ago

Refer the unit test, I write such an extension to workaround that:

namespace Nancy.Linker.Extension
{
    using System;
    using Nancy;
    using Nancy.Linker;

    public static class Linker
    {
        public static string BuildRelativeUrl(this NancyContext context, string routeName, dynamic parameters = null)
        {
            IResourceLinker linker = LinkerModule.Linker;
            Uri uri = linker.BuildRelativeUri(context, routeName, parameters);
            return uri.ToString();
        }

        public class LinkerModule : NancyModule
        {
            public LinkerModule(IResourceLinker linker)
            {
                Linker = linker;
            }

            internal static IResourceLinker Linker { get; private set; }
        }
    }
}
horsdal commented 9 years ago

Not completely sure what you propose here. Do you want me to add a LinkerModule like the one in your unit test example?

lijunle commented 9 years ago

What I want to do is to avoid add IResourceLinke parameter to all modules. I think the cureent API is too complicated.

Not completely sure what you propose here. Do you want me to add a LinkerModule like the one in your unit test example?

horsdal commented 9 years ago

@lijunle would you take a look at PR #3 and see if it solves your issue with taking dependencies on the IResourceLinker everywhere

lijunle commented 9 years ago

Hi, @horsdal , thanks for your response.

I don't know if the static variable linker will affect the multi-thread requests. And, the linker resolver module seems a flaw.

So, after I learnt Nancy's IoC container. I wrap the NancyContext and IResourceLinker to my custom context, suppose naming MyContext, then register my context to RequestContainer and inject it to each module.

Code like this:

// MyContext.cs
public class MyContext
{
    private readonly IResourceLinker linker;

    private readonly NancyContext context;

    public MyContext(NancyContext context, IResourceLinker linker)
    {
        this.linker = linker;
        this.context = context;
    }

    public string GetUrl(string routeName, dynamic parameters = null)
    {
        // wrap Nancy.Linker functionality here
        Uri uri = this.linker.BuildRelativeUri(this.context, routeName, parameters);
        return uri.ToString();
    }
}
// MyBootstrap.cs
public class MyBootstrapper : DefaultNancyBootstrapper
{
    protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
    {
        base.ConfigureRequestContainer(container, context);

        var myContext = container.Resolve<MyContext>(new NamedParameterOverloads { { "context", context } });
        container.Register(myContext); // I have ever register NancyContext here, but getting an exception
    }
}
// MyModule.cs
public class MyModule : NancyModule
{
    public MyModule(TinyIoCContainer container, MyContext myContext)
    {
        this.Get["MyNamedRouting", "/"] = _ => container.Resolve<MyViewModel>();
        // other named routings here...
        // in MyViewModel, add MyContext as constructor parameter, it can leverage myContext.GetUrl to build links

        var url = myContext.GetUrl("MyNamedRouting");
        // other logic here...
    }
}

So. I think the current API is OK. :smile: and I am closing this issue.