Inclusion Handling in MVC 2 / MVCContrib - asp.net-mvc

I'd like to improve my page by combining and minifying javascript and CSS files. Since MVCContrib already contains a project called IncludeHandling, I took a look at that which unfortunately left me with unanswered questions:
There is quite a set of interfaces and objects involved in the process. Now I'm using Ninject.Mvc, but it seems that MvcContrib.IncludeHandling is using some additional (home-brewed?) DI? Can I work around this? Has anybody used this and can share some experiences?
Secondly, advice that is often heard is to put static content on different domains so the request does not contain cookies and the like, making it much easier for the server to handle the request. But how can I combine this with automatic inclusion handling - isn't that necessarily served in the same application?
EDIT: Figured that there is really just a single resolve call in the whole thing, i really wonder why they use DI for that... Thinking about a fork there...

Well, MvcContrib.IncludeHandling uses MvcContrib's DependencyResolver to find the necessary components. It's not very well documented (see the sample site for more detail, although in that case uses a custom injector).
For example, MvcContrib.Castle has a WindsorDependencyResolver for that IoC container that you can mimic to use NInject (there may be something if you Google around).
The initialization is quite verbose, but goes like this (container is the Windsor container, in your case, use NInject):
var httpContextProvider = new HttpContextProvider(HttpContext.Current);
var settings = IIncludeHandlingSettings)ConfigurationManager.GetSection("includeHandling");
container.Register(Component.For(typeof(IIncludeReader)).ImplementedBy(typeof(FileSystemIncludeReader)));
container.Register(Component.For(typeof(IIncludeStorage)).ImplementedBy(typeof(StaticIncludeStorage)));
container.Register(Component.For(typeof(IKeyGenerator)).ImplementedBy(typeof(KeyGenerator)));
container.Register(Component.For(typeof(IIncludeHandlingSettings)).Instance(settings));
container.Register(Component.For(typeof(IHttpContextProvider)).Instance(httpContextProvider));
container.Register(Component.For(typeof(IIncludeCombiner)).ImplementedBy(typeof(IncludeCombiner)));
container.Register(Component.For(typeof(IncludeController)).ImplementedBy(typeof(IncludeController)).LifeStyle.Transient);
DependencyResolver.InitializeWith(new WindsorDependencyResolver(Container));
This way you can register all the dependencies that are needed. Beware that you need the includeHandler section in your web config.
<configSections>
<section name="includeHandling" type="MvcContrib.IncludeHandling.Configuration.IncludeHandlingSectionHandler, MvcContrib.IncludeHandling"/>
</configSections>
<includeHandling>
</includeHandling>
I hope this helped.

Check out the Asp.Net Ajax Minifier. http://www.asp.net/ajaxlibrary/ajaxminquickstart.ashx
It ships with a MS Build task that you can setup where on build it will find and minify Css and Js files in your project...

Here is a Unity version of the DependencyResolver setup. I did it as a Unity container extension.
public class ConfigureMvcContrib : UnityContainerExtension
{
protected override void Initialize()
{
var settings = (IIncludeHandlingSettings)ConfigurationManager.GetSection("includeHandling");
Container
.RegisterFactory<IHttpContextProvider>(c => new HttpContextProvider(HttpContext.Current))
.RegisterFactory<IIncludeReader>(c => new FileSystemIncludeReader(c.Resolve<IHttpContextProvider>()))
.RegisterType<IIncludeStorage, StaticIncludeStorage>()
.RegisterType<IKeyGenerator, KeyGenerator>()
.RegisterFactory<IIncludeCombiner, IncludeCombiner>()
.RegisterInstance<IIncludeHandlingSettings>(settings);
DependencyResolver.InitializeWith(new UnityDependencyResolver(Container));
}
}
It is worth noting that the IncludeHandling setup is not ideal for a web cluster setup as is because of the way it does caching. I had to roll my own controller action that took a list of files to combine and minify. I can provide more info if anyone is interested.

Related

Injecting dependencies to Knockout component via Razor

