2

I know it's a bad practice to use database in the view. However, I'm also passing the User object and I wonder how I can make it easy to use.

I love the way it works in Ruby On Rails. You just create an @instance_variable in before_filter and call it from the controllers and from the views.

You can't do this in ASP.NET MVC though. So I created a class with all the data I need to pass to the view (DataContext and User):

public class XData
{
    public DBDataContext DB { get; set; }
    public User User { get; set; }
}

In controller's Initialize method I get all the data:

public XData X;

protected override void Initialize(RequestContext requestContext)
{
    base.Initialize(requestContext);

    X = new XData();

    X.DB = ...;
    X.User = ....;
}

Works great: I can get the database object from the view like this:

<%= Model.X.DB.Users.First().Name %>

In order to pass the data to the view, I have to do the following:

    public ActionResult Foo()
    {
        return View(new FooModel
                        {
                            X = X,
                            HelloMessage = "Hello world!"
                        });
    }

The thing I don't like here is that I always have to write the X = X thing. How can I initialize that automatically?

Thanks

John Farrell
  • 24,673
  • 10
  • 77
  • 110
Alex
  • 34,581
  • 26
  • 91
  • 135
  • 3
    This is wrong in so many ways that I just don't know where to start. – queen3 Sep 25 '10 at 19:41
  • What's wrong about it? I know it's not the common way to do things, but that's what I use. – Alex Sep 25 '10 at 19:45
  • 2
    I have to agree that this is just very wrong in many, many ways. Your controller should extract what you need from your data store (i.e., Model.X.DB.Users) and then pass that in a simple model to your view. If the view is going straight to the data store, the point of MVC is defeated. – Rohan Singh Sep 25 '10 at 19:52
  • Ok, let's forget about the database. But what about the user object? – Alex Sep 25 '10 at 19:55

3 Answers3

1

You could place X in ViewData and write an HtmlHelper extension method to access X or override the View method of the controller and add a little reflection logic that maps every instance property of the controller to properties with matching names of your model (I guess Automapper could help here...)

saintedlama
  • 6,838
  • 1
  • 28
  • 46
1

I've seen a similar problem where a lot of controllers return a similar model with only a few customizations. In this case, create an abstract base model that other models derive from, and a function that returns the particular model you need with the base X = X and so forth already set.

For example, consider this:

public abstract class MyBaseModel
{
    public User User { get; set; }
}

public class FooModel : MyBaseModel
{
    public string FooMessage { get; set; }
}

public class BarModel : MyBaseModel
{
    public string BarMessage { get; set; }
}

public class MyController : Controller
{
    public ActionResult Foo()
    {
        var model = this.GetModel<FooModel>();

        // Set the properties on FooModel.
        model.FooMessage = "Hello world!"

        return View(model);
    }

    public ActionResult Bar()
    {
        var model = this.GetModel<BarModel>();

        // Set the properties on BarModel.
        model.BarMessage = "Hello world 2!"

        return View(model);
    }

    protected T GetModel<T>() where T : MyBaseModel, new()
    {
        T model = new T();

        // Set the properties on MyBaseModel.
        model.User = ...;

        return model;
    }
}

If you want to share MyBaseModel and GetModel among many controllers, extract it out to a ModelProvider or something similar that is supplied to each controller, ideally through dependency injection.

Rohan Singh
  • 20,497
  • 1
  • 41
  • 48
-1

I think you'll need to start by making your view strongly typed:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Namespace.XData>" %>

and in your controller:

 public ActionResult Foo()
    {
        var X = new XData();
        X.User = ....;
        X.SomeProperty = ...;
        X.Message = "Hello world!";
        return View(X);
    }

which allows you to access the object in your view like so:

<%: Model.User.UserName %>
<%: Model.Message %>
asfsadf
  • 3,822
  • 7
  • 31
  • 41