mirror of
https://github.com/markjprice/cs11dotnet7.git
synced 2025-12-06 05:32:03 +01:00
Add solution code for Exercise 15.2
This commit is contained in:
parent
69ad593b07
commit
f68d88588e
|
|
@ -135,7 +135,7 @@ namespace Northwind.Mvc.Controllers
|
|||
return View(model); // pass model to view
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Customers(string country)
|
||||
public async Task<IActionResult> Customers(string? country = null)
|
||||
{
|
||||
string uri;
|
||||
|
||||
|
|
@ -161,12 +161,92 @@ namespace Northwind.Mvc.Controllers
|
|||
IEnumerable<Customer>? model = await response.Content
|
||||
.ReadFromJsonAsync<IEnumerable<Customer>>();
|
||||
|
||||
if (model is not null)
|
||||
{
|
||||
model = model.OrderBy(c => c.CustomerId);
|
||||
}
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// Matches /home/categorydetail/{id} by default so to
|
||||
// match /category/{id}, decorate with the following:
|
||||
// [Route("category/{id}")]
|
||||
// GET /Home/AddCustomer
|
||||
public IActionResult AddCustomer()
|
||||
{
|
||||
ViewData["Title"] = "Add Customer";
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST /Home/AddCustomer
|
||||
// A Customer object in the request body.
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddCustomer(Customer customer)
|
||||
{
|
||||
HttpClient client = clientFactory.CreateClient(
|
||||
name: "Northwind.WebApi");
|
||||
|
||||
HttpResponseMessage response = await client.PostAsJsonAsync(
|
||||
requestUri: "api/customers", value: customer);
|
||||
|
||||
// Optionally, get the created customer back as JSON
|
||||
// so the user can see the assigned ID, for example.
|
||||
Customer? model = await response.Content
|
||||
.ReadFromJsonAsync<Customer>();
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
TempData["success-message"] = "Customer successfully added.";
|
||||
}
|
||||
else
|
||||
{
|
||||
TempData["error-message"] = "Customer was NOT added.";
|
||||
}
|
||||
|
||||
// Show the full customers list to see if it was added.
|
||||
return RedirectToAction("Customers");
|
||||
}
|
||||
|
||||
// GET /Home/DeleteCustomer
|
||||
public async Task<IActionResult> DeleteCustomer(string customerId)
|
||||
{
|
||||
HttpClient client = clientFactory.CreateClient(
|
||||
name: "Northwind.WebApi");
|
||||
|
||||
Customer? customer = await client.GetFromJsonAsync<Customer>(
|
||||
requestUri: $"api/customers/{customerId}");
|
||||
|
||||
ViewData["Title"] = "Delete Customer";
|
||||
|
||||
return View(customer);
|
||||
}
|
||||
|
||||
// POST /Home/DeleteCustomer
|
||||
// A CustomerId in the request body e.g. ALFKI.
|
||||
[HttpPost]
|
||||
[Route("home/deletecustomer")]
|
||||
// Action method name must have a different name from the GET method
|
||||
// due to C# not allowing duplicate method signatures.
|
||||
public async Task<IActionResult> DeleteCustomerPost(string customerId)
|
||||
{
|
||||
HttpClient client = clientFactory.CreateClient(
|
||||
name: "Northwind.WebApi");
|
||||
|
||||
HttpResponseMessage response = await client.DeleteAsync(
|
||||
requestUri: $"api/customers/{customerId}");
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
TempData["success-message"] = "Customer successfully deleted.";
|
||||
}
|
||||
else
|
||||
{
|
||||
TempData["error-message"] = $"Customer {customerId} was NOT deleted.";
|
||||
}
|
||||
|
||||
// Show the full customers list to see if it was deleted.
|
||||
return RedirectToAction("Customers");
|
||||
}
|
||||
|
||||
[Route("category/{id}")]
|
||||
public async Task<IActionResult> CategoryDetail(int? id)
|
||||
{
|
||||
if (!id.HasValue)
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ app.UseOutputCache();
|
|||
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}")
|
||||
.CacheOutput("views");
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
// .CacheOutput("views");
|
||||
|
||||
app.MapRazorPages();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
@using Packt.Shared
|
||||
@model Customer
|
||||
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
|
||||
<!--
|
||||
Show an editable form with a blank customer. Postback to the action
|
||||
method AddCustomer to perform the actual insert.
|
||||
-->
|
||||
<form asp-action="AddCustomer" method="post">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="customerId">Customer ID</label>
|
||||
@Html.EditorFor(model => model.CustomerId,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
<div class="form-text">
|
||||
Customer ID must be five (5) upper case characters.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="companyName">Company Name</label>
|
||||
@Html.EditorFor(model => model.CompanyName,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="contactName">Contact Name</label>
|
||||
@Html.EditorFor(model => model.ContactName,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="address">Address</label>
|
||||
@Html.EditorFor(model => model.Address,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="city">City</label>
|
||||
@Html.EditorFor(model => model.City,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="region">Region</label>
|
||||
@Html.EditorFor(model => model.Region,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="country">Country</label>
|
||||
@Html.EditorFor(model => model.Country,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="postalCode">Postal Code</label>
|
||||
@Html.EditorFor(model => model.PostalCode,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="phone">Phone</label>
|
||||
@Html.EditorFor(model => model.Phone,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="submit" value="Add Customer"
|
||||
class="btn btn-outline-primary" />
|
||||
<a asp-controller="Home" asp-action="Customers"
|
||||
class="btn btn-outline-secondary">
|
||||
Cancel and return to Customers
|
||||
</a>
|
||||
@Html.ValidationSummary()
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -2,6 +2,19 @@
|
|||
@model IEnumerable<Customer>
|
||||
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
|
||||
@if (TempData["error-message"] is not null)
|
||||
{
|
||||
<p class="alert alert-danger">Error! @TempData["error-message"]</p>
|
||||
}
|
||||
@if (TempData["success-message"] is not null)
|
||||
{
|
||||
<p class="alert alert-success">Congratulations! @TempData["success-message"]</p>
|
||||
}
|
||||
|
||||
<a asp-controller="Home" asp-action="AddCustomer"
|
||||
class="btn btn-outline-primary">Add Customer</a>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -9,6 +22,7 @@
|
|||
<th>Contact Name</th>
|
||||
<th>Address</th>
|
||||
<th>Phone</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -33,6 +47,12 @@
|
|||
<td>
|
||||
@Html.DisplayFor(modelItem => c.Phone)
|
||||
</td>
|
||||
<td>
|
||||
<a asp-controller="Home"
|
||||
asp-action="DeleteCustomer"
|
||||
asp-route-customerid="@c.CustomerId"
|
||||
class="btn btn-outline-danger">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
@using Packt.Shared
|
||||
@model Customer
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
|
||||
<!--
|
||||
Show a readonly form of an existing customer. Postback to the action
|
||||
method DeleteCustomer to perform the actual delete.
|
||||
-->
|
||||
<form asp-action="DeleteCustomer" method="post">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="customerId">Customer ID</label>
|
||||
<input class="form-control" id="customerId" value="@Model.CustomerId" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="companyName">Company Name</label>
|
||||
<input class="form-control" id="companyName" value="@Model.CompanyName" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="contactName">Contact Name</label>
|
||||
<input class="form-control" id="contactName" value="@Model.ContactName" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="address">Address</label>
|
||||
<input class="form-control" id="address" value="@Model.Address" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="city">City</label>
|
||||
<input class="form-control" id="city" value="@Model.City" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="region">Region</label>
|
||||
<input class="form-control" id="region" value="@Model.Region" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="country">Country</label>
|
||||
<input class="form-control" id="country" value="@Model.Country" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="postalCode">Postal Code</label>
|
||||
<input class="form-control" id="postalCode" value="@Model.PostalCode" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="phone">Phone</label>
|
||||
<input class="form-control" id="phone" value="@Model.Phone" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
@Html.HiddenFor(c => c.CustomerId)
|
||||
<input type="submit" value="Delete Customer"
|
||||
class="btn btn-outline-danger" />
|
||||
<a href="customers" class="btn btn-outline-secondary">
|
||||
Cancel and return to Customers
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
<h3>@Model.Categories[c].Description</h3>
|
||||
<p>
|
||||
<a class="btn btn-primary"
|
||||
href="/home/categorydetail/@Model.Categories[c].CategoryId">View</a>
|
||||
href="/category/@Model.Categories[c].CategoryId">View</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ namespace Northwind.Mvc.Controllers
|
|||
return View(model); // pass model to view
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Customers(string country)
|
||||
public async Task<IActionResult> Customers(string? country = null)
|
||||
{
|
||||
string uri;
|
||||
|
||||
|
|
@ -161,12 +161,92 @@ namespace Northwind.Mvc.Controllers
|
|||
IEnumerable<Customer>? model = await response.Content
|
||||
.ReadFromJsonAsync<IEnumerable<Customer>>();
|
||||
|
||||
if (model is not null)
|
||||
{
|
||||
model = model.OrderBy(c => c.CustomerId);
|
||||
}
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// Matches /home/categorydetail/{id} by default so to
|
||||
// match /category/{id}, decorate with the following:
|
||||
// [Route("category/{id}")]
|
||||
// GET /Home/AddCustomer
|
||||
public IActionResult AddCustomer()
|
||||
{
|
||||
ViewData["Title"] = "Add Customer";
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST /Home/AddCustomer
|
||||
// A Customer object in the request body.
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddCustomer(Customer customer)
|
||||
{
|
||||
HttpClient client = clientFactory.CreateClient(
|
||||
name: "Northwind.WebApi");
|
||||
|
||||
HttpResponseMessage response = await client.PostAsJsonAsync(
|
||||
requestUri: "api/customers", value: customer);
|
||||
|
||||
// Optionally, get the created customer back as JSON
|
||||
// so the user can see the assigned ID, for example.
|
||||
Customer? model = await response.Content
|
||||
.ReadFromJsonAsync<Customer>();
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
TempData["success-message"] = "Customer successfully added.";
|
||||
}
|
||||
else
|
||||
{
|
||||
TempData["error-message"] = "Customer was NOT added.";
|
||||
}
|
||||
|
||||
// Show the full customers list to see if it was added.
|
||||
return RedirectToAction("Customers");
|
||||
}
|
||||
|
||||
// GET /Home/DeleteCustomer
|
||||
public async Task<IActionResult> DeleteCustomer(string customerId)
|
||||
{
|
||||
HttpClient client = clientFactory.CreateClient(
|
||||
name: "Northwind.WebApi");
|
||||
|
||||
Customer? customer = await client.GetFromJsonAsync<Customer>(
|
||||
requestUri: $"api/customers/{customerId}");
|
||||
|
||||
ViewData["Title"] = "Delete Customer";
|
||||
|
||||
return View(customer);
|
||||
}
|
||||
|
||||
// POST /Home/DeleteCustomer
|
||||
// A CustomerId in the request body e.g. ALFKI.
|
||||
[HttpPost]
|
||||
[Route("home/deletecustomer")]
|
||||
// Action method name must have a different name from the GET method
|
||||
// due to C# not allowing duplicate method signatures.
|
||||
public async Task<IActionResult> DeleteCustomerPost(string customerId)
|
||||
{
|
||||
HttpClient client = clientFactory.CreateClient(
|
||||
name: "Northwind.WebApi");
|
||||
|
||||
HttpResponseMessage response = await client.DeleteAsync(
|
||||
requestUri: $"api/customers/{customerId}");
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
TempData["success-message"] = "Customer successfully deleted.";
|
||||
}
|
||||
else
|
||||
{
|
||||
TempData["error-message"] = $"Customer {customerId} was NOT deleted.";
|
||||
}
|
||||
|
||||
// Show the full customers list to see if it was deleted.
|
||||
return RedirectToAction("Customers");
|
||||
}
|
||||
|
||||
[Route("category/{id}")]
|
||||
public async Task<IActionResult> CategoryDetail(int? id)
|
||||
{
|
||||
if (!id.HasValue)
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ app.UseOutputCache();
|
|||
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}")
|
||||
.CacheOutput("views");
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
// .CacheOutput("views");
|
||||
|
||||
app.MapRazorPages();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
@using Packt.Shared
|
||||
@model Customer
|
||||
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
|
||||
<!--
|
||||
Show an editable form with a blank customer. Postback to the action
|
||||
method AddCustomer to perform the actual insert.
|
||||
-->
|
||||
<form asp-action="AddCustomer" method="post">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="customerId">Customer ID</label>
|
||||
@Html.EditorFor(model => model.CustomerId,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
<div class="form-text">
|
||||
Customer ID must be five (5) upper case characters.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="companyName">Company Name</label>
|
||||
@Html.EditorFor(model => model.CompanyName,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="contactName">Contact Name</label>
|
||||
@Html.EditorFor(model => model.ContactName,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="address">Address</label>
|
||||
@Html.EditorFor(model => model.Address,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="city">City</label>
|
||||
@Html.EditorFor(model => model.City,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="region">Region</label>
|
||||
@Html.EditorFor(model => model.Region,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="country">Country</label>
|
||||
@Html.EditorFor(model => model.Country,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="postalCode">Postal Code</label>
|
||||
@Html.EditorFor(model => model.PostalCode,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="phone">Phone</label>
|
||||
@Html.EditorFor(model => model.Phone,
|
||||
new { htmlAttributes = new { @class = "form-control" } })
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="submit" value="Add Customer"
|
||||
class="btn btn-outline-primary" />
|
||||
<a asp-controller="Home" asp-action="Customers"
|
||||
class="btn btn-outline-secondary">
|
||||
Cancel and return to Customers
|
||||
</a>
|
||||
@Html.ValidationSummary()
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -2,6 +2,19 @@
|
|||
@model IEnumerable<Customer>
|
||||
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
|
||||
@if (TempData["error-message"] is not null)
|
||||
{
|
||||
<p class="alert alert-danger">Error! @TempData["error-message"]</p>
|
||||
}
|
||||
@if (TempData["success-message"] is not null)
|
||||
{
|
||||
<p class="alert alert-success">Congratulations! @TempData["success-message"]</p>
|
||||
}
|
||||
|
||||
<a asp-controller="Home" asp-action="AddCustomer"
|
||||
class="btn btn-outline-primary">Add Customer</a>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -9,6 +22,7 @@
|
|||
<th>Contact Name</th>
|
||||
<th>Address</th>
|
||||
<th>Phone</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -33,6 +47,12 @@
|
|||
<td>
|
||||
@Html.DisplayFor(modelItem => c.Phone)
|
||||
</td>
|
||||
<td>
|
||||
<a asp-controller="Home"
|
||||
asp-action="DeleteCustomer"
|
||||
asp-route-customerid="@c.CustomerId"
|
||||
class="btn btn-outline-danger">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
@using Packt.Shared
|
||||
@model Customer
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
|
||||
<!--
|
||||
Show a readonly form of an existing customer. Postback to the action
|
||||
method DeleteCustomer to perform the actual delete.
|
||||
-->
|
||||
<form asp-action="DeleteCustomer" method="post">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="customerId">Customer ID</label>
|
||||
<input class="form-control" id="customerId" value="@Model.CustomerId" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="companyName">Company Name</label>
|
||||
<input class="form-control" id="companyName" value="@Model.CompanyName" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="contactName">Contact Name</label>
|
||||
<input class="form-control" id="contactName" value="@Model.ContactName" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="address">Address</label>
|
||||
<input class="form-control" id="address" value="@Model.Address" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="city">City</label>
|
||||
<input class="form-control" id="city" value="@Model.City" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="region">Region</label>
|
||||
<input class="form-control" id="region" value="@Model.Region" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="country">Country</label>
|
||||
<input class="form-control" id="country" value="@Model.Country" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="postalCode">Postal Code</label>
|
||||
<input class="form-control" id="postalCode" value="@Model.PostalCode" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="phone">Phone</label>
|
||||
<input class="form-control" id="phone" value="@Model.Phone" readonly />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
@Html.HiddenFor(c => c.CustomerId)
|
||||
<input type="submit" value="Delete Customer"
|
||||
class="btn btn-outline-danger" />
|
||||
<a href="customers" class="btn btn-outline-secondary">
|
||||
Cancel and return to Customers
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
<h3>@Model.Categories[c].Description</h3>
|
||||
<p>
|
||||
<a class="btn btn-primary"
|
||||
href="/home/categorydetail/@Model.Categories[c].CategoryId">View</a>
|
||||
href="/category/@Model.Categories[c].CategoryId">View</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue