0% found this document useful (0 votes)
9 views

Unit-4 Creating ASPdotnet Core MVC Application2

Uploaded by

lastminprep2022
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

Unit-4 Creating ASPdotnet Core MVC Application2

Uploaded by

lastminprep2022
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 27

The Model

The model classes represents domain-specific data and business logic in the
MVC application. It represents the shape of the data as public properties and
business logic as methods.
A very important aspect of the MVC pattern is the Separation of Concerns.
SoC is achieved by encapsulating information inside a section of code,
making each section modular, and then having strict control over how each
module communicates. For the MVC pattern, this means that both the View
and the Controller can depend on the Model, but the Model doesn't depend
on neither the View nor the Controller. This turns your Models into a module
that can exist even outside of the MVC framework, e.g. for use in a desktop
application, and then it has the added benefit of allowing your Models to be
tested without the visual representation, e.g. through the use of unit tests.
As mentioned, the Model can be a class already defined in your project, or it
can be a new class you add specifically to act as a Model. Therefore, Models
in the ASP.NET MVC framework usually exists in a folder called "Models", or
they come from outside of the project, e.g. from a class library.
Adding a Model
In the ASP.NET Core MVC Application, all the Model classes must be created in
the Models folder.
To create the model class that should have the required properties for
the Employee entity.
In the MVC application in Visual Studio, and right-click on the Models folder,
select Add -> and click on Class... It will open the Add New Item dialog box.

In the Add New Item dialog box, enter the class name Employee and click
Add.
This will add a new Employee class in model folder.

public class Employee


{
public int EmployeeId { get; set; }
}
Model Binding in ASP.NET Core
The Model Binding is a mechanism in ASP.NET Core Application which extracts the
data from an HTTP request and provides them to the controller action method
parameters.
The action method parameters may be simple types like integers, strings, etc. or
complex types such as Student, Order, Product, etc.

Example using Route Data:


Let us understand this with an example. When we want to view the details of a student whose id is
101, then we generally issue a GET request to the following URL.

http://localhost:5000/home/details/101

Our application default route template ({controller=Home}/{action=Index}/{Id?}) routes the above GET
request to the Details(int Id) action method of the HomeController. The following image shows
the Details action method of the Home Controller.

public ViewResult Details(int Id)


{
var studentDetails = listStudents.FirstOrDefault(std => std.StudentId == Id);
return View(studentDetails);
}
Example using Query String:
Let us understand this with an example. First, modify the Details Action
method as shown below. As you can see we made two changes here. First, we
change the return type of the action method to string. Secondly, the Details
method now taking two parameters.

public string Details(int Id, string name)


{
return "Id:" + Id + ", Name: " + name;
}

Now issue a Get Request as shown below.

http://localhost:5000/home/details?id=101&name=dotnet

The above GET request will handle by the Details action method and it will map the value
101 to the Id parameter and the value dotnet will be mapped to the name parameter of the
Details action method.
HTTP Request Data Sources:

ASP.NET Core MVC uses three primary data sources to map the HTTP requests
data to the action method parameter in the following order:

Form values: Values in the FORM in HTTP POST requests.


Route values: Values provided by the Routing system.
Query string: Values found in the URL’s query string (e.g. after ? character).
Model Binding in ASP.NET Core with Complex Type:

The Model Binding in ASP.NET Core Application also works with complex user defined
types like Customer, Student, Order, Product, etc. Let us understand this with a
Create Student form example
Add the following Create method to the Student Controller. When the above form is
posted, this is the method which is going to handle the request. Decorate the
method with HttpPost attribute.

[HttpPost]
public ActionResult Create(Student student)
{
student.StudentId = listStudents.Max(x => x.StudentId) + 1;
listStudents.Add(student);
return View("Details", student);
}
When the form is submitted, the values in the form are mapped to the Student object
parameter to the Post Create action method. The Model binder in asp.net core application
binds the posted form values to the properties of the Student object that is passed as a
parameter to the Create() action method.

The value in the input element that has the name attribute set to “Name” is mapped to the
Name property of the Studnet object. Similarly, the value in the Address input element will
be mapped to the Address property of the Student object. This is going to be same for the
rest of the properties like Email and Gender.
Using Model Binding
Create a simple Model class for handling information about a student

public class Student


