Skip to content

Commit 73799df

Browse files
Add referral Id's into hyperlinks
1 parent ebb0847 commit 73799df

File tree

9 files changed

+39
-65
lines changed

9 files changed

+39
-65
lines changed

EssentialCSharp.Web/Areas/Identity/Data/EssentialCSharpWebContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace EssentialCSharp.Web.Data;
66

7-
public class EssentialCSharpWebContext(DbContextOptions<EssentialCSharpWebContext> options) : IdentityDbContext<EssentialCSharpWebUser>(options)
7+
public class EssentialCSharpWebContext(DbContextOptions options) : IdentityDbContext<EssentialCSharpWebUser>(options)
88
{
99
protected override void OnModelCreating(ModelBuilder builder)
1010
{

EssentialCSharp.Web/Areas/Identity/Pages/Account/Login.cshtml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
using System.ComponentModel.DataAnnotations;
22
using EssentialCSharp.Web.Areas.Identity.Data;
3+
using EssentialCSharp.Web.Services.Referrals;
34
using Microsoft.AspNetCore.Authentication;
45
using Microsoft.AspNetCore.Identity;
56
using Microsoft.AspNetCore.Mvc;
67
using Microsoft.AspNetCore.Mvc.RazorPages;
78

89
namespace EssentialCSharp.Web.Areas.Identity.Pages.Account;
910

10-
public class LoginModel(SignInManager<EssentialCSharpWebUser> signInManager, UserManager<EssentialCSharpWebUser> userManager, ILogger<LoginModel> logger) : PageModel
11+
public class LoginModel(SignInManager<EssentialCSharpWebUser> signInManager, UserManager<EssentialCSharpWebUser> userManager, ILogger<LoginModel> logger, IReferralService referralService) : PageModel
1112
{
1213
private InputModel? _Input;
1314
[BindProperty]
@@ -77,6 +78,8 @@ public async Task<IActionResult> OnPostAsync(string? returnUrl = null)
7778
if (foundUser is not null)
7879
{
7980
result = await signInManager.PasswordSignInAsync(foundUser, Input.Password, Input.RememberMe, lockoutOnFailure: true);
81+
// Call the referral service to get the referral ID and set it onto the user claim
82+
_ = await referralService.GetReferralIdAsync(foundUser);
8083
}
8184
else
8285
{

EssentialCSharp.Web/Areas/Identity/Pages/Account/Manage/Index.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ ViewData["ActivePage"] = ManageNavPages.Index;
3232
<input asp-for="Input.PhoneNumber" class="form-control" placeholder="Please enter your phone number." />
3333
<label asp-for="Input.PhoneNumber" class="form-label"></label>
3434
<span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
35-
</div>
35+
</div>
3636
<button id="update-profile-button" type="submit" class="w-100 btn btn-lg btn-primary">Save</button>
3737
</form>
3838
</div>

EssentialCSharp.Web/Controllers/HomeController.cs

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,20 @@
77

88
namespace EssentialCSharp.Web.Controllers;
99

10-
public class HomeController : Controller
10+
public class HomeController(ILogger<HomeController> logger, IWebHostEnvironment hostingEnvironment, ISiteMappingService siteMappingService, IHttpContextAccessor httpContextAccessor) : Controller
1111
{
12-
private readonly IConfiguration _Configuration;
13-
private readonly IWebHostEnvironment _HostingEnvironment;
14-
private readonly ISiteMappingService _SiteMappingService;
15-
private readonly ILogger<HomeController> _Logger;
16-
17-
public HomeController(ILogger<HomeController> logger, IWebHostEnvironment hostingEnvironment, ISiteMappingService siteMappingService, IConfiguration configuration)
18-
{
19-
_Logger = logger;
20-
_HostingEnvironment = hostingEnvironment;
21-
_SiteMappingService = siteMappingService;
22-
_Configuration = configuration;
23-
}
24-
2512
public IActionResult Index(string key)
2613
{
2714
// if no key (default case), then load up home page
28-
SiteMapping? siteMapping = _SiteMappingService.SiteMappings.Find(key);
15+
SiteMapping? siteMapping = siteMappingService.SiteMappings.Find(key);
2916

3017
if (string.IsNullOrEmpty(key))
3118
{
3219
return RedirectToAction(nameof(Home));
3320
}
3421
else if (siteMapping is not null)
3522
{
36-
string filePath = Path.Combine(_HostingEnvironment.ContentRootPath, Path.Combine(siteMapping.PagePath));
23+
string filePath = Path.Combine(hostingEnvironment.ContentRootPath, Path.Combine(siteMapping.PagePath));
3724
HtmlDocument doc = new();
3825
doc.Load(filePath);
3926
string headHtml = doc.DocumentNode.Element("html").Element("head").InnerHtml;
@@ -44,6 +31,8 @@ public IActionResult Index(string key)
4431
ViewBag.PreviousPage = FlipPage(siteMapping.ChapterNumber, siteMapping.PageNumber, false);
4532
ViewBag.HeadContents = headHtml;
4633
ViewBag.Contents = html;
34+
// Set the referral Id for use in the front end if available
35+
ViewBag.ReferralId = httpContextAccessor.HttpContext?.User?.Claims?.FirstOrDefault(f => f.Type == "ReferrerId")?.Value;
4736
return View();
4837
}
4938
else
@@ -84,19 +73,19 @@ public IActionResult Home()
8473
public IActionResult Guidelines()
8574
{
8675
ViewBag.PageTitle = "Coding Guidelines";
87-
FileInfo fileInfo = new(Path.Combine(_HostingEnvironment.ContentRootPath, "Guidelines", "guidelines.json"));
76+
FileInfo fileInfo = new(Path.Combine(hostingEnvironment.ContentRootPath, "Guidelines", "guidelines.json"));
8877
if (!fileInfo.Exists)
8978
{
9079
return RedirectToAction(nameof(Error), new { errorMessage = "Guidelines could not be found", statusCode = 404 });
9180
}
92-
ViewBag.Guidelines = fileInfo.ReadGuidelineJsonFromInputDirectory(_Logger);
81+
ViewBag.Guidelines = fileInfo.ReadGuidelineJsonFromInputDirectory(logger);
9382
ViewBag.GuidelinesUrl = Request.Path.Value;
9483
return View();
9584
}
9685

9786
private string FlipPage(int currentChapter, int currentPage, bool next)
9887
{
99-
if (_SiteMappingService.SiteMappings.Count == 0)
88+
if (siteMappingService.SiteMappings.Count == 0)
10089
{
10190
return "";
10291
}
@@ -107,18 +96,18 @@ private string FlipPage(int currentChapter, int currentPage, bool next)
10796
page = 1;
10897
}
10998

110-
SiteMapping? siteMap = _SiteMappingService.SiteMappings.FirstOrDefault(f => f.ChapterNumber == currentChapter && f.PageNumber == currentPage + page);
99+
SiteMapping? siteMap = siteMappingService.SiteMappings.FirstOrDefault(f => f.ChapterNumber == currentChapter && f.PageNumber == currentPage + page);
111100

112101
if (siteMap is null)
113102
{
114103
if (next)
115104
{
116-
siteMap = _SiteMappingService.SiteMappings.FirstOrDefault(f => f.ChapterNumber == currentChapter + 1 && f.PageNumber == 1);
105+
siteMap = siteMappingService.SiteMappings.FirstOrDefault(f => f.ChapterNumber == currentChapter + 1 && f.PageNumber == 1);
117106
}
118107
else
119108
{
120-
int? previousPage = _SiteMappingService.SiteMappings.LastOrDefault(f => f.ChapterNumber == currentChapter - 1)?.PageNumber;
121-
siteMap = _SiteMappingService.SiteMappings.FirstOrDefault(f => f.ChapterNumber == currentChapter - 1 && f.PageNumber == previousPage);
109+
int? previousPage = siteMappingService.SiteMappings.LastOrDefault(f => f.ChapterNumber == currentChapter - 1)?.PageNumber;
110+
siteMap = siteMappingService.SiteMappings.FirstOrDefault(f => f.ChapterNumber == currentChapter - 1 && f.PageNumber == previousPage);
122111
}
123112
if (siteMap is null)
124113
{

EssentialCSharp.Web/Middleware/ReferralTrackingMiddleware.cs

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Web;
33
using EssentialCSharp.Web.Areas.Identity.Data;
44
using EssentialCSharp.Web.Services.Referrals;
5-
using Microsoft.AspNetCore.Http.Extensions;
65
using Microsoft.AspNetCore.Identity;
76

87
namespace EssentialCSharp.Web.Middleware;
@@ -21,48 +20,13 @@ public async Task InvokeAsync(HttpContext context, IReferralService referralServ
2120
// Retrieve current referral Id for processing
2221
System.Collections.Specialized.NameValueCollection query = HttpUtility.ParseQueryString(context.Request.QueryString.Value!);
2322
string? referralId = query["rid"];
24-
string? userReferralId;
25-
2623
if (context.User is { Identity.IsAuthenticated: true } claimsUser)
2724
{
28-
if (!string.IsNullOrWhiteSpace(referralId))
29-
{
30-
await TrackReferralAsync(referralService, referralId, claimsUser);
31-
}
32-
33-
// Add the referralId to the request context if it exists on a user
34-
EssentialCSharpWebUser? user = await userManager.GetUserAsync(claimsUser);
35-
if (user is not null)
36-
{
37-
userReferralId = await referralService.GetReferralIdAsync(user.Id);
38-
39-
if (!string.IsNullOrWhiteSpace(userReferralId) && (string.IsNullOrWhiteSpace(query["rid"]) || query["rid"] != userReferralId))
40-
{
41-
query.Remove("rid");
42-
query.Add("rid", userReferralId);
43-
var builder = new UriBuilder(context.Request.GetEncodedUrl())
44-
{
45-
Query = query.ToString()
46-
};
47-
context.Response.Redirect(builder.ToString());
48-
return;
49-
}
50-
}
25+
await TrackReferralAsync(referralService, referralId, claimsUser);
5126
}
5227
else
5328
{
54-
55-
if (!string.IsNullOrWhiteSpace(referralId))
56-
{
57-
await TrackReferralAsync(referralService, referralId, null);
58-
query.Remove("rid");
59-
var builder = new UriBuilder(context.Request.GetEncodedUrl())
60-
{
61-
Query = query.ToString()
62-
};
63-
context.Response.Redirect(builder.ToString());
64-
return;
65-
}
29+
await TrackReferralAsync(referralService, referralId, null);
6630
}
6731

6832
await _Next(context);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System.Security.Claims;
2+
using EssentialCSharp.Web.Areas.Identity.Data;
23

34
namespace EssentialCSharp.Web.Services.Referrals;
45

56
public interface IReferralService
67
{
78
Task TrackReferralAsync(string referralId, ClaimsPrincipal? user);
89
Task<string?> GetReferralIdAsync(string userId);
10+
Task<string?> GetReferralIdAsync(EssentialCSharpWebUser? user);
911
}

EssentialCSharp.Web/Services/Referrals/ReferralService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ public class ReferralService(EssentialCSharpWebContext dbContext, SqidsEncoder<i
1212
public async Task<string?> GetReferralIdAsync(string userId)
1313
{
1414
EssentialCSharpWebUser? user = await userManager.FindByIdAsync(userId);
15+
return await GetReferralIdAsync(user);
16+
}
17+
18+
public async Task<string?> GetReferralIdAsync(EssentialCSharpWebUser? user)
19+
{
1520
if (user is null)
1621
{
1722
return null;

EssentialCSharp.Web/Views/Shared/_Layout.cshtml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@
273273
PREVIOUS_PAGE = @Json.Serialize(ViewBag.PreviousPage)
274274
NEXT_PAGE = @Json.Serialize(ViewBag.NextPage)
275275
TOC_DATA = @Json.Serialize(tocData)
276+
REFERRAL_ID = @Json.Serialize(ViewBag.ReferralId)
276277
</script>
277278

278279
@* Recursive vue component template for rendering the table of contents. *@

EssentialCSharp.Web/wwwroot/js/site.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,13 @@ const app = createApp({
125125
const snackbarColor = ref();
126126

127127
function copyToClipboard(copyText) {
128+
let url = window.location.origin + "/" + copyText;
129+
let referralId = REFERRAL_ID;
130+
if (referralId && referralId.trim()) {
131+
url = addQueryParam(url, 'rid', referralId);
132+
}
128133
navigator.clipboard
129-
.writeText(window.location.origin + "/" + copyText)
134+
.writeText(url)
130135
.then(
131136
function () {
132137
/* Success */
@@ -151,6 +156,11 @@ const app = createApp({
151156
);
152157
}
153158

159+
function addQueryParam(url, key, value) {
160+
var separator = url.includes('?') ? '&' : '?';
161+
return url + separator + key + '=' + encodeURIComponent(value);
162+
}
163+
154164
function goToPrevious() {
155165
let previousPage = PREVIOUS_PAGE;
156166
if (previousPage !== null) {

0 commit comments

Comments
 (0)