@@ -140,133 +140,132 @@ In this section we'll add features that track attendees who have registered on t
140
140
[DataType (DataType .EmailAddress )]
141
141
public override string EmailAddress { get => base .EmailAddress ; set => base .EmailAddress = value ; }
142
142
}
143
- }
143
+ }
144
144
```
145
145
1 . In `Welcome .cshtml .cs `, add logic that associates the logged in user with an attendee :
146
146
```csharp
147
- using System .Threading .Tasks ;
148
- using FrontEnd .Services ;
149
- using FrontEnd .Pages .Models ;
150
- using Microsoft .AspNetCore .Mvc ;
151
- using Microsoft .AspNetCore .Mvc .RazorPages ;
152
- using System .Security .Claims ;
153
- using Microsoft .AspNetCore .Authentication ;
154
- using Microsoft .AspNetCore .Identity ;
155
-
156
- namespace FrontEnd
147
+ using System .Threading .Tasks ;
148
+ using FrontEnd .Services ;
149
+ using FrontEnd .Pages .Models ;
150
+ using Microsoft .AspNetCore .Mvc ;
151
+ using Microsoft .AspNetCore .Mvc .RazorPages ;
152
+ using System .Security .Claims ;
153
+ using Microsoft .AspNetCore .Authentication ;
154
+ using Microsoft .AspNetCore .Identity ;
155
+
156
+ namespace FrontEnd
157
+ {
158
+ public class WelcomeModel : PageModel
157
159
{
158
- public class WelcomeModel : PageModel
160
+ private readonly IApiClient _apiClient ;
161
+
162
+ public WelcomeModel (IApiClient apiClient )
159
163
{
160
- private readonly IApiClient _apiClient ;
164
+ _apiClient = apiClient ;
165
+ }
161
166
162
- public WelcomeModel (IApiClient apiClient )
163
- {
164
- _apiClient = apiClient ;
165
- }
167
+ [BindProperty ]
168
+ public Attendee Attendee { get ; set ; }
166
169
167
- [BindProperty ]
168
- public Attendee Attendee { get ; set ; }
170
+ public IActionResult OnGet ()
171
+ {
172
+ // Redirect to home page if user is anonymous or already registered as attendee
173
+ var isAttendee = User .IsAttendee ();
169
174
170
- public IActionResult OnGet ( )
175
+ if ( ! User . Identity . IsAuthenticated || isAttendee )
171
176
{
172
- // Redirect to home page if user is anonymous or already registered as attendee
173
- var isAttendee = User . IsAttendee ();
177
+ return RedirectToPage ( " /Index " );
178
+ }
174
179
175
- if (! User .Identity .IsAuthenticated || isAttendee )
176
- {
177
- return RedirectToPage (" /Index" );
178
- }
180
+ return Page ();
181
+ }
179
182
180
- return Page ();
181
- }
183
+ public async Task <IActionResult > OnPostAsync ()
184
+ {
185
+ var success = await _apiClient .AddAttendeeAsync (Attendee );
182
186
183
- public async Task < IActionResult > OnPostAsync ( )
187
+ if ( ! success )
184
188
{
185
- var success = await _apiClient .AddAttendeeAsync (Attendee );
186
-
187
- if (! success )
188
- {
189
- ModelState .AddModelError (" " , " There was an issue creating the attendee for this user." );
190
- return Page ();
191
- }
189
+ ModelState .AddModelError (" " , " There was an issue creating the attendee for this user." );
190
+ return Page ();
191
+ }
192
192
193
- // Re-issue the auth cookie with the new IsAttendee claim
194
- User .MakeAttendee ();
195
- await HttpContext .SignInAsync (IdentityConstants .ApplicationScheme , User );
193
+ // Re-issue the auth cookie with the new IsAttendee claim
194
+ User .MakeAttendee ();
195
+ await HttpContext .SignInAsync (IdentityConstants .ApplicationScheme , User );
196
196
197
- return RedirectToPage (" /Index" );
198
- }
197
+ return RedirectToPage (" /Index" );
199
198
}
200
199
}
200
+ }
201
201
```
202
202
1 . Logged in users can now be associated with an attendee by visiting this page .
203
203
204
- ## Add a filter to force logged in users to sign up on welcome page
205
- 1 . Add a folder called `Filters `.
204
+ ## Add a middleware to force logged in users to sign up on welcome page
205
+ 1 . Add a folder called `Middleware `.
206
206
1 . Add a new attribute `SkipWelcomeAttribute .cs ` to allow certain pages or action methods to be skipped from enforcing redirection to the Welcome page :
207
207
208
208
```csharp
209
209
using System ;
210
- using Microsoft .AspNetCore .Mvc .Filters ;
211
210
212
- namespace FrontEnd . Filters
211
+ namespace FrontEnd
213
212
{
214
213
[AttributeUsage (AttributeTargets .Class | AttributeTargets .Method )]
215
- public class SkipWelcomeAttribute : Attribute , IFilterMetadata
214
+ public class SkipWelcomeAttribute : Attribute
216
215
{
217
216
218
217
}
219
218
}
220
219
```
221
- 1 . Add a new class called `RequireLoginFilter .cs` that redirects to the Welcome page if the user is authenticated but not associated with an attendee (does not have the `"IsAttendee"` claim):
220
+ 1 . Add a new class called `RequireLoginMiddleware .cs` that redirects to the Welcome page if the user is authenticated but not associated with an attendee (does not have the `"IsAttendee"` claim):
222
221
223
222
```csharp
224
- public class RequireLoginFilter : IAsyncResourceFilter
223
+ public class RequireLoginMiddleware
225
224
{
226
- private readonly IUrlHelperFactory _urlHelperFactory ;
225
+ private readonly RequestDelegate _next ;
226
+ private readonly LinkGenerator _linkGenerator ;
227
227
228
- public RequireLoginFilter ( IUrlHelperFactory urlHelperFactory )
228
+ public RequireLoginMiddleware ( RequestDelegate next , LinkGenerator linkGenerator )
229
229
{
230
- _urlHelperFactory = urlHelperFactory ;
230
+ _next = next ;
231
+ _linkGenerator = linkGenerator ;
231
232
}
232
233
233
- public async Task OnResourceExecutionAsync ( ResourceExecutingContext context , ResourceExecutionDelegate next )
234
+ public Task Invoke ( HttpContext context )
234
235
{
235
- var urlHelper = _urlHelperFactory . GetUrlHelper ( context );
236
+ var endpoint = context . GetEndpoint ( );
236
237
237
238
// If the user is authenticated but not a known attendee *and* we've not marked this page
238
239
// to skip attendee welcome, then redirect to the Welcome page
239
- if (context .HttpContext . User .Identity .IsAuthenticated &&
240
- ! context . Filters . OfType <SkipWelcomeAttribute >(). Any () )
240
+ if (context .User .Identity .IsAuthenticated &&
241
+ endpoint ? . Metadata . GetMetadata <SkipWelcomeAttribute >() == null )
241
242
{
242
- var isAttendee = context .HttpContext . User .IsAttendee ();
243
+ var isAttendee = context .User .IsAttendee ();
243
244
244
245
if (! isAttendee )
245
246
{
247
+ var url = _linkGenerator .GetUriByPage (context , page : " /Welcome" );
246
248
// No attendee registerd for this user
247
- context .HttpContext . Response .Redirect (urlHelper . Page ( " /Welcome " ) );
249
+ context .Response .Redirect (url );
248
250
249
- return ;
251
+ return Task . CompletedTask ;
250
252
}
251
253
}
252
254
253
- await next ( );
255
+ return _next ( context );
254
256
}
255
257
}
256
258
```
257
- 1 . Register the `RequireLogin ` filter globally with MVC using its options in the ` ConfigureServices ` method in `Startup .cs `:
259
+ 1 . Add the `RequireLoginMiddleware ` in ` Configure ` method in `Startup .cs ` before ` UseEndpoints () `:
258
260
259
261
```csharp
260
- services .AddMvc (options = >
262
+ app .UseMiddleware <RequireLoginMiddleware >();
263
+
264
+ app .UseEndpoints (endpoints =>
261
265
{
262
- options . Filters . AddService < RequireLoginFilter > ();
263
- })
266
+ endpoints . MapRazorPages ();
267
+ });
264
268
```
265
- 1 . Register the filter in DI in the `ConfigureServices ` method in `Startup .cs `
266
-
267
- ```csharp
268
- services .AddTransient <RequireLoginFilter >();
269
- ```
270
269
1 . Update the `Welcome .cshtml .cs ` class with the attribute to ensure it is skipped when the global filter runs:
271
270
272
271
```csharp
@@ -345,9 +344,9 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext
345
344
return new List <SessionResponse >();
346
345
}
347
346
348
- var sessionIds = attendee .Sessions .Select (s => s .ID );
347
+ var sessionIds = attendee .Sessions .Select (s => s .Id );
349
348
350
- sessions .RemoveAll (s => ! sessionIds .Contains (s .ID ));
349
+ sessions .RemoveAll (s => ! sessionIds .Contains (s .Id ));
351
350
352
351
return sessions ;
353
352
}
@@ -364,15 +363,15 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext
364
363
```csharp
365
364
var sessions = await _apiClient .GetSessionsByAttendeeAsync (User .Identity .Name );
366
365
367
- IsInPersonalAgenda = sessions .Any (s => s .ID == id );
366
+ IsInPersonalAgenda = sessions .Any (s => s .Id == id );
368
367
```
369
368
1. Add a form to the bottom of `Session.cshtml` razor page that adds the ability to add/remove the session to the attendee's personal agenda:
370
369
371
370
```html
372
371
<form method = " post" >
373
- < input type = " hidden" name = " sessionId" value = " @Model.Session.ID " / >
372
+ < input type = " hidden" name = " sessionId" value = " @Model.Session.Id " / >
374
373
< p >
375
- < a authz - policy = " Admin" asp - page = " /Admin/EditSession" asp - route - id = " @Model.Session.ID " class = " btn btn-default btn-sm" > Edit < / a >
374
+ < a authz - policy = " Admin" asp - page = " /Admin/EditSession" asp - route - id = " @Model.Session.Id " class = " btn btn-default btn-sm" > Edit < / a >
376
375
@if (Model .IsInPersonalAgenda )
377
376
{
378
377
< button authz = " true" type = " submit" asp - page - handler = " Remove" class = " btn btn-default btn-sm" title = " Remove from my personal agenda" >
@@ -526,14 +525,14 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext
526
525
@foreach (var speaker in session .Speakers )
527
526
{
528
527
< li class = " list-inline-item" >
529
- < a asp - page = " Speaker" asp - route - id = " @speaker.ID " > @speaker .Name < / a >
528
+ < a asp - page = " Speaker" asp - route - id = " @speaker.Id " > @speaker .Name < / a >
530
529
< / li >
531
530
}
532
531
< / ul >
533
532
< form authz = " true" method = " post" >
534
- < input type = " hidden" name = " sessionId" value = " @session.ID " / >
533
+ < input type = " hidden" name = " sessionId" value = " @session.Id " / >
535
534
< p class = " mb-0" >
536
- < a authz - policy = " Admin" asp - page = " /Admin/EditSession" asp - route - id = " @session.ID " class = " btn btn-default btn-sm" > Edit < / a >
535
+ < a authz - policy = " Admin" asp - page = " /Admin/EditSession" asp - route - id = " @session.Id " class = " btn btn-default btn-sm" > Edit < / a >
537
536
@if (Model .UserSessions .Contains (session .ID ))
538
537
{
539
538
< button type = " submit" asp - page - handler = " Remove" class = " btn btn-default btn-sm bg-transparent" title = " Remove from my personal agenda" >
@@ -605,7 +604,7 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext
605
604
CurrentDayOffset = day ;
606
605
607
606
var userSessions = await _apiClient .GetSessionsByAttendeeAsync (User .Identity .Name );
608
- UserSessions = userSessions .Select (u => u .ID ).ToList ();
607
+ UserSessions = userSessions .Select (u => u .Id ).ToList ();
609
608
610
609
var sessions = await GetSessionsAsync ();
611
610
// ...
0 commit comments