Skip to content

Commit 5ee5262

Browse files
committed
Merge remote-tracking branch 'origin/staging' into fix/conflicts
* origin/staging: PetSite updates (#350)
2 parents f1d2d81 + 7a6312d commit 5ee5262

File tree

14 files changed

+555
-422
lines changed

14 files changed

+555
-422
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
3+
namespace PetSite.Helpers
4+
{
5+
public static class UrlHelper
6+
{
7+
public static string BuildUrl(string baseUrl, params (string key, string value)[] parameters)
8+
{
9+
if (string.IsNullOrEmpty(baseUrl))
10+
return string.Empty;
11+
12+
var url = baseUrl;
13+
var hasQuery = url.Contains("?");
14+
15+
foreach (var (key, value) in parameters)
16+
{
17+
if (!string.IsNullOrEmpty(value))
18+
{
19+
var separator = hasQuery ? "&" : "?";
20+
url += $"{separator}{key}={Uri.EscapeDataString(value)}";
21+
hasQuery = true;
22+
}
23+
}
24+
25+
return url;
26+
}
27+
}
28+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Microsoft.AspNetCore.Http;
2+
using Microsoft.Extensions.Logging;
3+
using System;
4+
using System.Threading.Tasks;
5+
6+
namespace PetSite.Middleware
7+
{
8+
public class ErrorHandlingMiddleware
9+
{
10+
private readonly RequestDelegate _next;
11+
private readonly ILogger<ErrorHandlingMiddleware> _logger;
12+
13+
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
14+
{
15+
_next = next;
16+
_logger = logger;
17+
}
18+
19+
public async Task InvokeAsync(HttpContext context)
20+
{
21+
try
22+
{
23+
await _next(context);
24+
}
25+
catch (Exception ex)
26+
{
27+
_logger.LogError(ex, "An unhandled exception occurred");
28+
29+
// Preserve userId and exception message
30+
var userId = context.Request.Query["userId"].ToString();
31+
var errorMessage = Uri.EscapeDataString(ex.Message);
32+
33+
var errorPath = $"/Home/Error?message={errorMessage}";
34+
if (!string.IsNullOrEmpty(userId))
35+
{
36+
errorPath += $"&userId={userId}";
37+
}
38+
39+
context.Response.Redirect(errorPath);
40+
}
41+
}
42+
}
43+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
@model ErrorViewModel
2+
@{
3+
ViewData["Title"] = "Error";
4+
}
5+
6+
<section class="pet-hero">
7+
<div class="container">
8+
<img class="pet-hero-title" src="~/images/main_banner_text.png" />
9+
</div>
10+
</section>
11+
12+
<div class="container mt-4">
13+
<div class="alert alert-danger" role="alert">
14+
<h4 class="alert-heading">Oops! Something went wrong</h4>
15+
<hr>
16+
@if (!string.IsNullOrEmpty(ViewBag.ErrorMessage))
17+
{
18+
<p class="mb-0"><strong>Error:</strong> @ViewBag.ErrorMessage</p>
19+
}
20+
else
21+
{
22+
<p class="mb-0">We're sorry, but an unexpected error occurred while processing your request.</p>
23+
}
24+
</div>
25+
26+
<div class="text-center mt-4">
27+
<a asp-controller="Home" asp-action="Index" asp-route-userId="@ViewBag.UserId" class="btn btn-primary btn-lg">
28+
Return to Home
29+
</a>
30+
</div>
31+
</div>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
@using Microsoft.AspNetCore.Http.Features
2+
@using Microsoft.CodeAnalysis.CSharp.Syntax
3+
@model Pet;
4+
5+
<form asp-controller="adoption" asp-action="takemehome" method="post">
6+
<div style="position: relative; display: inline-block;">
7+
<img class="pet-thumbnail" src="@Model.peturl" style="border: 1px solid #000000; border-radius: 23px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);" />
8+
9+
<!-- Pet type and color overlay - top left -->
10+
<span style="position: absolute; top: 8px; left: 8px; background: rgba(0,0,0,0.7); color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px;">@Model.pettype-@Model.petcolor</span>
11+
12+
<!-- Price overlay - bottom right -->
13+
<span style="position: absolute; bottom: 8px; right: 8px; background: rgba(0,0,0,0.7); color: white; padding: 2px 6px; border-radius: 4px; font-weight: bold;font-size: 18px;">$@Model.price</span>
14+
15+
<!-- Cuteness rating overlay - bottom center -->
16+
<div style="position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.7); padding: 2px 6px; border-radius: 4px;">
17+
@for (int i = 0; i < Int32.Parse(Model.cuteness_rate); i++)
18+
{
19+
<span style="color: #ffd700;">★</span>
20+
}
21+
</div>
22+
</div>
23+
24+
@if (Model.availability == "yes")
25+
{
26+
<br/>
27+
<input class="pet-button" type="submit" value="Take me home"/>
28+
}
29+
else
30+
{
31+
<br/>
32+
<br/>
33+
<span style="color: red; font-weight: bold;">Unavailable</span>
34+
}
35+
36+
<input type="hidden" asp-for="@Model.petcolor" name="petcolor" />
37+
<input type="hidden" asp-for="@Model.petid" name="petid" />
38+
<input type="hidden" asp-for="@Model.pettype" name="pettype" />
39+
<input type="hidden" asp-for="@Model.peturl" name="peturl" />
40+
<input type="hidden" asp-for="@Model.price" name="price" />
41+
<input type="hidden" asp-for="@Model.cuteness_rate" name="cuteness_rate" />
42+
<input type="hidden" name="userId" value="@ViewBag.UserId" />
43+
44+
</form>

src/applications/microservices/petsite-net/petsite/Controllers/AdoptionController.cs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,38 +26,38 @@ public AdoptionController(ILogger<AdoptionController> logger, PetSite.Services.I
2626
_petSearchService = petSearchService;
2727
_logger = logger;
2828
}
29-
29+
3030
// GET: Adoption
3131
[HttpGet]
3232
public IActionResult Index([FromQuery] Pet pet)
3333
{
3434
if (EnsureUserId()) return new EmptyResult(); // Redirect happened, stop processing
35-
35+
3636
_logger.LogInformation($"In Index Adoption/Index method with pet: {JsonSerializer.Serialize(pet)}");
37-
37+
3838
return View(pet);
3939
}
40-
40+
4141

4242

4343
[HttpPost]
4444
public async Task<IActionResult> TakeMeHome([FromForm] SearchParams searchParams, string userId)
4545
{
46-
if (string.IsNullOrEmpty(userId)) EnsureUserId();
47-
46+
if(string.IsNullOrEmpty(userId)) EnsureUserId();
47+
4848
// Add custom span attributes using Activity API
4949
var currentActivity = Activity.Current;
5050
if (currentActivity != null)
5151
{
5252
currentActivity.SetTag("pet.id", searchParams.petid);
5353
currentActivity.SetTag("pet.type", searchParams.pettype);
5454
currentActivity.SetTag("pet.color", searchParams.petcolor);
55-
55+
5656
_logger.LogInformation($"Processing adoption request - PetId:{searchParams.petid}, PetType:{searchParams.pettype}, PetColor:{searchParams.petcolor}");
5757
}
58-
58+
5959
List<Pet> pets;
60-
60+
6161
try
6262
{
6363
// Create tracing span for Search API operation
@@ -83,8 +83,7 @@ public async Task<IActionResult> TakeMeHome([FromForm] SearchParams searchParams
8383
var selectedPet = pets.FirstOrDefault();
8484
if (selectedPet != null)
8585
{
86-
return RedirectToAction("Index", new
87-
{
86+
return RedirectToAction("Index", new {
8887
userId = userId,
8988
petid = selectedPet.petid,
9089
pettype = selectedPet.pettype,
@@ -94,9 +93,8 @@ public async Task<IActionResult> TakeMeHome([FromForm] SearchParams searchParams
9493
cuteness_rate = selectedPet.cuteness_rate
9594
});
9695
}
97-
96+
9897
return RedirectToAction("Index", new { userId = userId });
9998
}
10099
}
101100
}
102-

src/applications/microservices/petsite-net/petsite/Controllers/BaseController.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ public class BaseController : Controller
2222
protected bool EnsureUserId()
2323
{
2424
string userId = Request.Query["userId"].ToString();
25-
25+
2626
// Generate userId only on Home/Index if not provided
2727
if (string.IsNullOrEmpty(userId))
2828
{
2929
// Only generate on Home/Index, otherwise require userId
30-
if (ControllerContext.ActionDescriptor.ControllerName == "Home" &&
30+
if (ControllerContext.ActionDescriptor.ControllerName == "Home" &&
3131
ControllerContext.ActionDescriptor.ActionName == "Index")
3232
{
3333
userId = UserIds[Random.Next(UserIds.Count)];
34-
34+
3535
if (Request.Method == "GET")
3636
{
3737
var queryString = Request.QueryString.HasValue ? Request.QueryString.Value + "&userId=" + userId : "?userId=" + userId;
@@ -46,19 +46,18 @@ protected bool EnsureUserId()
4646
return true;
4747
}
4848
}
49-
49+
5050
// Set ViewBag and ViewData for all views
5151
ViewBag.UserId = userId;
5252
ViewData["UserId"] = userId;
53-
53+
5454
var currentActivity = Activity.Current;
5555
if (currentActivity != null && !currentActivity.Tags.Any(tag => tag.Key == "userId"))
5656
{
5757
currentActivity.SetTag("userId", userId);
5858
}
59-
59+
6060
return false;
6161
}
6262
}
63-
}
64-
63+
}

src/applications/microservices/petsite-net/petsite/Controllers/FoodServiceController.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ public async Task<IActionResult> GetFoods()
3838
var url = UrlHelper.BuildUrl(foodApiUrl, ("userId", userId));
3939
var response = await httpClient.GetAsync(url);
4040
response.EnsureSuccessStatusCode();
41-
41+
4242
var jsonContent = await response.Content.ReadAsStringAsync();
4343
var foodResponse = JsonSerializer.Deserialize<FoodResponse>(jsonContent);
44-
44+
4545
return Json(foodResponse?.foods ?? new List<Food>());
4646
}
4747
catch (Exception ex)
@@ -60,11 +60,11 @@ public async Task<IActionResult> BuyFood(string foodId, string userId)
6060
{
6161
using var httpClient = _httpClientFactory.CreateClient();
6262
var purchaseApiUrl = _configuration["FOOD_PURCHASE_API_URL"] ?? "https://api.example.com/purchase";
63-
// var userId = ViewBag.UserId?.ToString();
63+
// var userId = ViewBag.UserId?.ToString();
6464
var url = UrlHelper.BuildUrl(purchaseApiUrl, ("foodId", foodId), ("userId", userId));
6565
var response = await httpClient.PostAsync(url, null);
6666
response.EnsureSuccessStatusCode();
67-
67+
6868
// Food purchase successful - could add ViewData or redirect with status
6969
}
7070
catch (Exception ex)
@@ -76,5 +76,4 @@ public async Task<IActionResult> BuyFood(string foodId, string userId)
7676
return RedirectToAction("Index", "Payment", new { userId = userId });
7777
}
7878
}
79-
}
80-
79+
}

src/applications/microservices/petsite-net/petsite/Controllers/HomeController.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public async Task<IActionResult> HouseKeeping()
7777
_logger.LogInformation("In Housekeeping, trying to reset the app.");
7878

7979
string cleanupadoptionsurl = _configuration["cleanupadoptionsurl"];
80-
80+
8181
using var httpClient = _httpClientFactory.CreateClient();
8282
var userId = ViewBag.UserId?.ToString();
8383
var url = UrlHelper.BuildUrl(cleanupadoptionsurl, ("userId", userId));
@@ -97,10 +97,10 @@ public async Task<IActionResult> Index(string selectedPetType, string selectedPe
9797
currentActivity.SetTag("pet.type", selectedPetType);
9898
currentActivity.SetTag("pet.color", selectedPetColor);
9999
currentActivity.SetTag("pet.id", petid);
100-
100+
101101
_logger.LogInformation($"Search string - PetType:{selectedPetType} PetColor:{selectedPetColor} PetId:{petid}");
102102
}
103-
103+
104104
List<Pet> Pets;
105105

106106
try
@@ -152,7 +152,7 @@ public async Task<IActionResult> Index(string selectedPetType, string selectedPe
152152
SelectedPetType = selectedPetType
153153
}
154154
};
155-
155+
156156
_logger.LogInformation("Search completed with {PetCount} pets found", Pets.Count);
157157

