mirror of
https://github.com/GCMatters/hermes.git
synced 2026-02-04 13:40:13 +01:00
Merge branch 'ChangingFromControllerToEndpoints' into maksCSS
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection.Metadata;
|
||||
using WebApp.Data;
|
||||
using WebApp.Entities;
|
||||
|
||||
namespace WebApp.Controllers.Api
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/events")]
|
||||
public class EventsApiController : ControllerBase
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public EventsApiController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: /api/events
|
||||
[HttpGet]
|
||||
public IActionResult GetAll()
|
||||
{
|
||||
var events = _context.Events.ToList();
|
||||
return Ok(events);
|
||||
}
|
||||
|
||||
// GET: /api/events/5
|
||||
[HttpGet("{id}")]
|
||||
public IActionResult GetById(int id)
|
||||
{
|
||||
var ev = _context.Events.Find(id);
|
||||
if (ev == null)
|
||||
return NotFound();
|
||||
|
||||
return Ok(ev);
|
||||
}
|
||||
|
||||
// POST: /api/events
|
||||
[HttpPost]
|
||||
public IActionResult Create([FromBody] Event ev)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
return BadRequest(ModelState);
|
||||
|
||||
ev.EventDate = DateTime.SpecifyKind(ev.EventDate, DateTimeKind.Utc);
|
||||
|
||||
_context.Events.Add(ev);
|
||||
_context.SaveChanges();
|
||||
|
||||
return CreatedAtAction(nameof(GetById), new { id = ev.EventId }, ev);
|
||||
}
|
||||
|
||||
// PUT: /api/events/5
|
||||
[HttpPut("{id}")]
|
||||
public IActionResult Update(int id, [FromBody] Event updated)
|
||||
{
|
||||
if (id != updated.EventId)
|
||||
return BadRequest("ID w URL nie zgadza się z obiektem.");
|
||||
|
||||
var ev = _context.Events.Find(id);
|
||||
if (ev == null)
|
||||
return NotFound();
|
||||
|
||||
ev.Title = updated.Title;
|
||||
ev.Description = updated.Description;
|
||||
ev.Location = updated.Location;
|
||||
ev.EventDate = updated.EventDate;
|
||||
ev.OrganisationId = updated.OrganisationId;
|
||||
|
||||
_context.SaveChanges();
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
// DELETE: /api/events/5
|
||||
[HttpDelete("{id}")]
|
||||
public IActionResult Delete(int id)
|
||||
{
|
||||
var ev = _context.Events.Find(id);
|
||||
if (ev == null)
|
||||
return NotFound();
|
||||
|
||||
_context.Events.Remove(ev);
|
||||
_context.SaveChanges();
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
WebApp/DTOs/EventCreateDto.cs
Normal file
15
WebApp/DTOs/EventCreateDto.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using WebApp.Entities;
|
||||
|
||||
namespace WebApp.DTOs;
|
||||
|
||||
// Input values in JSON file to create event
|
||||
public record class EventCreateDto
|
||||
(
|
||||
[Required] int? OrganisationId,
|
||||
[Required][StringLength(50)] string Title,
|
||||
[StringLength(500)] string Description,
|
||||
[Required][StringLength(100)] string Location,
|
||||
[Required] DateTime? EventDate,
|
||||
ICollection<EventSkill> EventSkills
|
||||
);
|
||||
17
WebApp/DTOs/EventDetailsDto.cs
Normal file
17
WebApp/DTOs/EventDetailsDto.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using WebApp.Entities;
|
||||
|
||||
namespace WebApp.DTOs;
|
||||
|
||||
// Output values in JSON file
|
||||
public record class EventDetailsDto
|
||||
(
|
||||
int EventId,
|
||||
[Required] int? OrganisationId,
|
||||
[Required][StringLength(50)] string Title,
|
||||
[StringLength(500)] string Description,
|
||||
[Required][StringLength(100)] string Location,
|
||||
[Required] DateTime? EventDate,
|
||||
ICollection<EventSkill> EventSkills,
|
||||
ICollection<EventRegistration> EventRegistrations
|
||||
);
|
||||
16
WebApp/DTOs/EventSummaryDto.cs
Normal file
16
WebApp/DTOs/EventSummaryDto.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using WebApp.Entities;
|
||||
|
||||
namespace WebApp.DTOs;
|
||||
|
||||
// Output values in JSON file
|
||||
public record class EventSummaryDto(
|
||||
int EventId,
|
||||
[Required] string Organisation,
|
||||
[Required] [StringLength(50)] string Title,
|
||||
[StringLength(500)] string Description,
|
||||
[Required] [StringLength(100)] string Location,
|
||||
[Required] DateTime? EventDate,
|
||||
ICollection<EventSkill> EventSkills,
|
||||
ICollection<EventRegistration> EventRegistrations
|
||||
);
|
||||
15
WebApp/DTOs/EventUpdateDto.cs
Normal file
15
WebApp/DTOs/EventUpdateDto.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using WebApp.Entities;
|
||||
|
||||
namespace WebApp.DTOs;
|
||||
|
||||
// Input values in JSON file to update event
|
||||
public record class EventUpdateDto
|
||||
(
|
||||
[Required] int? OrganisationId,
|
||||
[Required][StringLength(50)] string Title,
|
||||
[StringLength(500)] string Description,
|
||||
[Required][StringLength(100)] string Location,
|
||||
[Required] DateTime? EventDate,
|
||||
ICollection<EventSkill> EventSkills
|
||||
);
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using WebApp.Entities;
|
||||
|
||||
namespace WebApp.DTOs;
|
||||
public record class EventsDto(
|
||||
int EventId,
|
||||
int OrganisationId, //foreign key
|
||||
[StringLength(200)] string Title,
|
||||
[StringLength(800)] string Description,
|
||||
[StringLength(100)] string Location,
|
||||
DateTime EventDate,
|
||||
Organisation? Organisation,
|
||||
ICollection<EventSkill> EventSkills,
|
||||
ICollection<EventRegistration> EventRegistrations
|
||||
);
|
||||
124
WebApp/Endpoints/EventsEndpoints.cs
Normal file
124
WebApp/Endpoints/EventsEndpoints.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using WebApp.Data;
|
||||
using WebApp.DTOs;
|
||||
using WebApp.Entities;
|
||||
using WebApp.Mapping;
|
||||
|
||||
namespace WebApp.Endpoints
|
||||
{
|
||||
public static class EventsEndpoints
|
||||
{
|
||||
const string GetEventEndpointName = "GetEvent";
|
||||
|
||||
public static RouteGroupBuilder MapEventsEndpoints(this WebApplication app)
|
||||
{
|
||||
var group = app.MapGroup("api/events")
|
||||
.WithParameterValidation();
|
||||
|
||||
// GET /events
|
||||
group.MapGet("/", async (ApplicationDbContext dbContext) =>
|
||||
await dbContext.Events
|
||||
.Include(Eve => Eve.Organisation)
|
||||
.OrderByDescending(Eve => Eve.EventId)
|
||||
.Select(Eve => Eve.ToEventSummaryDto()) //EventSummaryDto
|
||||
.AsNoTracking()
|
||||
.ToListAsync());
|
||||
|
||||
// GET /events/1
|
||||
group.MapGet("/{id}", async (int id, ApplicationDbContext dbContext) =>
|
||||
{
|
||||
Event? Eve = await dbContext.Events.FindAsync(id);
|
||||
|
||||
if (Eve is null) return Results.NotFound();
|
||||
|
||||
// Sprawdź, czy token należy do organizacji, a jeżeli tak, to do której.
|
||||
// ...
|
||||
|
||||
// Jeśli token należy do organizacji, która utworzyła to wydarzenie,
|
||||
// to zwróć także EventRegistrations. W przeciwnym razie usuń to pole
|
||||
// przed jego wysłaniem!
|
||||
// ...
|
||||
|
||||
return Results.Ok(Eve.ToEventDetailsDto()); //EventDetailsDto
|
||||
})
|
||||
.WithName(GetEventEndpointName);
|
||||
|
||||
// POST /events
|
||||
group.MapPost("/", async (EventCreateDto newEvent, ApplicationDbContext dbContext) =>
|
||||
{
|
||||
|
||||
// Uzyskaj organizację z tokenu
|
||||
// ...
|
||||
|
||||
Event Eve = newEvent.ToEntity();
|
||||
|
||||
// Wyzeruj EventRegistrations, ponieważ nie są to dane,
|
||||
// które powinniśmy przyjmować bez zgody wolontariuszy!
|
||||
// ...
|
||||
|
||||
dbContext.Events.Add(Eve);
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
return Results.CreatedAtRoute(
|
||||
GetEventEndpointName,
|
||||
new { id = Eve.EventId },
|
||||
Eve.ToEventDetailsDto()); //EventDetailsDto
|
||||
});
|
||||
|
||||
// PUT /events/1
|
||||
group.MapPut("/{id}", async (int id, EventUpdateDto updatedEvent, ApplicationDbContext dbContext) =>
|
||||
{
|
||||
var existingEvent = await dbContext.Events.FindAsync(id);
|
||||
|
||||
if (existingEvent is null)
|
||||
{
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
// Uzyskaj organizację z tokenu
|
||||
// ...
|
||||
|
||||
// Sprawdź, czy organizacja ma prawo
|
||||
// do zmodyfikowania tego (EventId = id) eventu.
|
||||
// ...
|
||||
|
||||
// Nadpisz organisationId (obecne w updatedEvent,
|
||||
// lecz nie sprawdzane poniżej) na to, co odczytaliśmy
|
||||
// do existingEvent.
|
||||
// ...
|
||||
|
||||
dbContext.Entry(existingEvent)
|
||||
.CurrentValues
|
||||
.SetValues(updatedEvent.ToEntity(id));
|
||||
|
||||
dbContext.Entry(existingEvent)
|
||||
.Collection(Eve => Eve.EventRegistrations)
|
||||
.IsModified = false;
|
||||
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
return Results.NoContent();
|
||||
});
|
||||
|
||||
// DELETE /events/1
|
||||
group.MapDelete("/{id}", async (int id, ApplicationDbContext dbContext) =>
|
||||
{
|
||||
|
||||
// Uzyskaj organizację z tokenu
|
||||
// ...
|
||||
|
||||
// Sprawdź, czy organizacja ma prawo
|
||||
// do usunięcia tego (EventId = id) eventu.
|
||||
// ...
|
||||
|
||||
await dbContext.Events
|
||||
.Where(Eve => Eve.EventId == id)
|
||||
.ExecuteDeleteAsync();
|
||||
|
||||
return Results.NoContent();
|
||||
});
|
||||
|
||||
return group;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
WebApp/Mapping/EventMapping.cs
Normal file
64
WebApp/Mapping/EventMapping.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using WebApp.DTOs;
|
||||
using WebApp.Entities;
|
||||
|
||||
namespace WebApp.Mapping;
|
||||
|
||||
public static class EventMapping
|
||||
{
|
||||
public static Event ToEntity(this EventCreateDto ECDto)
|
||||
{
|
||||
return new Event()
|
||||
{
|
||||
OrganisationId = ECDto.OrganisationId!.Value,
|
||||
Title = ECDto.Title,
|
||||
Description = ECDto.Description,
|
||||
Location = ECDto.Location,
|
||||
EventDate = DateTime.SpecifyKind(ECDto.EventDate!.Value, DateTimeKind.Utc),
|
||||
EventSkills = ECDto.EventSkills,
|
||||
EventRegistrations = []
|
||||
};
|
||||
}
|
||||
|
||||
public static Event ToEntity(this EventUpdateDto EUDto, int id)
|
||||
{
|
||||
return new Event()
|
||||
{
|
||||
EventId = id,
|
||||
OrganisationId = EUDto.OrganisationId!.Value,
|
||||
Title = EUDto.Title,
|
||||
Description = EUDto.Description,
|
||||
Location = EUDto.Location,
|
||||
EventDate = DateTime.SpecifyKind(EUDto.EventDate!.Value, DateTimeKind.Utc),
|
||||
EventSkills = EUDto.EventSkills
|
||||
};
|
||||
}
|
||||
|
||||
public static EventSummaryDto ToEventSummaryDto(this Event myEvent)
|
||||
{
|
||||
return new EventSummaryDto(
|
||||
myEvent.EventId,
|
||||
myEvent.Organisation!.Name,
|
||||
myEvent.Title,
|
||||
myEvent.Description,
|
||||
myEvent.Location,
|
||||
myEvent.EventDate,
|
||||
myEvent.EventSkills,
|
||||
myEvent.EventRegistrations
|
||||
);
|
||||
}
|
||||
|
||||
public static EventDetailsDto ToEventDetailsDto(this Event myEvent)
|
||||
{
|
||||
return new EventDetailsDto(
|
||||
myEvent.EventId,
|
||||
myEvent.OrganisationId,
|
||||
myEvent.Title,
|
||||
myEvent.Description,
|
||||
myEvent.Location,
|
||||
myEvent.EventDate,
|
||||
myEvent.EventSkills,
|
||||
myEvent.EventRegistrations
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,54 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using WebApp.Data;
|
||||
using WebApp.Endpoints;
|
||||
using WebApp.Entities;
|
||||
|
||||
// Create WebAppliaction Builder
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
// Configure Database Conecction
|
||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
|
||||
builder.Services.AddDbContext<ApplicationDbContext>(options =>
|
||||
options.UseNpgsql(connectionString));
|
||||
|
||||
// Add Developer Exception Filter
|
||||
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
|
||||
|
||||
// Configure Identity
|
||||
builder.Services.AddDefaultIdentity<User>(options => options.SignIn.RequireConfirmedAccount = true)
|
||||
.AddEntityFrameworkStores<ApplicationDbContext>();
|
||||
builder.Services.AddControllersWithViews();
|
||||
|
||||
// API Services For Swagger
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "hermes", Version = "v1" });
|
||||
});
|
||||
|
||||
// Build Application
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseMigrationsEndPoint();
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "hermes v1"));
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Home/Error");
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseDefaultFiles();
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
// Middleware Configuration
|
||||
app.UseHttpsRedirection(); // Redirects all HTTP requests to HTTPS
|
||||
app.UseDefaultFiles(); // Serves default files (index.html) if no specific file is requested
|
||||
app.UseStaticFiles(); // Serves static files(CSS, JS, Img) from the wwwroot folder.
|
||||
app.UseRouting(); // Enables routing to match incoming request to endpoints
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
app.MapRazorPages();
|
||||
// Map Minimal API Endpoints
|
||||
app.MapEventsEndpoints();
|
||||
|
||||
|
||||
app.Run();
|
||||
|
||||
@@ -21,8 +21,14 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="1.6.24" />
|
||||
<PackageReference Include="MinimalApis.Extensions" Version="0.11.0" />
|
||||
<PackageReference Include="Npgsql" Version="9.0.3" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="8.1.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="8.1.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="8.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user