Is the following snippet a good practice when using Knockout components + Asp.Net MVC? Any drawbacks I am maybe missing?
Is basically injecting part of the ko component dependencies (mainly initial data) by using Razor server side rendering...
Code snippet:
<my-component params="{
foo: '#Model.FooProperty',
bar: '#Model.BarProperty',
baz: #Json.Encode(#Model.SomeArray)
}"> </my-component>
EDIT:
For avoiding the string escape issues pointed by #Quango, I've implemented this helper:
public static stringEscapeString(this HtmlHelper helper, string value)
{
return HttpUtility.JavaScriptStringEncode(value, true);
}
Usage:
<my-component params="{
foo: '#Html.EscapeString(Model.FooString)', ...
We use Knockout in an ASP.NET MVC project at my job, and do consider this bad practise. But the reasons for this might not apply to you. This is something you'll have to judge for yourself
No caching of HTML (since the injected values might change)
No bundling of your HTML with your JavaScript (same as above)
Mixing different solutions for the same problem can be a bad practise, especially in (large) teams. Essentially, you've picked Knockout, so the 'normal' practise would be to acquire any data you need in JavaScript, and bind to it in your view. If this is what you usually do, consider if you really want to create an exception here, just because the data is (supposedly) static. If this is all about saving a few bytes, then just imagine balancing this out to serving ALL your HTML and JavaScript in a minified bundle, that can also be cached on the client.
No way to override the data later, it is essentially 'hard coded' by the server.
Your code becomes less portable. Your Razor syntax essentially couples your frontend to your chosen backend technology. If this is a long term project, consider if there might be a small chance that in a couple years from now, you might decide another backend technology might be a better alternative, and if it really makes sense that you'd have to rewrite half the frontend just to make this possible.
None of these reasons are relevant for ALL projects, so it depends a lot on the context. I've tried to list as many possible disadvantages as I could think of.

Ninject 3 multiple bindings

My question is really a repeat of an old question posted here:
Ninject 2.2 multiple bindings
It seems someone was going to deal with this back in 2011. Does anyone know if there is some way to turn off such warnings in Ninject? Or some other workaround?
EDIT
In response to #BatteryBackupUnit, here is my exact problem:
I have multiple libraries... and in my core library, I do something like this:
Find all assemblies referenced by the host application (including the host)
Find all types inheriting from IDependency from all those assemblies.
Automatically register all of those as transient
Then from another library (which may or may not be referenced by the host app), I have this:
Kernel.Bind<IDbContextFactory>().To<DbContextFactory>().InSingletonScope();
Here IDbContextFactory is also an IDependency, so it got loaded already by the core library and now I register it here but with a different scope (singleton).
From experience (and having tested it earlier) I know this is no problem in Autofac, but Ninject gives me that error message about having already registered it.
Ideally it would be better to just override any previous registrations... "cascade style" (for lack of a better phrase)..
Ninject does now support overriding open generic bindings with more specific ones.
For Example:
public interface IFoo<T> { }
public class Foo<T> : IFoo<T> { }
public class StringFoo : IFoo<string> {}
used like:
var kernel = new StandardKernel();
kernel.Bind(typeof(IFoo<>)).To(typeof(Foo<>));
kernel.Bind<IFoo<string>>().To<StringFoo>();
var intFooInstance = kernel.Get<IFoo<int>>();
var stringFooinstance = kernel.Get<IFoo<string>>();
Works.
However, if you're not talking about open generic bindings, ninject 3 still handles multi bindings the same as ninject 2.2.
In most scenarios you can work around this by using contextual bindings. Okay i would not exactly call it a workaround, i would call it good design.
In general this is described here: https://github.com/ninject/ninject/wiki/Contextual-Binding
A simple way would be to specify the binding using a name. This requires one binding for the specified one and allows only one, too.
See: https://github.com/ninject/ninject/wiki/Contextual-Binding#simple-constrained-resolution-named-bindings
It is also possible to define a "default" binding like .Bind<IFoo>().To<Foo>(); and special case bindings with the .When(...) syntax, like:
.Bind<IFoo>().To<SpecialFoo>().When(ctx => ...)
See https://github.com/ninject/ninject/wiki/Contextual-Binding#specifying-constraints-on-the-type-binding-using-arbitrary-elements-of-the-resolution-request-context
If you show us your concrete problem we might be able to provide a more concrete solution.

Configuring mapping behavior that's non-framework specific

