[NancyFx] Vistas y contenido estático en diferente ensamblado

Gracias a OWIN (los componentes compatibles) podemos mover nuestra aplicación entre diferentes hosts y servidores sin mucho esfuerzo, por ésta razón, en ocasiones separamos físicamente la aplicación del host (en diferentes ensamblados).

Nancy tiene unas configuraciones predefinidas para localizar las vistas dentro del entrypoint, configuraciones que podemos sobrescribir para trabajar en la forma que deseemos, en este caso, localizar las vistas en un ensamblado distinto:

Lo primero que debemos hacer es cambiar las propiedades Build Action y Copy to Output Directory a Embedded Resource  y Do Not Copy respectivamente:

image 

Ahora necesitamos un Bootstrapper (o editar el que ya teníamos) para que Nancy pueda localizar las vistas dentro de nuestro ensamblado. Haremos uso del ResourceViewLocationProvider y su propiedad RootNamespaces para agregar el espacio de nombres que queremos. Finalmente sobrescribimos la InternalConfiguration:

    public class CustomNancyBootstraper : DefaultNancyBootstrapper
    {
        protected override void ConfigureApplicationContainer(TinyIoCContainer container)
        {
            var assembly = GetType().Assembly;
            ResourceViewLocationProvider.RootNamespaces.Clear();
            ResourceViewLocationProvider.RootNamespaces.Add(assembly, "Ensamblado.PathVistas"); // Donde se estan tus views
            base.ConfigureApplicationContainer(container);
        }
        protected override NancyInternalConfiguration InternalConfiguration
        {
            get
            {
                return NancyInternalConfiguration.WithOverrides(config => { config.ViewLocationProvider = typeof(ResourceViewLocationProvider); });
            }
        }
    }

¡Y listo! con estos pasos ya podemos tener las vistas en un ensamblado distinto.

¿Y el contenido estático?

El ResourceViewLocationProvider no nos sirve para el contenido estático dentro del sitio, así que debemos agregar las convenciones necesarias para localizar estos recursos (por ahora a pedal):

        protected override void ConfigureConventions(NancyConventions nancyConventions)
        {
            nancyConventions.StaticContentsConventions.Clear();            
            nancyConventions.StaticContentsConventions.Add(Css);
            base.ConfigureConventions(nancyConventions);
        }

        private Response Css(NancyContext context, string s)
        {
            const string resourcePath = @"/Content";
            var path = context.Request.Url.Path;
            if (!path.StartsWith(resourcePath, StringComparison.InvariantCultureIgnoreCase))
            {
                return null;
            }
            return new EmbeddedFileResponse(GetType().Assembly, "Ensamblado.PathContent", Path.GetFileName(context.Request.Url.Path));
        }

¡No sale mi Favicon!

Como vemos los contenidos deberán ser recursos embebidos y el favicon no es la excepción. Para que Nancy lo encuentre debemos sobrescribir la propiedad FavIcon, como dice la documentación:

        private byte[] _favicon;
        protected override byte[] FavIcon
        {
            get { return _favicon ?? (this._favicon = LoadFavIcon()); }
        }
        private byte[] LoadFavIcon()
        {
            using (var resourceStream = GetType().Assembly.GetManifestResourceStream("Ensamblado.favicon.ico"))
            {
                var tempFavicon = new byte[resourceStream.Length];
                resourceStream.Read(tempFavicon, 0, (int)resourceStream.Length);
                return tempFavicon;
            }
        }

El código completo de éste articulo se encuentra en este Gist.

Espero les sea de utilidad.

Hasta el próximo post.

Anuncios
[NancyFx] Vistas y contenido estático en diferente ensamblado

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s