MVC4 Models Best Practice Database v View Models (Submitted for View)

I want to start with good habits from the beginning, so I have this question and problem:

I do the following which works, then I read this post

Here

This example of what I was doing:

CONTROLLER

public ActionResult OneDollar130(Int32 number)
{
    MyEDM db = new MyEDM();
    MyDBModel model = db.MyTable.Where(t => t.Current == 1 && t.No == number).First();
    return View(model);
}

      

VIEW

@model MyProject.MyDBModel
<table>
  <tr>
    @if (Model.fldNo1 == "")
    {
        <td class="numberTD">
            @Html.ActionLink("1", "Number1", "Number", new { model = Model, number = 1 }, null)
        </td>
    }
    else
    {
        <td class="numberTD2">
            @Html.ActionLink("1", "Number2", "Number", new { model = Model, number = 1 })
        </td>
     }
  </tr>
</table>

      

I am using a model from my EDM and passing it to the view.

In the post above, I read that I should not pass database models to the view, as it is bad practice. This concerns me somewhat, since I want to do it right.

So, based on the above post, I change my code to experiment and hit:

CONTROLLER

public ActionResult OneDollar112(Int32 TableNo)
{
    return View(new getOneDollar112Game(TableNo));
}

      

MODEL

public class getMyModel
{
    MyEDM db = new MyEDM();
    public MyDBModel MyModel { get; set; }

    public getMyModel() { }
    public getMyModel(Int32 number)
    {
        MyModel = db.MyTable
            .Where(t => t.Current == 1 && t.No == numbner).First();
    }
}

      

VIEW

@model MyProject.Models.getMyModel
<table>
  <tr>
    @if (Model.fldNo1 == "")
    {
        <td class="numberTD">
            @Html.ActionLink("1", "Number1", "Number", new { model = Model, number = 1 }, null)
        </td>
    }
    else
    {
        <td class="numberTD2">
            @Html.ActionLink("1", "Number2", "Number", new { model = Model, number = 1 })
        </td>
    }
  </tr>
</table>

      

So my 2 questions:

  • What's the best practice ... does what I did before breaking the rule of not passing DB models to the view?

  • If the second method is correct (which I am assuming), why am I constantly getting the error that fldNo1 does not exist?

eg: CS1061: "MyProject.Models.getMyModel" does not contain a definition for "fldNo1" and does not use the "fldNo1" extension method taking a first argument of type "MyProject.Models.getMyModel" (are you missing using a directive or assembly reference?)

+3


source to share


3 answers


1) I edited your code.

Act:

public ActionResult OneDollar112(Int32 tableNo)
{
    return View(new OneDollar112ViewModel(tableNo));
}

      

Model:



public class OneDollar112ViewModel
{
    private static MyEDM db = new MyEDM();
    private MyDBModel myModel;

    public string fldNo1 
    {
        get 
        { 
            return myModel == null
                ? myModel.fldNo1
                : null;
        }

        set 
        {
            // Your set logic here 
        }
    }    

    public OneDollar112ViewModel(Int32 number)
    {
        myModel = db.MyTable
            .Where(t => t.Current == 1 && t.No == numbner).SingleOrDefault();
    }
}    

      

View:

@model MyProject.Models.OneDollar112ViewModel
<table>
    <tr>
    @if (Model.fldNo1 == "")
    {
        <td class="numberTD">
            @Html.ActionLink("1", "Number1", "Number", new { model = Model, number = 1 }, null)
        </td>
    }
    else
    {
        <td class="numberTD2">
            @Html.ActionLink("1", "Number2", "Number", new { model = Model, number = 1 })
        </td>
    }
    </tr>
</table>

      

2) You should use view models to decouple your business logic from the data layer that you could encapsulate in services and use dependency injection in the future.

0


source


I also don't like using database objects as models.

What I am doing relies on the MVC framework in my project.

Views

- contains views

Models

- contains models intended for presentation



Controllers

- contains a controller also responsible for translating between the database and the view model.

In my controllers, I add repositories (see repository pattern ) to communicate with the database. If I wanted to show the user in my opinion, I would get something like this

public ActionResult Show()
{
    // entity model
    var user = _userRepository.GetUserByName(User.Identity.Name);

    // translate to view model
    var model = new User
    {
        Name = user.Name,
        EmailAddress = user.EmailAddress
    }
    // Send the view model to the view
    return View(model);
}

      

Does it help?

+4


source


You must have separate Models and ViewModels for at least two reasons:

1. Safety

The default binder in MVC binds to any relevant data fields after entering the model properties. This provides security integrity, which can be exploited if you have properties that are not intended to be updated, but are in the model (for example, fake messages with property names that are not normally displayed)

By using the ViewModel and explicitly passing every required property from the ViewModel to the actual model you are defending against this attack vector

2. Complexity

Most sensible applications will require many models and collections of models to view

eg. A basic CRM customer view can have: customer details but not ratings, a list of names and phone numbers, a summary list of recent transactions, a list of registered products, etc. They can exist in a complex set of objects with names and phone numbers in different models, the last transactions can be the order number, the total number of order lines, and only the first three SKUs, etc.

The ViewModel allows you to create only the parts and summaries needed to be displayed from the model caches and static data. The result should simplify the workflow for creating the view and make it much more testable.

Typically, the inheritance path from simple ViewModels to the final complex ViewModel is actually used

+1


source







All Articles