I'm trying to configure my Object Mapper without knowing which mapper I'm using. :/
This might sound a bit strange. The reason for this is that I'm trying out the Onion Architecture so my UI cannot know about my Object Mapper located in my Infrastructure. See this solution for an example.
I'm having some trouble figuring out how I should "delegate" the none default mapping behavior.
Stuff like:
Mapper
.CreateMap<MyModel, MyDestViewModel>()
.ForMember(
dest => dest.SomeDestinationProperty,
opt => opt.MapFrom(src => src.SomeSourceProperty)
);
I've setup a class in my MVC project which is called from Global.asax and this is where I want to configure my mappings.
public static class MapConfig
{
public static void RegisterMaps()
{
}
}
I was thinking I could do something like the following. (IMapper is a self defined interface located in Domain)
public static void RegisterMaps(HttpConfiguration config)
{
var mapper = config.DependencyResolver.GetService(IMapper);
mapper.CreateMap<MyModel, MyViewModel>();
}
Now... how would I go about setting up special behavior like the .ForMember? Keeping in mind that it cannot be AutoMapper specific.
I was thinking something along these lines mapper.CreateMap<MyModel, MyViewModel>(Expression<Func<T>>) where the Func would do some black magic that I cannot figure out right now :( - Am I on the right path or have I missed something essential?
Onion Architecture isn't about the configuration being implementation-agnostic, it's about the execution.
Just create an IMapper interface for the execution of mappings, but don't worry about the configuration. This applies to your ORM, IoC container and everything else.
Also, Onion Architecture isn't about project structure, it's about the direction of your dependencies. Just call CreateMap in your UI. You can then define an IMapper interface all the way down in Core, with the other pieces implementing a version that delegates to AutoMapper.
you're abstracting away useful functionality that will cost you more time than you initially realize. Why not spend the time choosing a mapper and sticking with it?
Why is it so important that your UI doesnt know about your mapper? Assuming that you are using MVC, you are going to be flexing a lot of your chosen mappers functionality to flatten our your domain models to view models anyway.
Its the same kind of nonsense where people use generic repository implementations 'just in case' they decide to switch ORM mid project.
Choose your infrastructure carefully and stick with it.

Ninject binding/unbind issue

I have a bit of a dilemma, which to be honest is a fringe case but still poses an issue.
Currently I am using Ninject MVC and bind all my controllers like so:
Kernel.Bind<SomeController>.ToSelf();
Which works a treat for 99% of things that I have needed to do, however at the moment I am doing some wacky stuff around dynamic routing and dynamic controllers which require me to manually write a method to get the type of a controller from ninject. Now initially I thought it would be easy, but its not... I was expecting that I could get the controller based on its name, but that didnt work.
Kernel.Get<IController>("SomeController");
That got me thinking that its probably because it only knows about a binding to SomeController, not IController. So I thought, I can just write all my bindings like so:
Kernel.Bind<IController>.To<SomeController>().Named("SomeController");
This way it should be easy to get the type of the controller from the name doing the previous code, however if I were to bind this way, I would have a problem when I come to unbind the controllers (as plugins can be loaded and unloaded at runtime). So the normal:
Kernel.Unbind<SomeController>()
Which was great, will no longer work, and I would have to do:
Kernel.Unbind<IController>();
However then I realised that I need to give it some constraint to tell it which binding for this type I want to unbind, and there seems to be no overloads or DSL available to do this...
So I am trapped between a rock and a hard place, as I need to satisfy the ControllerLookup method, but also need to keep it so I can add and remove bindings easily at runtime.
protected override Type GetControllerType(RequestContext requestContext, string controllerName) {
//... find and return type from ninject
}
Anyone have any ideas?
(Just incase anyone questions why I am doing this, its because of the way I am loading plugins, Ninject knows about the types and the namespaces, but within the context of creating a controller it doesn't know the namespace just the controller name, so I do this to satisfy the isolation of the plugin, and the location of the dynamic controller, it is a roundabout way of doing it, but it is what people have done with AutoFac before Example of similar thing with AutoFac)
In my opinion the bindings should be created once at application startup and not change anymore after the first resolve. Everything else can lead to strange issues. Unless you have proper isolation using an AppDomain for each plugin you can not really unload them anyway. Instead of unloading bindings you can make them conditional and disable them using some configuration.
If you really want to unload bindings then I suggest not to do it for single bindings but take advantage of modules. Load all bindings belonging to one plugin together in one or several modules and unload those modules instead of the single bindings.

Where do you put methods for common web uri paths

We have a pretty common architecture:
Database
Repository Layer
Business Objects
Services Layer - serves DTOs to the client
Web Layer (MVC)
We've got a number of common paths to resources, in particular images and podcasts (Ex. http://media.mysite.com/podcasts/). I want to create a static utility class with properties:
MySite.Utils.ImagePathUri
MySite.Utils.PodcastsPathUri
etc
My question is: Where do you put uri paths? Into which project does this utility class go?
Initially, it seemed a no-brainer: the web layer. It's a web site. I should be able to change the urls of a site without the other layers knowing about it.
Everything was fine, but, . . . then one day one of my services needed to provide a SyndicationFeed type. The SyndicationFeed needs a full URI, not just a partial file name. But the services shouldn't have access to full paths. Or should they?
I've debated with myself several things, but can't come up with a firm position:
Move the paths to the services layer. That tightly couples the web layer to the services layer, but maybe that's ok, since they're pretty tightly coupled to begin with.
Move the paths to the business objects or repos. I don't like this, but if I'm open to putting it into the services layer, I have to at least consider it.
Don't use SyndicationFeed inside of services layer, but use it only in the web layer. Solves the issue, but it seems like SyndicationFeed should belong in a services layer.
Discard SyndicationFeed. Any SyndicationFeed can more easily be created in MVC with a PartialView that generates the appropriate XML without having to mess with the bloated abstractions like ElementExtensions. I like this one, but we're using SyndicationFeed in a number of places, so that one will take the most explaining to do.
Provide a fake uri to the syndication feed in the services layer and then change it in the web layer. Can you say hack?
Put the full path in the database. That sounds ok at first, but then I realize that it breaks as soon as you have a dynamically generated image.
Some other solution that doesn't occur to me.
What are your thoughts? Where do you put utility classes for web resources (images, podcasts, etc)? And if you say "web layer", what's your take on the SyndicationFeed issue?
UPDATE
At the end of the day, I decided to scrap the SyndicationFeed class, which negated the need for including the path to the file in the service and repository layers. However, the problem still comes up elsewhere and using DI and, in particular, an IoC like Ninject makes perfect sense. So does wrapping together these into a common interface.
SyndicationFeed, View engines and why Declarative does Declarative better
I ditched the SyndicationFeed and instead created the XML that I needed using Razor. Not only is it much easier to create, but it's 1000% more readable. I've come around to the opinion that using imperative code (C#, VB, etc.) to create XML is just harder than it ought to be. XML is declarative, not imperative.
Instead, I've now decided that declarative syntax of View Engines (e.g. Razor) is much easier to work with than imperative languages.
I feel your pain. I too had a similar situation that I resolved by passing the uri to my repository layer, from my web layer.
My project uses Ninject for binding, and since I was already passing the connection string to the repository with Ninject, it was a simple matter to pass my path string as well.
My repository then massages the path string and populates the necessary properties in my business object.
Is this proper? I do not know, but it works for now. I am not completely happy with the solution, but I have not yet had a chance attempt an improvemnt.
Would love to hear how others have dealt with this.
Facing a similar situation I felt the best way to approach it was to define a configuration interface that resulted in an object at the top most layer. Each layer in between would refine the interface with more specific properties and operations:
public interface IWebConfiguration
{
string RootImageUri { get; }
}
the service would layer would add the things needed by itself:
public interface IServicesConfiguration
{
string SyndicationFeedUri { get; }
}
public interface IDatabaseConfiguration
{
string ConnectionString { get; }
}
In the end I had the web tier implement the specific object that wired up all of the interfaces. Ugly? Perhaps. I will admit there was calls to isa in there and some casting.
However, I was able to then pass to each layer a strongly typed interface. In my opinion it was better than having a series of calls to get plain old string from a config file. Also, because each property was specific to a layer and the aggregate object was being passed around I only had to load the configuration once.

Resources