Models

.ASP.NET Models

Web page by Kevin Harris of Homer IL

Please contact Kevin Harris of Homer IL concerning this web site

Models

"Models represent knowledge. A model could be a single object (rather uninteresting), or it could be some structure of objects. There should be a one-to-one correspondence between the model and its parts on the one hand, and the represented world as perceived by the owner of the model on the other hand."Trygve Reenskaug, Dec. 1979


In ASP.NET MVC, Models are defined as classes which are responsible for data. Models can contain domain data (i.e. in business applications that would be the business data) or data that is grouped together for a special purpose, such as the View Models which provide data to display on the screen. Models typically retrieve data from a persistent store, such as a database or a web service. Models may also contain methods for manipulating the data. Models obtain and manipulate data and then pass the data to other components. Domain objects can be custom objects created by the developer or entity models create by Object Rational Mappers (ORMs). In addition to Domain and View Models, Data Transfer Objects (DTOs) are a type of model which is used for transferring batches of data to processes (usually remote processes) or between layers within a system. DTO's differ from other models in that they are just data contains and do not have business logic for manipulating the data. Many applications will employ a combination of these different types of models.

Model Binders are mechanisms for mapping HTTP request data (e.g. data posted in a form or passed in a query string) to action method parameters and objects (e.g. a .NET Model). This is a convenience that alleviates the developer from having to dig through the Request.Form values to manually map the data in the action method. The default model binder in MVC works well in most cases, but there are times when a custom model binder must be created. An example of where a custom model binder is required is when a data type conversion is required between the data store and the displayed data. Custom model binders implement the IModelBinder interface and are registered in the Application_Start method in the Global.asax.cs file.

Models do not have the strict conventions found with other MVC components, such as Views and Controllers. The default MVC template will create a Models folder, but the models do not have to reside in this folder. In fact the model classes are often implemented in a different assembly entirely, to create a Data Access Layer. Once models are created, they can be used in Visual Studio to automatically scaffold views which are strongly typed to the model, for various actions (Create, Display, Edit, Delete).


Example Application Showing Model Creation and Usage

An example web application (CathySite.sln) is used to demonstrate the creation of models, and their associated controllers and views, for the CRUD operations of a database table. The application was created in Visual Studio 2015 using .NET 4.5.2, MVC 5.2.3 and Entity Framework 6.1.3. Two of the projects in the application are the CathySite.Web (MVC project) and CathySite.DAL (Class Library for Data Access Layer). The entity objects from Entity Framework are used as the Models for the views. The entity objects represent two related tables (bill and period) from a remote MySQL database. In the CathySite.Web project, the Models folder, which was created as part of the MVC project template, was deleted. Only View Models are stored in the CathySite.Web project. The domain models are stored in a separate assembly (CathySite.DAL).

.Data Project


Data Project in Example Application

.Web Project


Web Project in Example Application

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace CathySite.DAL.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class bill
    {
        public int ID { get; set; }
        public string Payee { get; set; }
        public decimal Amount { get; set; }
        public int PeriodID { get; set; }
        public System.DateTime Date { get; set; }
        public decimal Balance { get; set; }
    
        public virtual period period { get; set; }
    }
}


CathySite.DAL.Models.bill.cs Entity Class

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace CathySite.DAL.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class period
    {
        public period()
        {
            this.bills = new HashSet<bill>();
        }
    
        public int ID { get; set; }
        public string Name { get; set; }
         
        public virtual ICollection<bill> bills { get; set; }
    }
}


CathySite.DAL.Models.period.cs Entity Class


List View

To create a listing of the bills, the following LINQ code was used in the Index() action method to retrieve the 10 most recent bills. Then a new List view was created using scaffolding. The view was strongly typed to the model (i.e. the bill entity class).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Linq;
using System.Web.Mvc;
using CathySite.DAL.Models;

