Skip to content

Commit b4881c7

Browse files
1208 (#139)
* Before stream * Updated unit test project * Fixed some possible null references * After stream * 1. Placed the "add" button in a column so it has the same padding as the rest of the layout and removed the button button width as it is not required. (#137) 2. Updated "index.chtm"l and "_itemCard.chtml" so that all cards have equal height and the width is automatically calculated (3 column layout). Ref: https://getbootstrap.com/docs/5.2/components/card/#card-groups 3. Updated the "_itemCard.chtml" card footer to use class="float-end" class instead of inline style (float:right). Ref: https://getbootstrap.com/docs/5.2/utilities/float/ 4. Updated the "_itemCard.chtm"l card footer buttons to use role="button" instead of inline style (cursor:pointer). Ref: https://getbootstrap.com/docs/5.2/content/reboot/#pointers-on-buttons 5. Updated the "_itemCard.chtml" card footer so that the text could not be accidentally selected when clicking a button. Ref: https://getbootstrap.com/docs/5.2/utilities/interactions/ * Updated to latest package versions * After stream 2 Co-authored-by: JustCallMeAD <[email protected]>
1 parent 8775fff commit b4881c7

File tree

128 files changed

+91928
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+91928
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30114.105
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyCollectionSite", "src\MyCollectionSite.csproj", "{5E91B40C-D360-44F0-9DAC-397CEFB24D97}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{4E71A210-6F3A-4DA9-B20B-3F3541FF83B6}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(SolutionProperties) = preSolution
16+
HideSolutionNode = FALSE
17+
EndGlobalSection
18+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
19+
{5E91B40C-D360-44F0-9DAC-397CEFB24D97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
20+
{5E91B40C-D360-44F0-9DAC-397CEFB24D97}.Debug|Any CPU.Build.0 = Debug|Any CPU
21+
{5E91B40C-D360-44F0-9DAC-397CEFB24D97}.Release|Any CPU.ActiveCfg = Release|Any CPU
22+
{5E91B40C-D360-44F0-9DAC-397CEFB24D97}.Release|Any CPU.Build.0 = Release|Any CPU
23+
{4E71A210-6F3A-4DA9-B20B-3F3541FF83B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24+
{4E71A210-6F3A-4DA9-B20B-3F3541FF83B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
25+
{4E71A210-6F3A-4DA9-B20B-3F3541FF83B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
26+
{4E71A210-6F3A-4DA9-B20B-3F3541FF83B6}.Release|Any CPU.Build.0 = Release|Any CPU
27+
EndGlobalSection
28+
EndGlobal
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Session 1208: Insert, Update, and Delete
2+
3+
Our collection website has grown and now has some interesting features to allow us to maintain the website, but how do we maintain the data? Let's look at adding, updating, and deleting items in our collection. Once we have these data maintenance features, we can add Security to them next time.
4+
5+
## Agenda
6+
7+
1. Let's introduce an "Add New" button to the home page. This will lead to a page with an empty form to add a new collection item. Let's not wire up the form to anything YET.
8+
1. We'll want to be able to edit items as well, let's add an edit link to the item display. We'll use the Open Iconic pencil icon:
9+
10+
```html
11+
<span class="oi oi-pencil" title="pencil" aria-hidden="true"></span>
12+
```
13+
14+
1. We can also add a delete button using the X icon:
15+
16+
```html
17+
<span class="oi oi-x" title="x" aria-hidden="true"></span>
18+
```
19+
20+
1. Let's see how Visual Studio 2022 provides a scaffolder to generate these actions for us and inspect the code generated.
21+
22+
1. We need some unit tests and we'll want to connect the new Add, Update, and Delete actions to our Repository object instead of directly using the Entity Framework context.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
// Use IntelliSense to find out which attributes exist for C# debugging
6+
// Use hover for the description of the existing attributes
7+
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
8+
"name": ".NET Core Launch (web)",
9+
"type": "coreclr",
10+
"request": "launch",
11+
"preLaunchTask": "build",
12+
// If you have changed target frameworks, make sure to update the program path.
13+
"program": "${workspaceFolder}/bin/Debug/net6.0/MyCollectionSite.dll",
14+
"args": [],
15+
"cwd": "${workspaceFolder}",
16+
"stopAtEntry": false,
17+
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
18+
"serverReadyAction": {
19+
"action": "openExternally",
20+
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
21+
},
22+
"env": {
23+
"ASPNETCORE_ENVIRONMENT": "Development"
24+
},
25+
"sourceFileMap": {
26+
"/Views": "${workspaceFolder}/Views"
27+
}
28+
},
29+
{
30+
"name": ".NET Core Attach",
31+
"type": "coreclr",
32+
"request": "attach"
33+
}
34+
]
35+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"sqltools.connections": [
3+
{
4+
"previewLimit": 50,
5+
"driver": "SQLite",
6+
"name": "collection-db",
7+
"database": "${workspaceFolder:src}/collection.db"
8+
}
9+
]
10+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"label": "build",
6+
"command": "dotnet",
7+
"type": "process",
8+
"args": [
9+
"build",
10+
"${workspaceFolder}/MyCollectionSite.csproj",
11+
"/property:GenerateFullPaths=true",
12+
"/consoleloggerparameters:NoSummary"
13+
],
14+
"problemMatcher": "$msCompile"
15+
},
16+
{
17+
"label": "publish",
18+
"command": "dotnet",
19+
"type": "process",
20+
"args": [
21+
"publish",
22+
"${workspaceFolder}/MyCollectionSite.csproj",
23+
"/property:GenerateFullPaths=true",
24+
"/consoleloggerparameters:NoSummary"
25+
],
26+
"problemMatcher": "$msCompile"
27+
},
28+
{
29+
"label": "watch",
30+
"command": "dotnet",
31+
"type": "process",
32+
"args": [
33+
"watch",
34+
"run",
35+
"--project",
36+
"${workspaceFolder}/MyCollectionSite.csproj"
37+
],
38+
"problemMatcher": "$msCompile"
39+
}
40+
]
41+
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Microsoft.AspNetCore.Http;
6+
using Microsoft.AspNetCore.Mvc;
7+
using Microsoft.AspNetCore.Mvc.Rendering;
8+
using Microsoft.EntityFrameworkCore;
9+
using MyCollectionSite.Models;
10+
11+
namespace MyCollectionSite.Controllers
12+
{
13+
public class CollectionItemsController : Controller
14+
{
15+
private readonly CollectionContext _context;
16+
private readonly IWebHostEnvironment Environment;
17+
18+
public CollectionItemsController(CollectionContext context
19+
, IWebHostEnvironment environment)
20+
{
21+
_context = context;
22+
this.Environment = environment;
23+
}
24+
25+
// GET: CollectionItems
26+
public async Task<IActionResult> Index()
27+
{
28+
return Redirect("/");
29+
}
30+
31+
// GET: CollectionItems/Details/5
32+
public async Task<IActionResult> Details(int? id)
33+
{
34+
if (id == null || _context.CollectionItems == null)
35+
{
36+
return NotFound();
37+
}
38+
39+
var collectionItem = await _context.CollectionItems
40+
.FirstOrDefaultAsync(m => m.Id == id);
41+
if (collectionItem == null)
42+
{
43+
return NotFound();
44+
}
45+
46+
return View(collectionItem);
47+
}
48+
49+
// GET: CollectionItems/Create
50+
public IActionResult Create()
51+
{
52+
return View();
53+
}
54+
55+
// POST: CollectionItems/Create
56+
// To protect from overposting attacks, enable the specific properties you want to bind to.
57+
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
58+
[HttpPost]
59+
[ValidateAntiForgeryToken]
60+
public async Task<IActionResult> Create(
61+
[Bind("Name,Description,Acquired")]
62+
CollectionItem collectionItem,
63+
List<IFormFile> files)
64+
{
65+
if (ModelState.IsValid)
66+
{
67+
68+
if ((files.FirstOrDefault()?.Length ?? 0) > 0)
69+
{
70+
var filePath = Path.Combine(this.Environment.WebRootPath,
71+
"collectionImages",
72+
collectionItem.Name + ".jpg");
73+
74+
using (var stream = System.IO.File.Create(filePath))
75+
{
76+
await files.First().CopyToAsync(stream);
77+
}
78+
79+
collectionItem.ImageURL = $"/collectionImages/{collectionItem.Name}.jpg";
80+
81+
}
82+
83+
_context.Add(collectionItem);
84+
await _context.SaveChangesAsync();
85+
return RedirectToAction(nameof(Index));
86+
}
87+
return View(collectionItem);
88+
}
89+
90+
// GET: CollectionItems/Edit/5
91+
public async Task<IActionResult> Edit(int? id)
92+
{
93+
if (id == null || _context.CollectionItems == null)
94+
{
95+
return NotFound();
96+
}
97+
98+
var collectionItem = await _context.CollectionItems.FindAsync(id);
99+
if (collectionItem == null)
100+
{
101+
return NotFound();
102+
}
103+
return View(collectionItem);
104+
}
105+
106+
// POST: CollectionItems/Edit/5
107+
// To protect from overposting attacks, enable the specific properties you want to bind to.
108+
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
109+
[HttpPost]
110+
[ValidateAntiForgeryToken]
111+
public async Task<IActionResult> Edit(int id, [Bind("Id,Name,Description,ImageURL,Acquired,Votes")] CollectionItem collectionItem)
112+
{
113+
if (id != collectionItem.Id)
114+
{
115+
return NotFound();
116+
}
117+
118+
if (ModelState.IsValid)
119+
{
120+
try
121+
{
122+
_context.Update(collectionItem);
123+
await _context.SaveChangesAsync();
124+
}
125+
catch (DbUpdateConcurrencyException)
126+
{
127+
if (!CollectionItemExists(collectionItem.Id))
128+
{
129+
return NotFound();
130+
}
131+
else
132+
{
133+
throw;
134+
}
135+
}
136+
return RedirectToAction(nameof(Index));
137+
}
138+
return View(collectionItem);
139+
}
140+
141+
// GET: CollectionItems/Delete/5
142+
public async Task<IActionResult> Delete(int? id)
143+
{
144+
if (id == null || _context.CollectionItems == null)
145+
{
146+
return NotFound();
147+
}
148+
149+
var collectionItem = await _context.CollectionItems
150+
.FirstOrDefaultAsync(m => m.Id == id);
151+
if (collectionItem == null)
152+
{
153+
return NotFound();
154+
}
155+
156+
return View(collectionItem);
157+
}
158+
159+
// POST: CollectionItems/Delete/5
160+
[HttpPost, ActionName("Delete")]
161+
[ValidateAntiForgeryToken]
162+
public async Task<IActionResult> DeleteConfirmed(int id)
163+
{
164+
if (_context.CollectionItems == null)
165+
{
166+
return Problem("Entity set 'CollectionContext.CollectionItems' is null.");
167+
}
168+
var collectionItem = await _context.CollectionItems.FindAsync(id);
169+
if (collectionItem != null)
170+
{
171+
_context.CollectionItems.Remove(collectionItem);
172+
}
173+
174+
await _context.SaveChangesAsync();
175+
return RedirectToAction(nameof(Index));
176+
}
177+
178+
private bool CollectionItemExists(int id)
179+
{
180+
return (_context.CollectionItems?.Any(e => e.Id == id)).GetValueOrDefault();
181+
}
182+
}
183+
}

0 commit comments

Comments
 (0)