Use Refit for APIs, make data/API stack async
This commit is contained in:
		
							parent
							
								
									9c4f01ab13
								
							
						
					
					
						commit
						b00158daa7
					
				|  | @ -1,6 +1,8 @@ | |||
| @using Start.Shared | ||||
| @using System.IO | ||||
| @inject HttpClient Http | ||||
| @using Start.Shared.Api | ||||
| @using Refit | ||||
| 
 | ||||
| @inject IBookmarkContainersApi bookmarkContainersApi | ||||
| 
 | ||||
| <Dialog Title="Create Container" Active="this.IsOpen" OnClose="this.OnDialogClose"> | ||||
|     <EditForm Model="this.model" OnValidSubmit="this.OnSubmit"> | ||||
|  | @ -50,16 +52,10 @@ | |||
| 
 | ||||
|     protected async void OnSubmit() | ||||
|     { | ||||
|         HttpResponseMessage response = await Http | ||||
|             .PostAsJsonAsync("BookmarkContainers/Create", model.Title); | ||||
|         ApiResponse<BookmarkContainerDto?> apiResponse = await bookmarkContainersApi | ||||
|             .CreateBookmarkContainer(model.Title); | ||||
| 
 | ||||
|         Stream stream = response.RequestMessage!.Content!.ReadAsStream(); | ||||
|         StreamReader reader = new StreamReader(stream); | ||||
|         Console.WriteLine(reader.ReadToEnd()); | ||||
| 
 | ||||
|         BookmarkContainerDto? container = await response | ||||
|             !.Content | ||||
|             !.ReadFromJsonAsync<BookmarkContainerDto>(); | ||||
|         BookmarkContainerDto? container = apiResponse.Content; | ||||
| 
 | ||||
|         if (container == null) | ||||
|         { | ||||
|  |  | |||
|  | @ -1,5 +1,8 @@ | |||
| @using Microsoft.AspNetCore.Components.WebAssembly.Authentication | ||||
| @using Start.Shared.Api | ||||
| 
 | ||||
| @inject HttpClient Http | ||||
| @inject IBookmarkContainersApi bookmarkContainersApi | ||||
| 
 | ||||
| @{ string title = $"Delete Container \"{this.ContainerTitle}\""; } | ||||
| 
 | ||||
|  | @ -41,8 +44,8 @@ | |||
|     { | ||||
|         try | ||||
|         { | ||||
|             HttpResponseMessage result = await Http | ||||
|                 .DeleteAsync($"BookmarkContainers/Delete/{this.BookmarkContainerId}"); | ||||
|             HttpResponseMessage result = await bookmarkContainersApi | ||||
|                 .DeleteBookmarkContainer(this.BookmarkContainerId); | ||||
| 
 | ||||
|             if (result.StatusCode == System.Net.HttpStatusCode.OK) | ||||
|             { | ||||
|  |  | |||
|  | @ -1,11 +1,16 @@ | |||
| @page "/Start" | ||||
| @using Microsoft.AspNetCore.Authorization | ||||
| @using System.Collections.Generic | ||||
| @using System.Linq | ||||
| @using Microsoft.AspNetCore.Components.WebAssembly.Authentication | ||||
| @using Start.Client.Components | ||||
| @using Start.Shared | ||||
| @attribute [Authorize] | ||||
| @inject HttpClient Http | ||||
| @using Start.Shared.Api | ||||
| @using Refit | ||||
| 
 | ||||
| @* Distiguish from Refit.Authorize *@ | ||||
| @attribute [Microsoft.AspNetCore.Authorization.Authorize] | ||||
| @inject Blazored.LocalStorage.ILocalStorageService localStorage | ||||
| @inject IBookmarkContainersApi bookmarkContainersApi | ||||
| 
 | ||||
| @if (bookmarkContainers == null) | ||||
| { | ||||
|  | @ -101,9 +106,10 @@ else | |||
|     { | ||||
|         try | ||||
|         { | ||||
|             this.bookmarkContainers = await Http | ||||
|                 .GetFromJsonAsync<IList<BookmarkContainerDto>>( | ||||
|                     "BookmarkContainers"); | ||||
|             ApiResponse<IEnumerable<BookmarkContainerDto>> response = await bookmarkContainersApi | ||||
|                 .GetAllBookmarkContainers(); | ||||
| 
 | ||||
|             this.bookmarkContainers = response.Content?.ToList(); | ||||
| 
 | ||||
|             if (this.bookmarkContainers == null || !this.bookmarkContainers.Any()) | ||||
|             { | ||||
|  | @ -120,13 +126,10 @@ else | |||
| 
 | ||||
|     protected async Task CreateDefaultContainer() | ||||
|     { | ||||
|         HttpResponseMessage response = await Http | ||||
|             .PostAsJsonAsync("BookmarkContainers/Create", "Default"); | ||||
|         ApiResponse<BookmarkContainerDto?> response = await bookmarkContainersApi | ||||
|             .CreateBookmarkContainer("Default"); | ||||
| 
 | ||||
|         BookmarkContainerDto? container = await response | ||||
|             .RequestMessage | ||||
|             !.Content | ||||
|             !.ReadFromJsonAsync<BookmarkContainerDto?>(); | ||||
|         BookmarkContainerDto? container = response.Content; | ||||
| 
 | ||||
|         if (container != null) | ||||
|             await this.OnContainerSelected(container.BookmarkContainerId); | ||||
|  | @ -139,12 +142,13 @@ else | |||
|             if (!this.bookmarkContainers?.Any(bc => bc.BookmarkContainerId == bookmarkContainerId) ?? false) | ||||
|                 bookmarkContainerId = this.bookmarkContainers?.First().BookmarkContainerId ?? bookmarkContainerId; | ||||
| 
 | ||||
|             BookmarkContainerDto? bookmarkContainer = await Http | ||||
|                 .GetFromJsonAsync<BookmarkContainerDto?>( | ||||
|                     $"BookmarkContainers/{bookmarkContainerId}"); | ||||
|             ApiResponse<BookmarkContainerDto?> response = await bookmarkContainersApi | ||||
|                 .GetBookmarkContainer(bookmarkContainerId); | ||||
| 
 | ||||
|             BookmarkContainerDto? container = response.Content; | ||||
| 
 | ||||
|             await this.SetSelectedContainer(bookmarkContainerId); | ||||
|             this.selectedBookmarkContainer = bookmarkContainer; | ||||
|             this.selectedBookmarkContainer = container; | ||||
|         } | ||||
|         catch (AccessTokenNotAvailableException e) | ||||
|         { | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ using Microsoft.AspNetCore.Components.WebAssembly.Authentication; | |||
| using Microsoft.AspNetCore.Components.WebAssembly.Hosting; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Blazored.LocalStorage; | ||||
| using Refit; | ||||
| using Start.Shared.Api; | ||||
| 
 | ||||
| namespace Start.Client { | ||||
| 	public class Program { | ||||
|  | @ -16,12 +18,26 @@ namespace Start.Client { | |||
| 					client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)) | ||||
| 				.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>(); | ||||
| 
 | ||||
| 			// Supply HttpClient instances that include access tokens when making requests to the server project | ||||
| 			// Supply HttpClient instances that include access tokens when making requests to the | ||||
| 			// server project | ||||
| 			builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>() | ||||
| 					.CreateClient("Start.ServerAPI")); | ||||
| 
 | ||||
| 			builder.Services.AddApiAuthorization(); | ||||
| 			// Blazor will throw an error if a relative URI is used, so we have to get the base | ||||
| 			// address for building the API paths | ||||
| 			Uri baseUri = new(builder.HostEnvironment.BaseAddress); | ||||
| 
 | ||||
| 			builder.Services.AddRefitClient<IBookmarkContainersApi>() | ||||
| 				.ConfigureHttpClient(c => { | ||||
| 					c.BaseAddress = new Uri(baseUri, "BookmarkContainers"); | ||||
| 				}) | ||||
| 				.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>(); | ||||
| 
 | ||||
| 			builder.Services.AddRefitClient<IBookmarksApi>() | ||||
| 				.ConfigureHttpClient(c => { c.BaseAddress = new Uri(baseUri, "Bookmarks"); }) | ||||
| 				.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>(); | ||||
| 
 | ||||
| 			builder.Services.AddApiAuthorization(); | ||||
| 			builder.Services.AddBlazoredLocalStorage(); | ||||
| 
 | ||||
| 			await builder.Build().RunAsync(); | ||||
|  |  | |||
|  | @ -17,6 +17,8 @@ | |||
|     <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> | ||||
|     <PackageReference Include="System.Net.Http.Json" Version="5.0.0" /> | ||||
|     <PackageReference Include="Blazored.LocalStorage" Version="4.1.5" /> | ||||
|     <PackageReference Include="Refit" Version="6.1.15" /> | ||||
|     <PackageReference Include="Refit.HttpClientFactory" Version="6.1.15" /> | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|   <ItemGroup> | ||||
|  | @ -29,6 +31,8 @@ | |||
| 
 | ||||
|   <ItemGroup> | ||||
|     <None Remove="Blazored.LocalStorage" /> | ||||
|     <None Remove="Refit" /> | ||||
|     <None Remove="Refit.HttpClientFactory" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Content Remove="wwwroot\css\Spectre\" /> | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
|  | @ -22,9 +23,9 @@ namespace Start.Server.Controllers { | |||
| 		[ProducesResponseType(StatusCodes.Status200OK, | ||||
| 			Type = typeof(IEnumerable<BookmarkContainerDto>))] | ||||
| 		[ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
| 		public IActionResult GetAllBookmarkContainers() { | ||||
| 			List<BookmarkContainerDto>? containers = this.bookmarkContainerService | ||||
| 				.GetUserBookmarkContainers(this.GetAuthorizedUserId()) | ||||
| 		public async Task<IActionResult> GetAllBookmarkContainers() { | ||||
| 			List<BookmarkContainerDto>? containers = (await this.bookmarkContainerService | ||||
| 				.GetUserBookmarkContainers(this.GetAuthorizedUserId())) | ||||
| 				.Select(bc => bc.MapToDto()) | ||||
| 				.ToList(); | ||||
| 
 | ||||
|  | @ -38,9 +39,9 @@ namespace Start.Server.Controllers { | |||
| 		[Route("{bookmarkContainerId}")] | ||||
| 		[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BookmarkContainerDto))] | ||||
| 		[ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
| 		public IActionResult GetBookmarkContainer(int bookmarkContainerId) { | ||||
| 			BookmarkContainerDto? container = this.bookmarkContainerService | ||||
| 				.GetBookmarkContainer(this.GetAuthorizedUserId(), bookmarkContainerId, true, true) | ||||
| 		public async Task<IActionResult> GetBookmarkContainer(int bookmarkContainerId) { | ||||
| 			BookmarkContainerDto? container = (await this.bookmarkContainerService | ||||
| 				.GetBookmarkContainer(this.GetAuthorizedUserId(), bookmarkContainerId, true, true)) | ||||
| 				?.MapToDto(); | ||||
| 
 | ||||
| 			if (container == null) | ||||
|  | @ -53,9 +54,9 @@ namespace Start.Server.Controllers { | |||
| 		[Route("Create")] | ||||
| 		[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(BookmarkContainerDto))] | ||||
| 		[ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||
| 		public IActionResult CreateBookmarkContainer([FromBody] string title) { | ||||
| 			BookmarkContainerDto? container = this.bookmarkContainerService | ||||
| 				.CreateBookmarkContainer(this.GetAuthorizedUserId(), title) | ||||
| 		public async Task<IActionResult> CreateBookmarkContainer([FromBody] string title) { | ||||
| 			BookmarkContainerDto? container = (await this.bookmarkContainerService | ||||
| 				.CreateBookmarkContainer(this.GetAuthorizedUserId(), title)) | ||||
| 				?.MapToDto(); | ||||
| 
 | ||||
| 			if (container == null) | ||||
|  | @ -71,8 +72,8 @@ namespace Start.Server.Controllers { | |||
| 		[Route("Delete/{bookmarkContainerId}")] | ||||
| 		[ProducesResponseType(StatusCodes.Status200OK)] | ||||
| 		[ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
| 		public IActionResult DeleteBookmarkContainer(int bookmarkContainerId) { | ||||
| 			bool res = this.bookmarkContainerService | ||||
| 		public async Task<IActionResult> DeleteBookmarkContainer(int bookmarkContainerId) { | ||||
| 			bool res = await this.bookmarkContainerService | ||||
| 				.DeleteBookmarkContainer(this.GetAuthorizedUserId(), bookmarkContainerId); | ||||
| 
 | ||||
| 			if (!res) | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
|  | @ -25,9 +24,9 @@ namespace Start.Server.Controllers { | |||
| 		[Route("{bookmarkId}")] | ||||
| 		[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BookmarkDto))] | ||||
| 		[ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
| 		public IActionResult GetBookmark(int bookmarkId) { | ||||
| 			BookmarkDto? bookmark = this.bookmarkService | ||||
| 				.GetBookmark(this.GetAuthorizedUserId(), bookmarkId) | ||||
| 		public async Task<IActionResult> GetBookmark(int bookmarkId) { | ||||
| 			BookmarkDto? bookmark = (await this.bookmarkService | ||||
| 				.GetBookmark(this.GetAuthorizedUserId(), bookmarkId)) | ||||
| 				?.MapToDto(); | ||||
| 
 | ||||
| 			if (bookmark == null) | ||||
|  | @ -40,10 +39,10 @@ namespace Start.Server.Controllers { | |||
| 		[Route("Create")] | ||||
| 		[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(BookmarkDto))] | ||||
| 		[ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||
| 		public IActionResult CreateBookmark(string title, string url, string? notes, | ||||
| 		public async Task<IActionResult> CreateBookmark(string title, string url, string? notes, | ||||
| 			int bookmarkGroupId) { | ||||
| 			BookmarkDto? bookmark =  this.bookmarkService | ||||
| 				.CreateBookmark(this.GetAuthorizedUserId(), title, url, notes, bookmarkGroupId) | ||||
| 			BookmarkDto? bookmark = (await this.bookmarkService | ||||
| 				.CreateBookmark(this.GetAuthorizedUserId(), title, url, notes, bookmarkGroupId)) | ||||
| 				?.MapToDto(); | ||||
| 
 | ||||
| 			if (bookmark == null) | ||||
|  | @ -58,8 +57,9 @@ namespace Start.Server.Controllers { | |||
| 		[Route("Delete/{bookmarkId}")] | ||||
| 		[ProducesResponseType(StatusCodes.Status200OK)] | ||||
| 		[ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
| 		public IActionResult DeleteBookmark(int bookmarkId) { | ||||
| 			var res = this.bookmarkService.DeleteBookmark(this.GetAuthorizedUserId(), bookmarkId); | ||||
| 		public async Task<IActionResult> DeleteBookmark(int bookmarkId) { | ||||
| 			var res = await this.bookmarkService | ||||
| 				.DeleteBookmark(this.GetAuthorizedUserId(), bookmarkId); | ||||
| 
 | ||||
| 			if (!res) | ||||
| 				return NotFound(); | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Start.Server.Data.Services.Interfaces; | ||||
| using Start.Server.Extensions; | ||||
|  | @ -13,15 +14,15 @@ namespace Start.Server.Data.Services { | |||
| 			this.db = dbContext; | ||||
| 		} | ||||
| 
 | ||||
| 		public BookmarkContainer? GetBookmarkContainer(string userId, | ||||
| 		public async Task<BookmarkContainer?> GetBookmarkContainer(string userId, | ||||
| 			int bookmarkContainerId, bool includeGroups = false, bool includeBookmarks = false) { | ||||
| 			BookmarkContainer? bookmarkContainer = this.db.BookmarkContainers | ||||
| 			BookmarkContainer? bookmarkContainer = await this.db.BookmarkContainers | ||||
| 				.Where(bc => bc.BookmarkContainerId == bookmarkContainerId) | ||||
| 				.If(includeGroups, q => q.Include(bc => bc.BookmarkGroups)) | ||||
| 				.If(includeBookmarks, q => q | ||||
| 					.Include(bc => bc.BookmarkGroups) | ||||
| 					.ThenInclude(bg => bg.Bookmarks)) | ||||
| 				.SingleOrDefault(); | ||||
| 				.SingleOrDefaultAsync(); | ||||
| 
 | ||||
| 			if (bookmarkContainer == null) | ||||
| 				return null; | ||||
|  | @ -33,31 +34,31 @@ namespace Start.Server.Data.Services { | |||
| 			return bookmarkContainer; | ||||
| 		} | ||||
| 
 | ||||
| 		public IList<BookmarkContainer> GetUserBookmarkContainers(string userId, | ||||
| 		public async Task<IList<BookmarkContainer>> GetUserBookmarkContainers(string userId, | ||||
| 			bool includeGroups = false, bool includeBookmarks = false) { | ||||
| 			return this.db.BookmarkContainers | ||||
| 			return await this.db.BookmarkContainers | ||||
| 				.Where(bc => bc.ApplicationUserId == userId) | ||||
| 				.If(includeGroups, q => q.Include(bc => bc.BookmarkGroups)) | ||||
| 				.If(includeBookmarks, q => q | ||||
| 					.Include(bc => bc.BookmarkGroups) | ||||
| 					.ThenInclude(bg => bg.Bookmarks)) | ||||
| 				.ToList(); | ||||
| 				.ToListAsync(); | ||||
| 		} | ||||
| 
 | ||||
| 		public BookmarkContainer? CreateBookmarkContainer(string userId, | ||||
| 		public async Task<BookmarkContainer?> CreateBookmarkContainer(string userId, | ||||
| 			string title) { | ||||
| 			// No need to worry about ownership here | ||||
| 
 | ||||
| 			BookmarkContainer newContainer = new(userId, title); | ||||
| 			this.db.BookmarkContainers.Add(newContainer); | ||||
| 			this.db.SaveChanges(); | ||||
| 			await this.db.BookmarkContainers.AddAsync(newContainer); | ||||
| 			await this.db.SaveChangesAsync(); | ||||
| 			return newContainer; | ||||
| 		} | ||||
| 
 | ||||
| 		public BookmarkContainer? UpdateBookmarkContainer(string userId, | ||||
| 		public async Task<BookmarkContainer?> UpdateBookmarkContainer(string userId, | ||||
| 			BookmarkContainer bookmarkContainer) { | ||||
| 			BookmarkContainer? exitingBookmarkContainer = this.db.BookmarkContainers | ||||
| 				.SingleOrDefault(bc => bc.BookmarkContainerId | ||||
| 			BookmarkContainer? exitingBookmarkContainer = await this.db.BookmarkContainers | ||||
| 				.SingleOrDefaultAsync(bc => bc.BookmarkContainerId | ||||
| 					== bookmarkContainer.BookmarkContainerId); | ||||
| 
 | ||||
| 			if (exitingBookmarkContainer == null | ||||
|  | @ -66,15 +67,15 @@ namespace Start.Server.Data.Services { | |||
| 				return null; | ||||
| 
 | ||||
| 			this.db.Entry(bookmarkContainer).State = EntityState.Modified; | ||||
| 			this.db.SaveChanges(); | ||||
| 			await this.db.SaveChangesAsync(); | ||||
| 
 | ||||
| 			return bookmarkContainer; | ||||
| 		} | ||||
| 
 | ||||
| 		public bool DeleteBookmarkContainer(string userId, int bookmarkContainerId) { | ||||
| 			BookmarkContainer? bookmarkContainer = this.db.BookmarkContainers | ||||
| 		public async Task<bool> DeleteBookmarkContainer(string userId, int bookmarkContainerId) { | ||||
| 			BookmarkContainer? bookmarkContainer = await this.db.BookmarkContainers | ||||
| 				.Where(bc => bc.BookmarkContainerId == bookmarkContainerId) | ||||
| 				.SingleOrDefault(); | ||||
| 				.SingleOrDefaultAsync(); | ||||
| 
 | ||||
| 			if (bookmarkContainer == null) | ||||
| 				return false; | ||||
|  | @ -83,7 +84,7 @@ namespace Start.Server.Data.Services { | |||
| 				return false; | ||||
| 
 | ||||
| 			this.db.BookmarkContainers.Remove(bookmarkContainer); | ||||
| 			this.db.SaveChanges(); | ||||
| 			await this.db.SaveChangesAsync(); | ||||
| 
 | ||||
| 			return true; | ||||
| 		} | ||||
|  |  | |||
|  | @ -1,11 +1,10 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Start.Server.Data.Services.Interfaces; | ||||
| using Start.Server.Extensions; | ||||
| using Start.Server.Models; | ||||
| using Start.Shared; | ||||
| 
 | ||||
| namespace Start.Server.Data.Services { | ||||
| 	public class BookmarkGroupService : IBookmarkGroupService { | ||||
|  | @ -15,12 +14,12 @@ namespace Start.Server.Data.Services { | |||
| 			this.db = dbContext; | ||||
| 		} | ||||
| 
 | ||||
| 		public BookmarkGroup? GetBookmarkGroup(string userId, int bookmarkGroupId, | ||||
| 		public async Task<BookmarkGroup?> GetBookmarkGroup(string userId, int bookmarkGroupId, | ||||
| 			bool includeBookmarks = false) { | ||||
| 			BookmarkGroup? group = db.BookmarkGroups | ||||
| 			BookmarkGroup? group = await db.BookmarkGroups | ||||
| 				.Where(bg => bg.BookmarkGroupId == bookmarkGroupId) | ||||
| 				.If(includeBookmarks, q => q.Include(bg => bg.Bookmarks)) | ||||
| 				.SingleOrDefault(); | ||||
| 				.SingleOrDefaultAsync(); | ||||
| 
 | ||||
| 			if (!BookmarkOwnershipTools.IsBookmarkGroupOwner(db, userId, bookmarkGroupId)) | ||||
| 				return null; | ||||
|  | @ -28,31 +27,31 @@ namespace Start.Server.Data.Services { | |||
| 			return group; | ||||
| 		} | ||||
| 
 | ||||
| 		public IList<BookmarkGroup> GetUserBookmarkGroups(string userId, | ||||
| 		public async Task<IList<BookmarkGroup>> GetUserBookmarkGroups(string userId, | ||||
| 			bool includeBookmarkGroups = false) { | ||||
| 			return this.db.BookmarkGroups | ||||
| 			return await this.db.BookmarkGroups | ||||
| 				.Where(bg => bg.BookmarkContainer!.ApplicationUserId == userId) | ||||
| 				.If(includeBookmarkGroups, q => q.Include(bg => bg.Bookmarks)) | ||||
| 				.ToList(); | ||||
| 				.ToListAsync(); | ||||
| 		} | ||||
| 
 | ||||
| 		public BookmarkGroup? CreateBookmarkGroup(string userId, string title, | ||||
| 		public async Task<BookmarkGroup?> CreateBookmarkGroup(string userId, string title, | ||||
| 			string color, int bookmarkContainerId) { | ||||
| 			if (!BookmarkOwnershipTools | ||||
| 				.IsBookmarkContainerOwner(this.db, userId, bookmarkContainerId)) | ||||
| 				return null; | ||||
| 
 | ||||
| 			BookmarkGroup newBookmarkGroup = new(title, color, bookmarkContainerId); | ||||
| 			this.db.BookmarkGroups.Add(newBookmarkGroup); | ||||
| 			this.db.SaveChanges(); | ||||
| 			await this.db.BookmarkGroups.AddAsync(newBookmarkGroup); | ||||
| 			await this.db.SaveChangesAsync(); | ||||
| 
 | ||||
| 			return newBookmarkGroup; | ||||
| 		} | ||||
| 
 | ||||
| 		public BookmarkGroup? UpdateBookmarkGroup(string userId, | ||||
| 		public async Task<BookmarkGroup?> UpdateBookmarkGroup(string userId, | ||||
| 			BookmarkGroup bookmarkGroup) { | ||||
| 			BookmarkGroup? existingGroup = this.db.BookmarkGroups | ||||
| 				.SingleOrDefault(bg => bg.BookmarkGroupId == bookmarkGroup.BookmarkGroupId); | ||||
| 			BookmarkGroup? existingGroup = await this.db.BookmarkGroups | ||||
| 				.SingleOrDefaultAsync(bg => bg.BookmarkGroupId == bookmarkGroup.BookmarkGroupId); | ||||
| 
 | ||||
| 			if (existingGroup == null) | ||||
| 				return null; | ||||
|  | @ -66,14 +65,14 @@ namespace Start.Server.Data.Services { | |||
| 				return null; | ||||
| 
 | ||||
| 			this.db.Entry(bookmarkGroup).State = EntityState.Modified; | ||||
| 			this.db.SaveChanges(); | ||||
| 			await this.db.SaveChangesAsync(); | ||||
| 
 | ||||
| 			return bookmarkGroup; | ||||
| 		} | ||||
| 
 | ||||
| 		public bool DeleteBookmarkGroup(string userId, int bookmarkGroupId) { | ||||
| 			BookmarkGroup? bookmarkGroup = this.db.BookmarkGroups | ||||
| 				.SingleOrDefault(bg => bg.BookmarkGroupId == bookmarkGroupId); | ||||
| 		public async Task<bool> DeleteBookmarkGroup(string userId, int bookmarkGroupId) { | ||||
| 			BookmarkGroup? bookmarkGroup = await this.db.BookmarkGroups | ||||
| 				.SingleOrDefaultAsync(bg => bg.BookmarkGroupId == bookmarkGroupId); | ||||
| 
 | ||||
| 			if (bookmarkGroup == null) | ||||
| 				return false; | ||||
|  | @ -82,7 +81,7 @@ namespace Start.Server.Data.Services { | |||
| 				return false; | ||||
| 
 | ||||
| 			this.db.BookmarkGroups.Remove(bookmarkGroup); | ||||
| 			this.db.SaveChanges(); | ||||
| 			await this.db.SaveChangesAsync(); | ||||
| 
 | ||||
| 			return true; | ||||
| 		} | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Start.Server.Data.Services.Interfaces; | ||||
| using Start.Server.Models; | ||||
|  | @ -12,29 +13,29 @@ namespace Start.Server.Data.Services { | |||
| 			this.db = dbContext; | ||||
| 		} | ||||
| 
 | ||||
| 		public Bookmark? GetBookmark(string userId, int bookmarkId) { | ||||
| 		public async Task<Bookmark?> GetBookmark(string userId, int bookmarkId) { | ||||
| 			if (!BookmarkOwnershipTools.IsBookmarkOwner(this.db, userId, bookmarkId)) | ||||
| 				return null; | ||||
| 
 | ||||
| 			return this.db.Bookmarks | ||||
| 				.SingleOrDefault(b => b.BookmarkId == bookmarkId); | ||||
| 			return await this.db.Bookmarks | ||||
| 				.SingleOrDefaultAsync(b => b.BookmarkId == bookmarkId); | ||||
| 		} | ||||
| 
 | ||||
| 		public IList<Bookmark> GetUserBookmarks(string userId) { | ||||
| 			return this.db.Bookmarks | ||||
| 		public async Task<IList<Bookmark>> GetUserBookmarks(string userId) { | ||||
| 			return await this.db.Bookmarks | ||||
| 				.Where(b => b.BookmarkGroup!.BookmarkContainer!.ApplicationUserId == userId) | ||||
| 				.ToList(); | ||||
| 				.ToListAsync(); | ||||
| 		} | ||||
| 
 | ||||
| 		public Bookmark? CreateBookmark(string userId, string title, string url, string? notes, | ||||
| 		public async Task<Bookmark?> CreateBookmark(string userId, string title, string url, string? notes, | ||||
| 			int bookmarkGroupId) { | ||||
| 			if (!BookmarkOwnershipTools.IsBookmarkGroupOwner(this.db, userId, bookmarkGroupId)) | ||||
| 				return null; | ||||
| 
 | ||||
| 			Bookmark newBookmark = new(title, url, bookmarkGroupId); | ||||
| 
 | ||||
| 			db.Bookmarks.Add(newBookmark); | ||||
| 			db.SaveChanges(); | ||||
| 			await db.Bookmarks.AddAsync(newBookmark); | ||||
| 			await db.SaveChangesAsync(); | ||||
| 
 | ||||
| 			if (newBookmark.BookmarkId <= 0) | ||||
| 				return null; | ||||
|  | @ -42,7 +43,7 @@ namespace Start.Server.Data.Services { | |||
| 			return newBookmark; | ||||
| 		} | ||||
| 
 | ||||
| 		public Bookmark? UpdateBookmark(string userId, Bookmark bookmark) { | ||||
| 		public async Task<Bookmark?> UpdateBookmark(string userId, Bookmark bookmark) { | ||||
| 			Bookmark? existingBookmark = db.Bookmarks | ||||
| 				.SingleOrDefault(b => b.BookmarkId == bookmark.BookmarkId); | ||||
| 
 | ||||
|  | @ -55,12 +56,12 @@ namespace Start.Server.Data.Services { | |||
| 				return null; | ||||
| 
 | ||||
| 			db.Entry(bookmark).State = EntityState.Modified; | ||||
| 			db.SaveChanges(); | ||||
| 			await db.SaveChangesAsync(); | ||||
| 
 | ||||
| 			return bookmark; | ||||
| 		} | ||||
| 
 | ||||
| 		public bool DeleteBookmark(string userId, int bookmarkId) { | ||||
| 		public async Task<bool> DeleteBookmark(string userId, int bookmarkId) { | ||||
| 			Bookmark? bookmark = db.Bookmarks | ||||
| 				.SingleOrDefault(b => b.BookmarkId == bookmarkId); | ||||
| 
 | ||||
|  | @ -71,7 +72,7 @@ namespace Start.Server.Data.Services { | |||
| 				return false; | ||||
| 
 | ||||
| 			db.Bookmarks.Remove(bookmark); | ||||
| 			db.SaveChanges(); | ||||
| 			await db.SaveChangesAsync(); | ||||
| 
 | ||||
| 			return true; | ||||
| 		} | ||||
|  |  | |||
|  | @ -1,19 +1,18 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | ||||
| using Start.Server.Models; | ||||
| using Start.Shared; | ||||
| 
 | ||||
| namespace Start.Server.Data.Services.Interfaces { | ||||
| 	public interface IBookmarkContainerService { | ||||
| 		public BookmarkContainer? GetBookmarkContainer(string userId, | ||||
| 		public Task<BookmarkContainer?> GetBookmarkContainer(string userId, | ||||
| 			int bookmarkContainerId, bool includeGroups = false, bool includeBookmarks = false); | ||||
| 		public IList<BookmarkContainer> GetUserBookmarkContainers(string userId, | ||||
| 		public Task<IList<BookmarkContainer>> GetUserBookmarkContainers(string userId, | ||||
| 			bool includeGroups = false, bool includeBookmarks = false); | ||||
| 
 | ||||
| 		public BookmarkContainer? CreateBookmarkContainer(string userId, | ||||
| 		public Task<BookmarkContainer?> CreateBookmarkContainer(string userId, | ||||
| 			string title); | ||||
| 		public BookmarkContainer? UpdateBookmarkContainer(string userId, | ||||
| 		public Task<BookmarkContainer?> UpdateBookmarkContainer(string userId, | ||||
| 			BookmarkContainer bookmarkContainer); | ||||
| 		public bool DeleteBookmarkContainer(string userId, int bookmarkContainerId); | ||||
| 		public Task<bool> DeleteBookmarkContainer(string userId, int bookmarkContainerId); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -1,19 +1,20 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | ||||
| using Start.Server.Models; | ||||
| using Start.Shared; | ||||
| 
 | ||||
| namespace Start.Server.Data.Services.Interfaces { | ||||
| 	public interface IBookmarkGroupService { | ||||
| 		public BookmarkGroup? GetBookmarkGroup(string userId, | ||||
| 		public Task<BookmarkGroup?> GetBookmarkGroup(string userId, | ||||
| 			int bookmarkGroupId, bool includeBookmarks = false); | ||||
| 		public IList<BookmarkGroup> GetUserBookmarkGroups(string userId, | ||||
| 		public Task<IList<BookmarkGroup>> GetUserBookmarkGroups(string userId, | ||||
| 			bool includeBookmarks = false); | ||||
| 
 | ||||
| 		public BookmarkGroup? CreateBookmarkGroup(string userId, string title, | ||||
| 		public Task<BookmarkGroup?> CreateBookmarkGroup(string userId, string title, | ||||
| 			string color, int bookmarkContainerId); | ||||
| 		public BookmarkGroup? UpdateBookmarkGroup(string userId, | ||||
| 		public Task<BookmarkGroup?> UpdateBookmarkGroup(string userId, | ||||
| 			BookmarkGroup bookmarkGroup); | ||||
| 		public bool DeleteBookmarkGroup(string userId, int bookmarkGroupId); | ||||
| 		public Task<bool> DeleteBookmarkGroup(string userId, int bookmarkGroupId); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -1,16 +1,15 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | ||||
| using Start.Server.Models; | ||||
| using Start.Shared; | ||||
| 
 | ||||
| namespace Start.Server.Data.Services.Interfaces { | ||||
| 	public interface IBookmarkService { | ||||
| 		public Bookmark? GetBookmark(string userId, int bookmarkId); | ||||
| 		public IList<Bookmark> GetUserBookmarks(string userId); | ||||
| 		public Task<Bookmark?> GetBookmark(string userId, int bookmarkId); | ||||
| 		public Task<IList<Bookmark>> GetUserBookmarks(string userId); | ||||
| 
 | ||||
| 		public Bookmark? CreateBookmark(string userId, string title, string url, | ||||
| 		public Task<Bookmark?> CreateBookmark(string userId, string title, string url, | ||||
| 			string? notes, int bookmarkGroupId); | ||||
| 		public Bookmark? UpdateBookmark(string userId, Bookmark bookmark); | ||||
| 		public bool DeleteBookmark(string userId, int bookmarkId); | ||||
| 		public Task<Bookmark?> UpdateBookmark(string userId, Bookmark bookmark); | ||||
| 		public Task<bool> DeleteBookmark(string userId, int bookmarkId); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ using Start.Server.Data; | |||
| using Start.Server.Models; | ||||
| using Start.Server.Data.Services; | ||||
| using Start.Server.Data.Services.Interfaces; | ||||
| using Refit; | ||||
| using Start.Shared.Api; | ||||
| 
 | ||||
| namespace Start.Server { | ||||
| 	public class Startup { | ||||
|  |  | |||
							
								
								
									
										21
									
								
								Start/Shared/Api/IBookmarkContainersApi.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								Start/Shared/Api/IBookmarkContainersApi.cs
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| using System.Collections.Generic; | ||||
| using System.Net.Http; | ||||
| using System.Threading.Tasks; | ||||
| using Refit; | ||||
| 
 | ||||
| namespace Start.Shared.Api { | ||||
| 	public interface IBookmarkContainersApi { | ||||
| 		[Get("/")] | ||||
| 		Task<ApiResponse<IEnumerable<BookmarkContainerDto>>> GetAllBookmarkContainers(); | ||||
| 
 | ||||
| 		[Get("/{bookmarkContainerId}")] | ||||
| 		Task<ApiResponse<BookmarkContainerDto?>> GetBookmarkContainer(int bookmarkContainerId); | ||||
| 
 | ||||
| 		[Post("/Create")] | ||||
| 		Task<ApiResponse<BookmarkContainerDto?>> CreateBookmarkContainer( | ||||
| 			[Body(BodySerializationMethod.Serialized)] string title); | ||||
| 
 | ||||
| 		[Delete("/Delete/{bookmarkContainerId}")] | ||||
| 		Task<HttpResponseMessage> DeleteBookmarkContainer(int bookmarkContainerId); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										15
									
								
								Start/Shared/Api/IBookmarksApi.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Start/Shared/Api/IBookmarksApi.cs
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| using System.Threading.Tasks; | ||||
| using Refit; | ||||
| 
 | ||||
| namespace Start.Shared.Api { | ||||
| 	public interface IBookmarksApi { | ||||
| 		[Get("{bookmarkId}")] | ||||
| 		Task<BookmarkDto?> GetBookmark(int bookmarkId); | ||||
| 
 | ||||
| 		[Post("/Create")] | ||||
| 		Task CreateBookmark(string title, string url, string? notes, int bookmarkGroupId); | ||||
| 
 | ||||
| 		[Delete("/Delete/{bookmarkId}")] | ||||
| 		Task DeleteBookmark(int bookmarkId); | ||||
| 	} | ||||
| } | ||||
|  | @ -9,4 +9,14 @@ | |||
|   <ItemGroup> | ||||
|     <SupportedPlatform Include="browser" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Remove="Refit" /> | ||||
|     <None Remove="Api\" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Folder Include="Api\" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="Refit" Version="6.1.15" /> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue