1

I'm new to ASP.NET MVC and just curious what is the best practise for next scenario. I would to pass query result to a view:

public class HomeController : Controller
{
  public ActionResult Index() // show last 3 posts from the database
  {
    DB db = new DB(); // DB is just a tiny wrapper to work with LocalDB sql database
    db.openConnection(ConfigurationManager.ConnectionStrings["PostDBContext"].ConnectionString);      
    db.select(@"select p.id, p.title, p.content, FORMAT(p.created_at, 'yyyy-MM-dd') as created_at, u.firstname,
                                u.lastname, c.name
                       from posts p
                               inner join users u on (u.id = p.created_by)
                               inner join categories c on (c.id = p.category_id)
                       where p.visibility = 'public'
                       order by p.id desc limit 3");

  while( db.read() > 0 ) // reads one row
  {
    ....
  }
  db.closeConnection();
  return View();
}

I've read several articles about how to pass data from controller to a view. Every article mentions that the best and recommended way is to pass data from Model to View or create ViewModels. So using this approach means that I need to create a ViewModel and a Model, something like this:

public class FullPostViewModel
{
  public List<FullPost> Posts { get; set; }
}

public class FullPost
{
  public int id;
  public string title;
  public string content;
  public string created_at;
  public string author_firstname;
  public string author_lastname;
  public string category;
}

And then in controller:

....
FullPostViewModel model = new FullPostViewModel();

while( db.read() > 0 ) // reads one row
{
  model.Posts.Add( new FullPost(){id = Convert.ToInt32(db[0]), title = db[1], ....});
}
...
return View(model);

Or is it better to make three Models: Post, Category, User and then the FullPost contains something like this:

public class FullPost
{
  public Post p;
  public Category c;
  public User u;
}

If you have for example even more complex query (3, 4, ... joins), this would mean to create new class for each table. Well of course it makes sense to create one class for each table, because this is what ORM is all about.

I just want to know if is using Models/ViewModels always a best practise for showing query results (I'm aware of ViewBag for simple and small data)? In Laravel (PHP) I often didn't use Models when it came to queries which involved joins. It just seemed easier which doesn't mean its ok.

broadband
  • 3,266
  • 6
  • 43
  • 73
  • You don't necessarily need the `FullPostViewModel` model. You can just pass `List` to the view. –  Aug 28 '15 at 12:23
  • Your first code sample doesn't send *anything* to the view. So I'm not really sure what that's even illustrating. Any type can be used as a view model, including the result of your query. You'd want to make a custom view model when you want to transform the data to something specific to that view, or include functionality specific to that view. If the view is just binding to back-end types, you can just send it the result of your back-end query. – David Aug 28 '15 at 12:24
  • 2
    Refer also [What is ViewModel in MVC?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) –  Aug 28 '15 at 12:25
  • @StephenMuecke thank you for the post about what is viewmodel in mvc. – broadband Aug 28 '15 at 13:06
  • @David I need to store query result to some datastructure List, ... SqlDataReader works as unbuffered stream of data. It is neccessary to close SqlDataReader and it is preffered to now write logic in the view (SqlDataReader.Close()). As for the first code, I just wanted to show what I'm trying to do (example query, ....). – broadband Aug 28 '15 at 13:13
  • @broadband: It's definitely a good idea to use actual models instead of things like data readers and data tables. Ideally this would happen in a data access component in the infrastructure layer rather than in the controller, but for simple enough projects it's not a big deal. But you definitely want to be using real objects and not database components by the time you get to the view. – David Aug 28 '15 at 13:21

2 Answers2

2

I recommend that you just pass as much or less data you need to render your view. Since you can create many view models you are free to put properties in them as you like.

For example:

When you want to show a list of Post: return View(List<LightWeightFullPost>) When you want to show a post in detail: return View(FullPost)

For the LightWeightFullPost you could just send the Name of the Post and the Author. This will keep the Data you send as small as possible, since you don't want to show every detail on the List View.

Also passing complex objects in a ViewModel is only recommended, when you really need it. For example: do you really need the complete Category Object when responding the FullPost ViewModel? Or is a CategoryId enough?

sebastian
  • 813
  • 1
  • 7
  • 14
1

1) Divide your application in layers. Don't put SQL queries in Controllers, do that in a Service Layer.

2) You can return business objects to Views but it's better and more flexible to return ViewModels. That way you don't need to send any extra fields that you don't need and you can mix multiple classes into one. Also, you can deal with formatting in the Controller if you want.

3) If your View has logic all over the place, think again, you're probably doing it wrong. Try to have simple views, that just take care of the HTML and displaying properties.

Based on one comment, I add extra information below: Sometimes you need to format a decimal or DateTime property or combine several properties into one. It's better to that in the Controller than in the View. Let's say you need to display an amount, including currency and decimal numbers. You can do that in the View or in the Controller. If you do it in the View, you'll have more logic in the View. Then, if you have a different view for the same page (for example a Mobile view for that page) you need to do it twice or create a Partial View for that. If you do it in the Controller you do it once and you can easily test it.

Francisco Goldenstein
  • 13,299
  • 7
  • 58
  • 74
  • I agree with point 3 about simple views. Don't fully understand what do you mean with formatting in the Controller. – broadband Aug 28 '15 at 13:04
  • Sometimes you need to format a decimal or DateTime property or combine several properties into one. It's better to that in the Controller than in the View. Let's say you need to display an amount, including currency and decimal numbers. You can do that in the View or in the Controller. If you do it in the View, you'll have more login in the View. Then, if you have a different view for the same page (for example a Mobile view for that page) you need to do it twice or create a Partial View for that. If you do it in the Controller you do it once and you can easily test it. – Francisco Goldenstein Aug 28 '15 at 13:43