158158
// Sets the metric value to the number of pets available for adoption at the moment
@@ -169,11 +169,10 @@ public IActionResult Error(string userId, string message)
169169
ViewBag.UserId = userId;
170170
ViewData["UserId"] = userId;
171171
}
172-
172+
173173
ViewBag.ErrorMessage = message;
174-
175-
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
174+
175+
return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
176176
}
177177
}
178178
}
179-

src/applications/microservices/petsite-net/petsite/Controllers/PaymentController.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ public PaymentController(ILogger<PaymentController> logger, IConfiguration confi
3838
public ActionResult Index([FromQuery] string userId, string status)
3939
{
4040
if (EnsureUserId()) return new EmptyResult();
41-
41+
4242
// Transfer Session to ViewData for the view
4343
ViewData["txStatus"] = status;
44-
44+
4545
// ViewData["FoodPurchaseStatus"] = HttpContext.Session.GetString("FoodPurchaseStatus");
4646
// ViewData["PurchasedFoodId"] = HttpContext.Session.GetString("PurchasedFoodId");
4747
//
@@ -60,7 +60,7 @@ public async Task<IActionResult> MakePayment(string petId, string pettype, strin
6060
//if (EnsureUserId()) return new EmptyResult();
6161

6262
if (string.IsNullOrEmpty(userId)) EnsureUserId();
63-
63+
6464
// Add custom span attributes using Activity API
6565
var currentActivity = Activity.Current;
6666
if (currentActivity != null)
@@ -86,7 +86,7 @@ public async Task<IActionResult> MakePayment(string petId, string pettype, strin
8686

8787
using var httpClient = _httpClientFactory.CreateClient();
8888

89-
var url = UrlHelper.BuildUrl(_configuration["paymentapiurl"],
89+
var url = UrlHelper.BuildUrl(_configuration["paymentapiurl"],
9090
("petId", petId), ("petType", pettype), ("userId", userId));
9191
await httpClient.PostAsync(url, null);
9292
}
@@ -104,5 +104,4 @@ public async Task<IActionResult> MakePayment(string petId, string pettype, strin
104104
}
105105
}
106106
}
107-
}
108-
107+
}

0 commit comments

Comments
 (0)