Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ModelFactory in ASP.NET MVC to solve 'RenderPartial' issue

The 'RenderPartial()' method in ASP.NET MVC offeres a very low level of functionality. It does not provide, nor attempt to provide a true 'sub-controller' model *.

I have an increasing number of controls being rendered via 'RenderPartial()'. They fall into 3 main categories :

1) Controls that are direct descendants of a specific page that use that page's model

2) Controls that are direct descendants of a specific page that use that page's model with an additional key of some type. Think implementation of 'DataRepeater'.

3) Controls that represent unrelated functionality to the page they appear on. This could be anything from a banner rotator, to a feedback form, store locator, mailing list signup. The key point being it doesn't care what page it is put on.

Because of the way the ViewData model works there only exists one model object per request - thats to say anything the subcontrols need must be present in the page model.

Ultimately the MVC team will hopefully come out with a true 'subcontroller' model, but until then I'm just adding anything to the main page model that the child controls also need.

In the case of (3) above this means my model for 'ProductModel' may have to contain a field for 'MailingListSignup' model. Obviously that is not ideal, but i've accepted this at the best compromise with the current framework - and least likely to 'close any doors' to a future subcontroller model.

The controller should be responsible for getting the data for a model because the model should really just be a dumb data structure that doesn't know where it gets its data from. But I don't want the controller to have to create the model in several different places.

What I have begun doing is creating a factory to create me the model. This factory is called by the controller (the model doesn't know about the factory).

public static class JoinMailingListModelFactory {

        public static JoinMailingListModel CreateJoinMailingListModel() {

            return new JoinMailingListModel()
            {
                MailingLists = MailingListCache.GetPartnerMailingLists();
            };
        }
    }   

So my actual question is how are other people with this same issue actually creating the models. What is going to be the best approach for future compatibility with new MVC features?


  • NB: There are issues with RenderAction() that I won't go into here - not least that its only in MVCContrib and not going to be in the RTM version of ASP.NET-MVC. Other issues caused sufficent problems that I elected not to use it. So lets pretend for now that only RenderPartial() exists - or at least that thats what I've decided to use.
like image 564
Simon_Weaver Avatar asked Mar 13 '09 05:03

Simon_Weaver


People also ask

How to load partial view in mvc view?

To create a partial view, right click on the Shared folder -> click Add -> click View.. to open the Add View popup, as shown below. You can create a partial view in any View folder. However, it is recommended to create all your partial views in the Shared folder so that they can be used in multiple views.

Why do we use partial view in mvc?

A partial view is a Razor markup file ( . cshtml ) without an @page directive that renders HTML output within another markup file's rendered output. The term partial view is used when developing either an MVC app, where markup files are called views, or a Razor Pages app, where markup files are called pages.

Which of the following methods are used to render partial view HTML partial() HTML RenderPartial() HTML RenderAction() all of the above?

The Partial, RenderPartial, RenderAction helper methods are used to render partial view in mvc3 razor.


1 Answers

Instead of adding things like MailingListSignup as a property of your ProductModel, encapsulate both at the same level in a class like ProductViewModel that looks like:

public class ProductViewModel() {
    public ProductModel productModel;
    public MailingListSignup signup;
}

Then get your View to be strongly-typed to the ProductViewModel class. You can access the ProductModel by calling Model.productModel, and you can access the signup class using Model.signup.

This is a loose interpretation of Fowler's 'Presentation Model' (http://martinfowler.com/eaaDev/PresentationModel.html), but I've seen it used by some Microsoft devs, such as Rob Conery and Stephen Walther.

like image 191
JMS Avatar answered Sep 16 '22 11:09

JMS