namespace CathySite.Web.Controllers
{
    public class BillController : Controller
    {
        // GET: Bill
        public ActionResult Index()
        {
            using (var ctx = new CathySiteEntities())
            {
                var bills = ctx.bills
                    .Include("period")
                    .OrderByDescending(b => b.Date)
                    .Take(10)
                    .ToList();
                return View(bills);
            }
        }


Index Action Method inside BillController.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@model IEnumerable<CathySite.DAL.Models.bill>

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Payee)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Amount)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Date)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Balance)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.period.Name)
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Payee)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Amount)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Date)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Balance)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.period.Name)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
                @Html.ActionLink("Details", "Details", new { id=item.ID }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.ID })
            </td>
        </tr>
    }
    
    </table>
</body>
</html>


The Bill List View (Index.cshtml)


Details View

To create a detail view of the bills, the following LINQ code was used in the Details() action method. Then a new Detail view was created using scaffolding. The view was strongly typed to the model (i.e. the bill entity class).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
        // GET: /Bill/Details/id
        public ActionResult Details(int id)
        {
            using (var ctx = new CathySiteEntities())
            {
                var bill = ctx.bills
                    .Include("period")
                    .Where (b => b.ID == id)
                    .FirstOrDefault();
                return View(bill);
            }
        }


Details Action Method inside BillController.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
@model CathySite.DAL.Models.bill

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Details</title>
</head>
<body>
    <div>
        <h4>bill</h4>
        <hr />
        <dl class="dl-horizontal">
            <dt>
                @Html.DisplayNameFor(model => model.Payee)
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.Payee)
            </dd>
    
            <dt>
                @Html.DisplayNameFor(model => model.Amount)
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.Amount)
            </dd>
    
            <dt>
                @Html.DisplayNameFor(model => model.Date)
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.Date)
            </dd>
    
            <dt>
                @Html.DisplayNameFor(model => model.Balance)
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.Balance)
            </dd>
    
            <dt>
                @Html.DisplayNameFor(model => model.period.Name)
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.period.Name)
            </dd>
    
        </dl>
    </div>
    <p>
        @Html.ActionLink("Edit", "Edit", new { id = Model.ID }) |
        @Html.ActionLink("Back to List", "Index")
    </p>
</body>
</html>


The Detail View (Details.cshtml)


Create View

For the Create view, to insert new data into a the bill row in the database, the following LINQ code was used in the Create() action method. An action method was created to display the empty fields for data entry (GET), then another action method was created for posting the entered data (POST). The view was created using using the Create template for scaffolding. The view was strongly typed to the model (i.e. the bill entity class). Note, the action method specifies the ID field should be excluded (i.e. blacklisted) which will protect the field from modification.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   // GET: Bill/Create
        [HttpGet]
        public ActionResult Create()
        {
            return View();
        }

        // POST: Bill/Create
        [HttpPost]
        public ActionResult Create([Bind(Exclude="ID")] bill Bill)
        {
            if (ModelState.IsValid)
            {
                using (var ctx = new CathySiteEntities())
                {
                    bill theBill = new bill();
                    theBill.ID = Bill.ID;
                    theBill.Payee = Bill.Payee;
                    theBill.Amount = Bill.Amount;
                    theBill.PeriodID = Bill.PeriodID;
                    theBill.Date = Bill.Date;
                    theBill.Balance = Bill.Balance;
                    ctx.bills.Add(theBill);
                    ctx.SaveChanges();
                    return RedirectToAction("Index");
                }
            }
            return View("bill");
        }


