Opgave: Create new Items


Dette er den anden opgave i opgave-serien ItemRazor.
I denne opgave skal vi oprette Mock-data, en Service klasse med interface samt en ny Razor Page til at kunne oprette nye Item objekter.
Udgangspunktet er løsningen fra opgave 1:





Step 1 (MockData -MockItems)
Mock data er data beregnet til test. Testdata i opgave 1 blev oprettet direkte i pagen GetAllItems og er bestemt ikke en "pæn" løsning.
Testdata skal vi have flyttet ud i en separat Mappe hvor alle testdata kan samles.

Opret en ny mappe MockData og add en ny klasse MockItems til mappen.

Klassen MockItem skal indeholde et static classfield items der referere til en liste af Item objekter ala.:

private static List<Item> items = new List<Item>() {
new Item(1, "PC", 5999),
new Item(2, "Skærm", 1999),
new Item(3, "Tastatur", 999)
};

Klassen MockItem skal desuden have en statisk metode GetMockItems( ) der returnere listen items


Step 2 (GetAllItems.cshtml.cs)
Vi skal nu have klassen GetAllItemsModel refaktoreret (opdateret/omstruktureret).
Først fjernes initialiseringen af property Items og så skal vi have onGet() til at assigne Items til vores Mock-data (Items skal "pege på/referere til" den statiske liste i MockItems)

Hint:
benyt MockItems.GetMockItems( )



Step 3 (Afprøv)
Afprøv at siden stadigt viser tabellen med vores testdata.


Vi er nu klar til endnu en refaktorering, hvor vi introducere begrebet Service (via mappe, interface og klasse). En Service (funktionalitet) kan være en samling metoder der kan udføre forskellige ting ala. beregninger, filtrering af data, sortering af data, søgning i data, hent og gem af data mm

 

Step 4 (Services, IItemService og ItemService)
Vi skal nu implementere en Service der skal kunne tilbyde funktionaliteten: "at hente Items objekter fra Mock-data".

Hint:
Klassen ItemService skal have et instancefield _items eller en property Items der kan referere til listen med Item objekter.
ItemService skal også have en constructor der kan initialisere _items eller Items med Mock-data (Hint: benyt MockItems.GetMockItems( ) )
GetItems( ) skal returnere listen med Items (_items eller Items)

 

Step 5 (Program.cs)
Vores nye service: ItemService skal registreres før den kan anvendes af vores razor pages, det sker i Program.cs.

Åben Program.cs og tilføj linien:

builder.Services.AddSingleton<ItemService, ItemService>();

lige under linien:

builder.Services.AddRazorPages();


Bemærk: AddSingleton betyder at der kun skabes en instans af klassen ItemService (der kan deles af alle de pages hvor servicen injiceres)

 


Step 6 (GetAllItems.cshtml.cs)

Vi skal nu bringe vores nye Service i anvendelse, derfor skal der i klassen GetAllItemsModel tilføjes et nyt instancefield: _itemService, der kan referere til vores nye service: ItemService. _itemService skal initialiseres i konstruktøren, hvor ItemService injiceres vhj dependency injection (servicen er argument til konstruktøren):

public GetAllItemsModel(ItemService itemService) //Dependency Injection
{
this._itemService=itemService;
}

Refaktorer onGet() metoden så den henter Mock-data via servicen istedet for direkte via GetAllItems() fra MockItems:

public void OnGet()
{
Items = _itemService.GetItems(); ;
}

 

Step 7 (Afprøv)
Afprøv at siden stadigt virker efter at vi har refaktoreret koden og introduceret services.

 

Vi har nu refaktoreret vores projekt så det benytter Service og er nu klar til at udvide programmet så vi også kan oprette nye Computer Items.

 

Step 8 (CreateItem)
Først skal der oprettes en ny Razer Page: CreateItem i mappen Pages/Item.

 

Step 9 (CreateItem.cshtml.cs)
a) Tilføj følgende instancefield til klassen CreateItemModel:

private ItemService _itemService;

Så klassen kan benytte vores service og kan anvende listen af Item objekter.


b) Tilføj en property Item til klassen.

[BindProperty]
public Models.Item Item { get; set; }

Det er denne property der skal bindes til fra UI'en (html-siden) (så data kan overføres fra inputfields i UI'en til Item-properties i CreateItemModel).
Bemærk: propertyen er annoteret med: [BindProperty] - der angiver at der kan bindes til denne property fra html-siden

c) Tilføj en constructor: CreateItemModel(ItemService itemService) der injicere ItemService og initialisere _itemService:

public CreateItemModel(ItemService itemService)
{
_itemService = itemService;
}

d) Tilføj metoden OnPost( ). Metoden skal returnere siden selv (CreateItem) hvis ModelState ikke er valid ellers kaldes metoden AddItem(Item) (implementeres senere) på ItemService. Efter Item er added til listen, omdirigeres til siden GetAllItems:

public IActionResult OnGet()
{
return Page();
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return Page();
}
_itemService.AddItem(Item);
return RedirectToPage("GetAllItems");
}

 

Step 10 (CreateItem.cshtml)
Der skal tilføjes et <form> -tag med inputfields så der kan indlæses data til et nyt Item ala:






 


Bemærk:
Når der klikkes på et input feldt af typen submit (vist i browseren som en button med teksten: Create) sendes der et http-request til serveren med metoden "post". Det betyder at metoden OnPost( ) automatisk bliver kaldt på CreateItemModel objektet.

 

Step 11 (IItemService og ItemService)
Nu mangler vi blot at erklærer metoden AddItem(Item item) i interface IItemService og implementere metoden i ItemService:

public void AddItem(Item item)
{
_items.Add(item);
}

 

Step 12 (GetAllItems.cshtml)
For at kunne navigere til vores nye CreateItem side indsættes en button, med et "Anchor tag helper" direktiv: asp-page til vores CreateItem side, under tabellen:

<p>
<a class="btn btn-primary" asp-page="CreateItem"> Create a new Item </a>
</p>


 

Step 13 (Afprøv)
Afprøv at programmet virker og at der kan tilføjes nye Items objekter via CreateItem siden.

 





God fornøjelse!
Henrik Høltzer