{
public string Name { get; set; }
public string City { get; set; }
}
In the Student Controller, we can now pass an instance of this class to the View. In a real-world
application, we would probably get the Student object from a database, but to keep things
simple, we just generate a new one for this demonstration.
[HttpGet]
public IActionResult StudentInfo()
{
return View(new Student() { Name = “Ram”, City = “Kathmandu" });
}
By letting our View know what kind of Model it can expect, with the @model
directive, we can now use various helper methods to help with the generation of a
Form.
@model WebApplication1. Models.Student
@using(var form = Html.BeginForm())
{
<div>
@Html.LabelFor(m => m.Name)
@Html.TextBoxFor(m => m.Name)
</div>

<div>
@Html.LabelFor(m => m.City)
@Html.TextBoxFor(m => m.City)
</div>

<input type="submit" value="Submit" />


}
The result will be a form with the properties of the student model

Note: The ASP.NET Core MVC framework automatically converts request values into a
primitive or complex type object. Model binding is a two-step process. First, it collects
values from the incoming HTTP request, and second, it populates primitive type or a
complex type with these values.
Data Annotations
DataAnnotations is used to configure model classes, which will highlight the most
commonly needed configurations. Sometimes, it can be relevant for a View to know
more about a property on a Model than just its name and type. For these situations,
ASP.NET Core MVC comes with the concept of DataAnnotations (sometimes referred
to as Model Attributes), which basically allows to add meta data to a property.

As an example, we might want to change the display version of the First Name
property to “First Name”

public class Employee


{
[Display(Name="First Name")]
public string FirstName { get; set; }
}
Type of Data Annotations
Model Validation:

A lot of the available DataAnnotations are actually directly related to the validation
mechanisms found in the ASP.NET Core MVC framework. They will allow you to
enforce various kinds of rules for your properties, which will be used in your Views
and in your Controllers, where you will be able to check whether a certain Model is valid
in its current state or not (e.g. after a FORM submission).
public class Employee
{
[Required]
[StringLength(25)]
public string FirstName { get; set; }

[Required]
[StringLength(50, MinimumLength = 3)]
public string LastName { get; set; }

[Required]
[EmailAddress]
public string EmailAddress { get; set; }
}
The three properties have all been decorated with
DataAnnotations, giving the framework useful information for
validating the data. First of all, all properties have been
marked with the [Required] attribute, meaning that a value is
required - it can't be NULL. We have also used the
[StringLength] attribute to make requirements about the
maximum, and in one case minimum, length of the strings.
These are of course particularly relevant if your Model
corresponds to a database table, where strings are often
defined with a maximum length. For the last property, we
have used the [EmailAddress] attribute to ensure that the
value provided looks like an e-mail adress.
@model WebApplication1.Models.Employee
@using(var form = Html.BeginForm())
{
<div>
@Html.LabelFor(m => m.FirstName)
@Html.TextBoxFor(m => m.FirstName)
</div>

<div>
@Html.LabelFor(m => m.LastName)
@Html.TextBoxFor(m => m.LastName)
</div>

<div>
@Html.LabelFor(m => m.EmailAddress)
@Html.TextBoxFor(m => m.EmailAddress)
</div>

<input type="submit" value="Submit" />


}
public class EmployeeController : Controller
{
[HttpPost]
public IActionResult Create(Empoyee employee)
{
if(ModelState.IsValid)
return Content("Model validation success");
else
return Content("Model validation failed");
}

Depending on the data you submitted in the FORM, IsValid property of the
ModelState object will be either true or false, based on the validation rules we
defined for the Model (Employee). With this in place, you can now prevent a Model
from being saved, e.g. to a database, unless it's completely valid.
Displaying validation errors
First of all, we need to extend our FORM so that it can display error messages to the user. We can use another
helper method found on the Html object: The ValidationMessageFor() method. It will simply output the error
message related to the field, if there is one - otherwise, nothing will be outputted. Here's the extended
version of the FORM
@model WebApplication1.Models.Employee
@using(var form = Html.BeginForm())
{
<div>
@Html.LabelFor(m => m.FirstName)
@Html.TextBoxFor(m => m.FirstName)
@Html.ValidationMessageFor(m => m.FirstName)
</div>
<div>
@Html.LabelFor(m => m.LastName)
@Html.TextBoxFor(m => m.LastName)
@Html.ValidationMessageFor(m => m.LastName)
</div>
<div>
@Html.LabelFor(m => m.EmailAddress)
@Html.TextBoxFor(m => m.EmailAddress)
@Html.ValidationMessageFor(m => m.EmailAddress)
</div>
<input type="submit" value="Submit" />
}
We also need to make sure that once the FORM is submitted, and if there are
validation errors, we return the FORM to the user, so that they can see and fix these
errors. We do that in our Controller, simply by returning the View and the current
Model state, if there are any validation errors.

[HttpPost]
public IActionResult Create(Employee employee)
{
if (ModelState.IsValid)
return Content(“Validation Successful");
else
return View(employee);
}
If you try submitting the FORM with a value that doesn't meet the StringLength
requirements, you will notice that there are even automatically generated error
messages for these as well. For instance, if you submit the FORM with a LastName
that's either too long or too short, you will get this message:
An individual error message for each input field can be really useful, especially if you
have a large FORM. However, for smaller forms, it might be more useful to simply
display a summary of the validation errors, either above or below all the fields.
Syntax:
@Html.ValidationSummary()

Types of Model Validation DataAnnotations

[Required]
[StringLength]
[Range]
[Compare]
[EmailAddress]
[RegularExpression]
ViewModels
A ViewModel in ASP.NET Core MVC is a model that is passed to a View, and it is
considered as a ViewModel because it's used by that particular View. In other words,
there doesn't have to be a difference - you can use your Models as ViewModels
interchangeably. however, a lot of situations where you may want to create a specific
ViewModel for a specific View. This can be to extend or simplify an existing Model, or
because you want to represent something in a View that's not already covered by one
of your models.
ViewModels are often placed in their own directory in your project, called
"ViewModels". Again, this is just a convention and since ViewModels are just regular
.NET classes.

When to use a ViewModel?


To represent something in a View that's not already contained by an existing Model:
When you pass a Model to a View, you are free to pass e.g. a String or another
simple
type, but if you want to pass multiple values, it might make more sense to create a
simple ViewModel to hold the data.
Eg:
public class AddressViewModel
{
public string StreetName { get; set; }
public string ZipCode { get; set; }
}
To access the data of multiple Models from the same View: This is relevant in a lot of situations,
e.g. when you want to create a FORM where you can edit the data of multiple Models at the same
time. You could then create a ViewModel as shown below
public class EditItemsViewModel
{
public Model1Type Model1 { get; set; }
public Model2Type Model2 { get; set; }
}

To simplify an existing Model: only expose the parts of model that actually needed for a view.
To extend an existing Model with data only relevant to the View
URL Routing and Features
The Route is similar to a roadmap. We use a roadmap to go to our destination. Similarly, the
ASP.NET Core Apps uses the Route to go to the controller action. The Each Route contains a
Name, URL Pattern (Template), Defaults and Constraints. The URL Pattern is compared to the
incoming URLs for a match. An example of URL Pattern is {controller=Home}/{action=Index}/{id?}

The Routing in ASP.NET Core MVC is a mechanism which inspects the incoming http request
and maps them to Controller Actions. It also used to generate the outgoing URLs. This
process is handled by the Routing Middleware. The Routing Middleware is available in
Microsoft.AspNetCore.Routing Namespace.
The Routing has two main responsibilities:
1) It maps the incoming requests to the Controller Action
2) Generate an outgoing URLs that correspond to Controller Action
How Routing Works
When the Request arrives at the Routing Middleware it does the following.
• It Parses the URL.
• Searches for the Matching Route in the RouteCollection.
• If the Route found then it passes the control to RouteHandler.
• If Route not found, it gives up and invokes the next Middleware.
What are the different types of Routing supported by ASP.NET Core MVC?
In ASP.NET Core MVC application, you can define routes in two ways. They are as
follows:
1) Convention Based Routing
2) Attribute-Based Routing.

