A small disclaimer: I am an avid Unity user, and here are my 2 cents.
1st: Violation of SOLID (SRP / OCP / DIP)
Already declared by @democodemonkey and @thumbmunkeys, you are closely linking 2 classes. Suppose some classes (let it be ProductsThingamajigOne and ProductsThingamajigTwo) use the ProductsController and use its default constructor. What to do if the architecture decided that the system should not use the ProductsRepository, which stores the Products in files, but should use a database or cloud storage. What impact will this have on classes?
2nd: what if ProductRepository needs another dependency?
If the repository is database-based, you may need to provide it with a ConnectionString. If it is file-based, you may need to provide it with a parameter class that provides the exact path to where the files are saved - and the truth is that, in the general case, applications usually contain dependency trees (A depends on B and C)., B depends on D, C depends on E, D depends on F and G, etc.), which have more than 2 levels, so SOLID violations do more harm, because to complete a task you need to change more code - but even before that, can you imagine the code that will create the whole application? In fact, classes can have many of their own dependencies, in which case the problems described earlier multiply.
This is usually the work of Bootstrapper - it defines the structure of dependencies and performs (usually) one resolution, which puts the whole system in action, like a puppet in a string.
3rd: What if the dependency tree is not a tree, but a graph?
Consider the following case: a class A, depending on classes B and C, B and C, both depends on class D, and expect to use the same instance of D. It was common practice to make D single, but this could raise a lot of questions. Another option is to pass instance D to constructor A and force it to create B and C, or pass instances of B and C to and create them from the outside - and the complexity goes on and on.
4th: packaging (assembly)
Your code assumes that the "ProductsController" can see the "ProductRepository" (assembly). What if there are no links between them? An assembly map can be nontrivial. As a rule, the boot code (I assume that it is in the code, and not in the configuration file for a second) is written in the assembly, which refers to the whole solution. (This has also been described by @Steven).
5th: cool things you can do with IoC containers
Singletones are made easy (using unity: just use the "containercontrolledlifetimemanager" when registering), Lazy Instantiation is really easy (with unity: register a mapping and ask in the Func constructor). These are just a couple of examples of what IoC containers give you (almost) for free.