views:

175

answers:

6

I am working on an MVC app and I am wondering in what situation it is best to use a strongly typed view and when not... I guess this is more of a best practice question. I am making an ecommerce app and there is a table for orders, products, etc. The part I was working on that brought me to this question was my add a new product page for the admins to put more store items in. Any tips about when to know to use strongly typed view will be great help.

I already searched for related questions and nothing popped out in the first 3 pages or so, but if you know of a post please direct me.

Thanks.

A: 

A strongly typed view is best used when you modify an instance of that type in the view.

For example when you edit or create a Product in a view it would definitely be adviceable to have a strongly typed view for the product class.

If you are only displaying text or images without actually having a connection to anything in the underlying databaselayers it would probably be easier to go without a strongly typed view.

This will all come rather naturally as you work more with MVC in my experience.

Robban
+5  A: 

Any time you need to show data (on any particular object or collection of objects) on the view, use a strongly typed view.

If your view is purely informational, you may be able to use the ModelState to pass small bits of information (eg: Success/Error pages, Not Authorized Messages, and etc.)

In my applications, I have EVERY view strongly typed, so that I can easily pass user login information to the Master Page. That is, all of my views are strongly typed, templated and constrained to a base class that contains the Site Configuration and the User Login info.

Because of that, I can do this:

public class MyBaseMasterPage : ViewMasterPage<MyBaseModel>
{
    public string CurrentTheme
    {
        get
        {
            if (this.Model.CurrentUser != null)
                return this.Model.CurrentUser.Theme;

            else return this.Model.Config.DefaultTheme;
        }
    }

    public User CurrentUser { get { return this.Model.CurrentUser; } }

    public ConfigurationRepository Config { get { return this.Model.Config; } }
}

Note that, since the Master Page is themed based on ONLY what is populated in the model, the View itself will never trigger a hit to the database/cache.

MyBaseModel is configured like so:

public class MyBaseModel
{
    private MyBaseModel() { }

    public MyBaseModel(MyBaseController controller)
    {
        this.CurrentUser = controller.CurrentUser;
        this.Config = controller.Config;
    }

    public User CurrentUser { get; private set; }

    public ConfigurationRepository Config { get; private set; }
}

The private constructor forces all subclasses of my model to initialize the model with the soruce controller.

The controller base class pulls the user out of session and the Config out of cache.

That way, no matter what, all of my views have access to the user and config data, without ever generating a hit to the DB.

Now, in MyBaseController:

public class LanLordzBaseController : Controller
{
    [Obsolete]
    protected new ViewResult View(string viewName, object model)
    {
        if (model == null)
        {
            throw new ArgumentNullException("model");
        }

        if (!(model is MyBaseModel))
        {
            throw new ArgumentException("The model you passed is not a valid model.", "model");
        }

        return base.View(viewName, model);
    }

    protected ViewResult View(string viewName, MyBaseModelmodel)
    {
        if (model == null)
        {
            throw new ArgumentNullException("model");
        }

        return base.View(viewName, (object)model);
    }

    public ConfigurationRepository Config { get { ... } }

    public User CurrentUser { get { ... } }
}

This helped me find all of my controllers that were returning views that weren't inherited from the proper base class.

John Gietzen
John, does that mean you are using a custom Membership provider?
Lazarus
Yes, I rolled my own.
John Gietzen
Hmm that sounds very handy. All our views are strongly typed and we have created our own MembershipProvider and MembershipUser. How did you modify the master page to hang onto that information?
Jedidja
Updated with details on how I was doing this.
John Gietzen
Most of your update makes sense until have code with the ControllerResponse type - where does this come from? :)
Jedidja
The ControllerResponse was MyBaseModel, i renamed it for this example to clarify, but forgot about that spot. Fixed.
John Gietzen
Thanks for sharing :) Going to try to use your approach as well.
Jedidja
+1  A: 

I use strongly typed views whenver I can so I can get away from all the casts of various bits of ViewData within the view.

I create my own strongly typed views any time I need information from more than one source for the view.

For example in my Checkout, I require an order but also the user's prefences for price display; so I created CheckoutViewModel which has an Order and PriceDisplay property.

Hope that helps,

Dan

Daniel Elliott
Exactly! I agree.
Fabio Milheiro
A: 

Although I'm repeating what others have eloquently stated I think there is one more point to raise. The View is part of the Model, View, Controller concept and as such is there to present the Model in a visual way to the user. Given that it is, in essence, a representation of the Model it makes sense for it to be strongly typed.

I only ever use ModelState or TempState for passing small pieces of data, like outcome messages from activities like add, delete, etc. Any time I find tempted to use State to pass collections that are unrelated to the View-type then I refactor that functionality into a partial view and present that through a separate controller action.

In my code related types are generally referenced hierarchically from the base type to which the view is strongly-typed, and so are accessible within the View where necessary.

Lazarus
I think "ModelState or TempState" should read "ViewData or TempData".
Craig Stuntz
You're right... brain was fried!
Lazarus
+3  A: 

If there is data involved, there should be a strongly typed view. Period.

Wyatt Barnett
+1  A: 

Always. I would go further and use strongly typed controls and HtmlHelper actions also. Most are available in the MvcContrib library.

mxmissile