What is Conventional Based Routing in ASP.NET Core MVC Application?


In Conventional Based Routing, the route is determined based on the conventions
defined in the route templates which will map the incoming Requests (i.e. URLs) to
controllers and their action methods. In ASP.NET Core MVC application, the
Convention based Routes are defined within the Configure method of the Startup.cs
class file.

What is Attribute-Based Routing in ASP.NET Core MVC Application?


In Attribute-Based Routing, the route is determined based on the attributes which are
configured either at the controller level or at the action method level. We can use
both Conventional Based Routing and Attribute-Based Routing in a single application.
Understanding Conventional Based Routing in ASP.NET Core MVC:

In ASP.NET Core MVC application, it is the controller action method that is going to handle the
incoming Requests i.e. URLs. For example, if we issue a request to the “/Home/Index” URL,
then it is the Index action method of Home Controller class which is going to handle the
request as shown in the below image.

Similarly, if you issue a request to the “/Home/Details/2” URL, then it is the Details action method
of the Home Controller class which is going to process that request as shown in the above image.
Where the parameter value 2 is automatically mapped to the id parameter of the Details action
method.
The request mapping is done by the MVC Middleware which we registered in the application’s
request processing pipeline.
Set up conventional route
Startup.Configure typically has code similar to the following when using conventional
routing:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

Inside the call to UseEndpoints, MapControllerRoute is used to create a single route.


The single route is named default route. Most apps with controllers and views use a
route template similar to the default route.
• The first path segment, {controller=Home}, maps to the controller name.
• The second segment, {action=Index}, maps to the action name.
• The third segment, {id?} is used for an optional id. The ? in {id?} makes it optional.
id is used to map to a model entity.
Attribute Routing in ASP.NET Core MVC Application
With the help of ASP.NET Core Attribute Routing, you can use the Route attribute to
define routes for your application. You can use the Route attribute either at the
Controller level or at the Controller Action Methods level. When you apply the Route
attribute at the Controller level, then it is applicable for all the action methods of that
controller.
Let us modify the Home Controller as shown below. Here we have applied the Route
Attribute at the Action method.
public class HomeController : Controller
{
[Route("")]
[Route("Home")]
[Route("Home/Index")]
public string Index()
{
return "Index() Action Method of HomeController";
}
[Route("Home/Details/{id}")]
public string Details(int id)
{
return "Details() Action Method of HomeController, ID Value = " + id;
}
}
Attribute Routes at Controller Level:
In the ASP.NET Core MVC application, it is also possible to apply the Route() attribute
on the Controller class as well as on individual action methods. If you want to make
the attribute routing less repetitive, then you need to use the route attributes on the
controller level as well as on the individual action methods level.
[Route(“Main")]
public class HomeController : Controller
{

}
REST APIs should use attribute routing to model the app's functionality as a set of
resources where operations are represented by HTTP verbs.
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase

You might also like