The following demo will create an ASP.
NET MVC Core app to
display a list of products in a view and enable users to search
products by name. it will involve creating models, controllers, and
views. It will also illustrate dependency injection of the services
used by controllers.
Demo 3: Creating models and displaying model data in views
1. In visual studio 2022, open the FirstCoreMVCApp solution
created for exercise 2.
2. this exercise will involve the following scenario:
a. creating a model class
b. creating a service class to return model data. The service
class will return a list of model objects instead of connecting
to a database.
c. invoking the service class methods in the page model to
display the data in the view.
3.
3.1 :In the Solution Explorer, right click on the Models folder -
> Add-> Class
Name the class as Product.cs. Add properties to the Product
class so that the class looks as shown below:
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public int Price { get; set; }
}
3.2: Right click on the Models folder in Solution Explorer ->
Add-> New Item -> Interface. Name the interface as
IProductDataService.cs. The interface code must look as shown
below:
public interface IProductDataService
{
IEnumerable<Product> GetProducts();
}
3.3: Add one more class to the Models folder and name it as
ProductDataService.cs. The code for this class should look as
shown below:
public class ProductDataService: IProductDataService
{
static List<Product> products;
static ProductDataService()
{
products = new List<Product>
{
new Product{ProductId=101,ProductName="apple iPhone 13",
Price=50000},
new Product{ProductId=102,ProductName="oppo plus",
Price=30000},
new Product{ProductId=103,ProductName="Samsung ultra",
Price=20000},
new Product{ProductId=104,ProductName="moto e", Price=10000}
};
}
public IEnumerable<Product> GetProducts()
{
return products;
}
Observe the above code and answer the following questions:
a. Why is a static constructor used in the service class?
b. Why is the instance variable static?
Build the application.
4. The service class method must be invoked from the ASP.NET
app and the list of products must be displayed in a view. We
can modify the actions in the home controller to do this or add
a new controller. This exercise will focus on adding a new
controller.
5. Right click on the Controllers folder in Solution Explorer, Add->
Controller. Select the MVC Controller – Empty option and name
the controller as ProductController.cs
6. The service dependency will be registered in the following
steps:
a. Open the Startup.cs file and add the following code to the
ConfigureServices method as shown below:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IProductDataService,
ProductDataService>();
b. From the Solution Explorer, open the ProductController file.
The controller class will be injected with the service reference
using constructor injection. Once this is done, the service
reference will be used to invoke the GetProducts method and
return the product list to the view. This property will be bound
with the view.
Modify the controller file as shown below:
public class ProductController: Controller
{
private readonly IProductDataService service;
public IEnumerable<Product> Products { get; set; }
public ProductController(IProductDataService service)
{
this.service = service;
}
public IActionResult Index()
{
Products=service.GetProducts();
return View(Products);
}
}
Observe the above code and think of the answers to the
following questions:
a. What is the need for the instance variable?
b. What is happening in the constructor?
c. Why is the Products property passed as a parameter to the
view ?
7. To display the list of products returned by the service, a view is
required for the Index action. To create a view, right click on
the Index action method in the controller, select Add View. The
following dialog box opens:
Select Razor View option and click on the Add button. The
following dialog box opens:
Retain the view name as Index. Select the template as List. This
is because the requirement is to display all the products. The
List template will generate a table of model instances. Choose
the model class as Product. Ensure that the Reference script
libraries and Use a layout page checkboxes are selected. Click
on the Add button.
8. The view is now generated in the Views folder under the
Product sub folder:
9. Open the Index.cshtml file under the Product folder and
understand the markup and code generated in the same.
This code /markup is auto generated by VS according to the
template chosen while creating the view. Developers will
retain parts of it and modify parts of it to meet app
requirements.
The models, view and controller are now complete. We need
to provide a link in the UI to access the views. A link is to be
provided in the Layout page to access the same, as shown
below:
10. Add a link to the Layout page. The link text must be
‘Products’, and the Index action of the Product controller must
be invoked when the link is clicked.
To do this, open the _Layout.cshtml and add the following
markup after the list item for the Privacy link:
<a class="nav-link text-dark" asp-area=""
asp-controller="Product" asp-action="Index">Products</a>
11. Run the app, navigate to the Products link, and observe
the output:
12. This view shows the details of all products. The app will
now be modified to allow users to search for products by
product name. The Index view will include a form with input
elements for searching. Add a form element to the
Index.cshtml view [before the table tag is created] as shown
below:
<form method="post">
<div class="form-group">
<input type="search" value="" name="productName"/>
<input type="submit" value="search" />
</div>
</form>
<table class="table">
13. When a “GET” request is made to the page, the Index
method of the controller class is executed as the default
request type is GET, and the service is invoked to fetch the
details of all the products. With the search form added, when
the search button is clicked, a “POST” request is made to the
server. The following additions must be made to the code now:
a. Modify the interface in the data service to declare a search
method:
IEnumerable<Product> GetProductsByName(string name);
b. Implement the search method in the data service class
public IEnumerable<Product> GetProductsByName(string name)
{
return products.Where(p => p.ProductName.Contains(name));
}
The Where method will require the System.Linq namespace
to be imported.
c. Invoke the search method from the POST implementation of
the Index action of the controller class. Add the post
implementation of the Index action method to the controller
as shown below:
[HttpPost]
public IActionResult Index(string productName)
{
Products = service.GetProductsByName(productName);
return View(Products);
}
Note that the parameter has the same name as the HTML
search element. Why is this so? What will happen if the names are
different?
14. Run the application, enter “apple” in the search box and
observe the output
15. The next requirement will be to display the details of
individual products. Each row in the products display view will
have a link. On clicking the link, the product id of the product in
the current row will be used to fetch and display the details of
the product in a new view. The following figures show the
desired output:
What will be the changes which will need to be made?
Think over the same. Which files need to be modified and
which files need to be created?
16. Perform the following steps for the modifications:
a. Add the following method declaration to the
IProductDataService interface:
Product GetProductById(int id)
b. Implement the method in the ProductDataService class to
return a product based on the product Id.
public Product GetProductById(int id)
{
return products.Where(p=>p.ProductId==id).FirstOrDefault();
}
c. The Index.html view has already auto generated 3 links for
every row in the table. We will modify the second link now
(with text Details):
Replace the markup
@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })
With
@Html.ActionLink("View Details", "Details", new { id=item.ProductId })
What is the use of Html.ActionLink ?
What are the 3 parameters of the ActionLink method?
d. Add an action to ProductController. The action must be as
shown below:
public IActionResult Details(int id)
{
Product product = service.GetProductById(id);
return View(product);
}
17. Right click on the Details method, select Add View option,
and choose Razor View. Choose the template as Details and the
model class as Product as shown below:
18. The view is now created under the Views/Product folder.
Understand the markup generated in the file.
19. Run the app. Click on the View Details link for any row
and observe the output.