How to create a view model by IoC container?

Topics: Writing modules
Aug 8, 2015 at 7:58 AM
Sorry in advance if this is more an AutoFac question rather than an Orchard question :-/

My CarPartDriver's Editor Method currently passes the CarPart type to the template's model:
protected override DriverResult Editor(CarPart part, dynamic shapeHelper) {
            return ContentShape("Parts_Car_Edit", () =>
                shapeHelper.EditorTemplate(TemplateName: "Parts/Car", Model: part, Prefix: Prefix));
        }
Now, I have introduced a view model, passing it to the template like this: Model: new CarPartViewModel(part):
protected override DriverResult Editor(CarPart part, dynamic shapeHelper) {
            return ContentShape("Parts_Car_Edit", () =>
                shapeHelper.EditorTemplate(TemplateName: "Parts/Car", Model: new CarPartViewModel(part), Prefix: Prefix));
        }
But rather than creating the view model with new, I would prefer that Autofac would create that instance for me. How could I accomplish this?
Developer
Aug 8, 2015 at 11:22 AM
You would have to register it with Autofac, which can be done by either creating a class that derives from Module (in the Autofac namespace) and register your component, or to have it automatically discovered and registered, by creating an interface for your view model that derives from IDependency.

However, why would you want to resolve an instance of your view model via Autofac? That seems pretty unconventional.
Aug 9, 2015 at 7:32 AM
Edited Aug 9, 2015 at 7:41 AM
Thank you for explaining the registration of a type with AutoFac.

How would you, as a next step, manually resolve an instance (without constructor/property injection)? As I understand, I would need Autofac's ContainerBuilder and use a Scope? But when injecting the IContainerBuilder via the driver's constructor, I cannot find the expected Resolve method and I am stuck.

I was using Microsoft PRISM a lot, where most of the participating objects are created by the container, also the view models. The view models in PRISM tend to get very complex and have more dependencies, maybe that's why I thought it could make sense.

But here, I understand after your post that my strategy might not be so good. Maybe it is a better idea to resolve the view model's dependencies in the driver class and pass them via constructor to the view model to avoid using the container for constructing the view model.
Developer
Aug 9, 2015 at 9:08 AM
Once your type is registered with Autofac, you can resolve instances of it using WorkContext, which you can get via IOrchardServices or via IWorkContextAccessor. WorkContext has a method called Resolve<T>.

What I typically see with ASP.NET MVC view models is that they tend to contain all the data they need for the view. Preparing this data happens in the controller layer, where various services are resolved and queried. So you wouldn't actually pass these services to the view model. Instead, invoke those services and store whatever data you need for the view in the view model.
Marked as answer by mcmcod120 on 8/9/2015 at 5:27 AM
Aug 9, 2015 at 1:01 PM
Thanks for this clarification. I will reduce my view models to its basic responsability, which is, as you say, to provide data for UI elements.