Now that we have a Controller and a View in our application, it is time to start filling in the last component of the MVC architecture, the Model. In this module we are going to start modeling our domain, or business domain, using C# POCOs (Plain Old C# Objects).
In our case the business domain is a local car dealership.
Model the Domain with C# POCO objects
To start with all we need is a Vehicle
entity class and a VehicleType
entity class both represented as C# POCOs in our Web project.
Create the Models folder
Create a folder named Models in the root of the FredsCars project.

Create the POCO classes
The VehicleType class
In the new Models folder, add a class file named VehicleType.cs
by right clicking on the Models folder and selecting Add -> Class...
.

In the Add New Item
dialogue, name the file VehicleType.cs
and click the Add button.

Replace it’s contents with the code shown below.
FredsCars/Models.VehicleTypes.cs
namespace FredsCars.Models
{
public class VehicleType
{
public int Id { get; set; }
// ["Car", "Truck", "Jeep"]
public string Name { get; set; } = string.Empty;
// Entity Framework Navigation Property
public ICollection<Vehicle> Vehicles { get; set; } =
new List<Vehicle>();
}
}
In the code above, we have a new class called VehicleType
with three properties.
The first property is an integer called Id. An integer DataType in C# holds whole numbers like 0, 1, 2, and so on. It can also hold negative whole numbers like -1, -2, and -3. The int DataType can store values from from -2,147,483,648 to 2,147,483,647. The Id property of VehicleType is called a Primary Key. It holds a unique value for each VehicleType. You can think of the primary key as the unique identifier for each VehicleType.
The second property is a string called Name. It will hold the name of each category type of Vehicle (Car, Truck, or Jeep). A string stores a sequence of characters, surrounded by double quotes.
The third property is a navigation property for Entity Framework Core. We will talk about this in a later section in this module.
C# Class Properties
You can tell these two members, Id and Name, are properties in a C# class because of the get and set accessors in the property’s code block, between the two squiggly lines.
{ get; set; }
This is a newer feature in C# called Auto Properties. Before Auto Properties the code above would have looked like the following.
public class VehicleType
{
private int _id;
private string _name = string.Empty;
public int Id
{
get
{
return _id;
}
set
{
_id = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
}
C# Member Fields
The sample code above declares two member fields, _id and _name, of type int and string respectively for the class. It then declares two properties of the same names, Id and Name, but with different casing, and without the preceding underscore character, ‘_’.
This type of software pattern and syntax protects the actual data and integrity of the class state stored in the private fields, _Id and _Name, and forces the user, or calling code, of the class to go through the public get/set accessor properties, Id and Name.
This can be thought of as an API for the class or an Application Programming Interface. Programmers using the class have to go through the public properties to interact with the data and state of the class.
This full accessor syntax is still available and allows us to add extra logic to the get/set accessors if needed, for instance validation when setting a value.
C# Auto Properties
Let’s take another look at the C# Auto Property pattern.
FredsCars/Models.VehicleTypes.cs
public class VehicleType
{
public int Id { get; set; }
// ["Car", "Truck", "Jeep"]
public string Name { get; set; } = string.Empty;
}
When we use the get/set accessor auto properties pattern, C# sets up private backing stores behind the scenes. So the _id and _name private fields actually exist (although C# may not name these fields exactly as we would under the hood). But we are still forcing the calling code to go through the public members, in this case properties, to access those private backing store fields.
C# Member Types
We have now seen the three basic members a C# class can have.
- Field
- Property
- Method (or function)
Remember each type of member can have any of the access modifiers such as private, public, protected, internal, and internal protected we talked about earlier.
Class Member Naming Conventions.
There are two basic types of naming schemes. Pascal case and Camel case.
Pascal case: Capitalizes the first letter of each word in a compound word, including the first word. For example, “PascalCase”.
Camal case: Capitalizes the first letter of each word in a compound word, excluding the first word. For example, “camelCase”.
Private member fields (also known as instance fields because we create object instances of the class) such as _id and _name are Camel case and preceded by an underscore character, ‘_’.
Some programmers no longer use the underscore character. I prefer to use it because other types of variables also use Camel case and it can become confusing whether or not a variable is a private field of the class or not.
Class names and Namespace names are Pascal case.
Properties are Pascal case.
Function names are Pascal case.
Function parameters (arguments) are Camel case (without the underscore).
Variables declared inside of functions are Camel case (without the underscore).
Public fields are Camel case (without the underscore).
Namespaces autogenerated in Visual Studio
Notice the namespace that was generated by Visual Studio when we created the VehicleType class.
namespace FredsCars.Models
Visual Studio generates the namespace of a class by using the folder hierchy structure and folder path the class is created in. Here we created the VehicleType class in the Models folder under the root of the FredsCars project.
/FredsCars/Models
We are free to change the autogenerated namespace to anything we want. But I usually just stick with the default unless there is good reason to change it.
The Vehicle class
In the Models folder add a second class called Vehicle.cs with the code below.
/FredsCars/Models/Vehicle.cs
namespace FredsCars.Models
{
public enum Status
{
New,
Used
}
public class Vehicle
{
public int Id { get; set; }
public Status Status { get; set; }
public string Year { get; set; } = string.Empty;
public string Make { get; set; } = string.Empty;
public string Model { get; set; } = string.Empty;
public string Color { get; set; } = string.Empty;
public double Price { get; set; }
public string VIN { get; set; } = string.Empty;
// Foriegn Key to VehicleType entity/table row
public int VehicleTypeId { get; set; }
// Entity Framework Navigation Property
public VehicleType VehicleType { get; set; } = null!;
}
}
In the code above, we actually have defined two C# types. The first is an enum called Status. The second is our Vehicle class.
Enums, or enumerations, are a special kind of value type in C# that let you specify a group of named constants, making your code more readable and less error-prone.
The Status enum contains two values; New and Used.
We can use the enum Status type for the Status property in the Vehicle class rather then setting it up as a simple string. Otherwise, having to type in “New” or “Used” for every vehicle would get old very soon, I am sure.
NOTE: There are five Types in C#; class, structure, interface, enumeration, and delegate. We will be using mostly classes and interfaces. But, we also got to see an enumeration here in the Vehicle class.
The second type in the Vehicle.cs class file is the Vehicle class. We have defined ten properties for the class.
Again we have an integer ID property as our primary key (or PK in database terms).
Next we have a property called Status of type Status (our enum type) that will contain the values New or Used
Status.New
or
Status.Used
Next we have defined four properties of type String; Year, Make, Model, and Color.
For the Price property we have a new data type, double. A double stores fractional numbers rather then whole numbers.
Following the Price property we have one more String property called VIN.
The ninth and tenth properties are for Entity Framework Core. We will talk about this in a later section in this module.
More on C# DataTypes
As I have already touched on earlier, any property or variable in C# must be a specified data type. Here is a list of the most common data types.
Data Type | Size | Description |
---|---|---|
int | 4 bytes | Stores whole numbers from -2,147,483,648 to 2,147,483,647 |
long | 8 bytes | Stores whole numbers from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
float | 4 bytes | Stores fractional numbers. Sufficient for storing 6 to 7 decimal digits |
double | 8 bytes | Stores fractional numbers. Sufficient for storing 15 decimal digits |
bool | 1 byte | Stores true or false values |
char | 2 bytes | Stores a single character/letter, surrounded by single quotes |
string | 2 bytes per character | Stores a sequence of characters, surrounded by double quotes |
You can read more about data types here at w3schools.
C# Nullable types
Notice in the Vehicle class I have initialized the value of all our String type properties to String.Empty
.
If you remove the “= string.Empty
” portion from one of the string properties declarations, a green squiggly appears over the property name.

A green squiggly is just a warning so our code would still work. But lengthy warning descriptions will show up in our console window running the application making troubleshooting and reading feedback more difficult.
A red squiggly would signify an error.
If you hover over the property name with the green squiggly, in this case Year, you see an error message that reads:
Non-nullable property ‘Year’ must contain a non-null value when exiting constructor. Consider adding the ‘required‘ modifier or declaring the property as nullable.
If we wanted to make the Year property required, we could declare the Year property with the required
keyword.
public required string Year { get; set; }
Or, if we wanted to declare that the Year property can remain null, we could declare it with the nullable character, a question mark after the type, ‘?
‘.
public string? Year { get; set; }
NOTE: The default value of a nullable type is null unless it is explicitly set to a value like the following.
public string? Year { get; set; } = "2000";
You can also initialize a nullable property to null or set it to null if it contained another value.
public string? Year { get; set; } = null;
Sometimes we call this clearing out or nulling out the value.
I haven’t decided yet to either make the property required or nullable so I am initializing the string property to a special value called String.Empty
in order to get rid of the warning.
The way C# handles nulls and nullable features can be a hard concept to wrap your mind around. I will try to touch more on this concept as we go.
Code Review
Let’s take a minute to discuss some of the design decisions in our first two entity classes.
Revisit the Vehicle class
The Vehicle Entity class uses the same properties we thought of as vehicle attributes way back in chapter one.
NOTE: I refer to Vehicle and VehicleType as Entity classes because they are going to be our entities and entity sets in Entity Framework Core. Entity Sets represent tables in a database and Entities represent the rows in a database. But, more on that soon.
For the Status property I use a C# enum with the values New or Used. I doubt the status of a vehicle will ever have any other value so it’s not worth breaking out that property to its own class or database table. But we do strongly type it as an enum rather than just use the string values of “New” and “Used”. This way we can avoid any stupid human typing errors and get to use IntelliSense as we are typing to select the correct value.

Revisit the VehicleType class
The VehicleType property in the Vehicle Entity class should be able to hold one of the values of “Car”, Truck”, or “Jeep”. But I can see the possibility of another category being added in the future. However, we don’t want to use an enum here because then if a user wanted to add a new type of vehicle, they would have to ask a developer to add it in, then it would have to be recompiled and redeployed. So the user would have to wait until the next release to use the new type of vehicle. For that reason, we create a separate class called VehicleType with a Name property. The VehicleType.Name property will hold the value of either, “Car”, “Truck”, or “Jeep”.
Meanwhile, back in the Vehicle Entity class, we access a VehicleType with these two properties:
public int VehicleTypeId { get; set; }
public VehicleType VehicleType { get; set; } = null!;
Once we get to using Entity Framework Core to create the database and access data from within our code, we’ll see that the VehicleType property is a navigation property and will hold a VehicleType object as its value. The VehicleTypeId property is a foreign key used to locate the specific VehicleType object in the database to fill the VehicleType property.
What’s Next
Well! We certainly did a lot in this module. We got a good start modeling out our business domain, set up our C# POCO’s for Entity Framework, and continued to build up our C# knowledge.
In the next module, we are going to set up Entity Framework Core and create the database.