Create Action Method inside BillController.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
@model CathySite.DAL.Models.bill
@{
//Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Create</title>
    <script>
        function ResetForm() {
            document.getElementById('txtPayee').value = "";
        }
    </script>
</head>
<body>
     @*For MVC Model Binder to work, "name=" must equal class name, 
     else use 'Request.Form["myName"]', or create a custom binder*@
    <form action="/Bill/Create" method="post">
        <br /><br />
        <div style="width:100%; padding-left: 200px;">
            <div style="width:90%">
                <table>
                    <tr>
                        <td>Payee: </td>
                        <td><input type="text" id="txtPayee" name="Payee" value="" /></td>
                    </tr>
                    <tr>
                        <td colspan="2" align="right">
                            @Html.ValidationMessage("Payee")
                        </td>
                    </tr>
                    <tr>
                        <td> Amount: </td>
                        <td><input type="text" id="txtAmount" name="Amount" value="" /></td>
                    </tr>
                    <tr>
                        <td colspan="2" align="right">
                            @Html.ValidationMessage("Amount")
                        </td>
                    </tr>
                    <tr>
                        <td>PeriodID: </td>
                        <td><input type="text" id="txtPeriodID" name="PeriodID" value="" /></td>
                    </tr>
                    <tr>
                        <td colspan="2" align="right">
                            @Html.ValidationMessage("PeriodID")
                        </td>
                    </tr>
                    <tr>
                        <td>Date:</td>
                        <td><input type="text" id="txtDate" name="Date" value="" /></td>
                    </tr>
                    <tr>
                        <td colspan="2" align="right">
                            @Html.ValidationMessage("Date")
                        </td>
                    </tr>
                    <tr>
                        <td>Balance:</td>
                        <td><input type="text" id="txtBalance" name="Balance" value="" /></td>
                    </tr>
                    <tr>
                        <td colspan="2" align="right">
                            @Html.ValidationMessage("Balance")
                        </td>
                    </tr>
                </table>
                <div style="float: left; padding-left: 50px">
                    <br />
                    <input type="submit" name="btnSubmit" value="Save" />
                    <input type="submit" name="btnSubmit" value="Cancel" />
                    <input type="button" name="btnReset" value="Reset Form" onclick="ResetForm();" />
                </div>
            </div>
        </div>
    </form>
    <br /><br />

    <form action="" method="post" id="frmBill">
        <div style="float: left; clear: both; padding-left: 50px">
            <br />
            <input type="submit" value="PrevPay" onclick="document.getElementById('frmBill').action='/Bill/ShowPrevPayment'" />
        </div>
    </form>
    <br /><br />
</body>
</html>


The Create View (Create.cshtml)


Delete View

For the Dele view

, to insert new data into a the bill row in the database, the following LINQ code was used in the Create() action method. An action method was created to display the empty fields for data entry (GET), then another action method was created for posting the entered data (POST). The view was created using using the Create template for scaffolding. The view was strongly typed to the model (i.e. the bill entity class). Note, the action method specifies the ID field should be excluded (i.e. blacklisted) which will protect the field from modification.


Delete Action Method inside BillController.cs


The Delete View (Delete.cshtml)


Edit View

For the Edit view,

to insert new data into a the bill row in the database, the following LINQ code was used in the Create() action method. An action method was created to display the empty fields for data entry (GET), then another action method was created for posting the entered data (POST). The view was created using using the Create template for scaffolding. The view was strongly typed to the model (i.e. the bill entity class). Note, the action method specifies the ID field should be excluded (i.e. blacklisted) which will protect the field from modification.


Edit Action Method inside BillController.cs


The Edit View (Details.cshtml)

Error | ASP.NET Developer

Error

Error message

  • Warning: Cannot modify header information - headers already sent by (output started at /srv/disk9/1218369/www/kcshadow.net/aspnet/includes/common.inc:2748) in drupal_send_headers() (line 1232 of /srv/disk9/1218369/www/kcshadow.net/aspnet/includes/bootstrap.inc).
  • PDOException: SQLSTATE[42000]: Syntax error or access violation: 1142 INSERT command denied to user '1218369_b2cf'@'185.176.40.58' for table 'watchdog': INSERT INTO {watchdog} (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array ( [:db_insert_placeholder_0] => 0 [:db_insert_placeholder_1] => cron [:db_insert_placeholder_2] => Attempting to re-run cron while it is already running. [:db_insert_placeholder_3] => a:0:{} [:db_insert_placeholder_4] => 4 [:db_insert_placeholder_5] => [:db_insert_placeholder_6] => http://www.kcshadow.net/aspnet/?q=models [:db_insert_placeholder_7] => [:db_insert_placeholder_8] => 54.162.171.242 [:db_insert_placeholder_9] => 1534727875 ) in dblog_watchdog() (line 160 of /srv/disk9/1218369/www/kcshadow.net/aspnet/modules/dblog/dblog.module).
The website encountered an unexpected error. Please try again later.