简体   繁体   中英

MVC4 Best Practice Database Models v View Models (passed to view)

I want to get into good habits from the start so I have this question and a problem:

I have been doing the following which has been working, then I read this post

Here

This example of what I have been 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 the model from my EDM and passing it to the View.

I read in above post that I should not pass my database models to the view as this is bad practice. This concerns me somewhat as I want to be doing it right.

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

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>

Okay so my 2 questions are:

  1. Which is the best practice ... does what I was doing before break the rule of not passing DB models to the view?

  2. If the second method is correct (which I am supposing) why do I continually get the error that fldNo1 does not exist?

eg: CS1061: 'MyProject.Models.getMyModel' does not contain a definition for 'fldNo1' and no extension method 'fldNo1' accepting a first argument of type 'MyProject.Models.getMyModel' could be found (are you missing a using directive or an assembly reference?)

I am also not fond of using database objects as models.

What I do, is rely on the MVC structure in my project.

Views - contains views

Models - contains the models, dedicated for the view

Controllers - contain the controller, also responsible for making the translation between database and view models.

In my controllers I add repositories (see Repository Pattern ) to communicate with the database. If I would like to show a user in my view I'd end up with 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 that help?

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

1. Security

The default model binder in MVC will bind with any matching post data fields to Model properties. This provides a security whole that can be exploited if you have properties that are not meant to be updated, but are in the Model (eg fake a post back with the property names that are not normally displayed)

By using a ViewModel and explicitly passing each required property from ViewModel to the actual Model you defend against this attack vector

2. Complexity

Most reasonable applications will require a multitude of models and model collections per view

eg a basic CRM customer view might have: customer details, but not scores, list of names and phone numbers, summary list of recent transactions, list of products registered etc. These might exist in a complex collection of objects, with names and phone numbers in different models, recent transactions might be order number, total number of order lines, and only first three SKU codes etc.

A ViewModel allows you to build up just the parts and summaries needed for display from the Models and static data caches. The result should simplify the workflow to build a view, and make it much more testable

There is normally a path of inheritance from simple ViewModels to the final complex ViewModel actually used

1) I edited your code.

Action:

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 separate your business logic from your data layer which you could encapsulate in services and in the future take advantage of dependency injection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM