Shady nagy/remove newton soft (#436)

* replace NewtonSoft with System.Text.Json

* not use auth for brande and types and use GetFromJsonAsync

* fix

* fix

* Auth HttpGet more simple.

* Put, Delete and Post  more simple.

* Fixed Edit for remove image and keep image and change other fields.
Added description required in Blazor Admin.

* Removed using not used

* Refactor AuthService and introduce HttpService. add validation for price.

* return null in HttpService if not success.

* Limt Price to 1000 mximum

* DI for Blazor Services

* one blazor service.

* fix
This commit is contained in:
Shady Nagy
2020-07-29 16:28:55 +02:00
committed by GitHub
parent 24cf9be6ae
commit b640926a19
24 changed files with 164 additions and 190 deletions

View File

@@ -14,7 +14,6 @@
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="3.2.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="3.1.5" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="System.Net.Http.Json" Version="3.2.0" />
</ItemGroup>

View File

@@ -1,6 +1,4 @@
using System.Threading.Tasks;
using BlazorAdmin.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
namespace BlazorAdmin.Helpers
{

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BlazorAdmin.JavaScript
namespace BlazorAdmin.JavaScript
{
public static class JSInteropConstants
{

View File

@@ -1,6 +1,9 @@
@page "/admin"
@attribute [Authorize(Roles = BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS)]
@inject AuthService Auth
@inject BlazorAdmin.Services.CatalogItemServices.ListPaged CatalogItemListPaged
@inject BlazorAdmin.Services.CatalogTypeServices.List TypeList
@inject BlazorAdmin.Services.CatalogBrandServices.List BrandList
@inherits BlazorAdmin.Helpers.BlazorComponent
@namespace BlazorAdmin.Pages.CatalogItemPage

View File

@@ -22,9 +22,9 @@ namespace BlazorAdmin.Pages.CatalogItemPage
{
if (firstRender)
{
catalogItems = await new BlazorAdmin.Services.CatalogItemServices.ListPaged(Auth).HandleAsync(50);
catalogTypes = await new BlazorAdmin.Services.CatalogTypeServices.List(Auth).HandleAsync();
catalogBrands = await new BlazorAdmin.Services.CatalogBrandServices.List(Auth).HandleAsync();
catalogItems = await CatalogItemListPaged.HandleAsync(50);
catalogTypes = await TypeList.HandleAsync();
catalogBrands = await BrandList.HandleAsync();
CallRequestRefresh();
}
@@ -37,9 +37,9 @@ namespace BlazorAdmin.Pages.CatalogItemPage
await DetailsComponent.Open(id);
}
private void CreateClick()
private async Task CreateClick()
{
CreateComponent.Open();
await CreateComponent.Open();
}
private async Task EditClick(int id)

View File

@@ -25,6 +25,8 @@ namespace BlazorAdmin
builder.Services.AddSingleton<AuthenticationStateProvider, CustomAuthStateProvider>();
builder.Services.AddSingleton(sp => (CustomAuthStateProvider)sp.GetRequiredService<AuthenticationStateProvider>());
builder.Services.AddBlazorServices();
await builder.Build().RunAsync();
}
}

View File

@@ -1,12 +1,10 @@
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Threading.Tasks;
using BlazorAdmin.JavaScript;
using Blazored.LocalStorage;
using Microsoft.JSInterop;
using Newtonsoft.Json;
using BlazorShared.Authorization;
namespace BlazorAdmin.Services
@@ -16,12 +14,10 @@ namespace BlazorAdmin.Services
private readonly HttpClient _httpClient;
private readonly ILocalStorageService _localStorage;
private readonly IJSRuntime _jSRuntime;
private static bool InDocker { get; set; }
public string ApiUrl => Constants.GetApiUrl(InDocker);
public string WebUrl => Constants.GetWebUrl(InDocker);
private static bool InDocker { get; set; }
public bool IsLoggedIn { get; set; }
public string UserName { get; set; }
@@ -32,28 +28,9 @@ namespace BlazorAdmin.Services
_jSRuntime = jSRuntime;
}
public async Task<HttpResponseMessage> HttpGet(string uri)
public HttpClient GetHttpClient()
{
return await _httpClient.GetAsync($"{ApiUrl}{uri}");
}
public async Task<HttpResponseMessage> HttpDelete(string uri, int id)
{
return await _httpClient.DeleteAsync($"{ApiUrl}{uri}/{id}");
}
public async Task<HttpResponseMessage> HttpPost(string uri, object dataToSend)
{
var content = ToJson(dataToSend);
return await _httpClient.PostAsync($"{ApiUrl}{uri}", content);
}
public async Task<HttpResponseMessage> HttpPut(string uri, object dataToSend)
{
var content = ToJson(dataToSend);
return await _httpClient.PutAsync($"{ApiUrl}{uri}", content);
return _httpClient;
}
public async Task Logout()
@@ -108,11 +85,6 @@ namespace BlazorAdmin.Services
return (await _localStorage.GetItemAsync<string>("inDocker")).ToLower() == "true";
}
private StringContent ToJson(object obj)
{
return new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json");
}
private async Task LogoutIdentityManager()
{
await _httpClient.PostAsync("Identity/Account/Logout", null);

View File

@@ -1,45 +1,25 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Newtonsoft.Json;
namespace BlazorAdmin.Services.CatalogBrandServices
{
public class List
{
private readonly AuthService _authService;
private readonly HttpClient _httpClient;
public List(AuthService authService)
public List(AuthService authService, HttpClient httpClient)
{
_authService = authService;
_httpClient = httpClient;
}
public async Task<List<CatalogBrand>> HandleAsync()
{
var brands = new List<CatalogBrand>();
if (!_authService.IsLoggedIn)
{
return brands;
}
try
{
var result = await _authService.HttpGet("catalog-brands");
if (result.StatusCode != HttpStatusCode.OK)
{
return brands;
}
brands = JsonConvert.DeserializeObject<CatalogBrandResult>(await result.Content.ReadAsStringAsync()).CatalogBrands;
}
catch (AccessTokenNotAvailableException)
{
return brands;
}
return brands;
return (await _httpClient.GetFromJsonAsync<CatalogBrandResult>($"{_authService.ApiUrl}catalog-brands"))?.CatalogBrands;
}
public static string GetBrandName(IEnumerable<CatalogBrand> brands, int brandId)

View File

@@ -17,11 +17,12 @@ namespace BlazorAdmin.Services.CatalogItemServices
[Required(ErrorMessage = "The Name field is required")]
public string Name { get; set; }
[Required(ErrorMessage = "The Description field is required")]
public string Description { get; set; }
// decimal(18,2)
[RegularExpression(@"^\d+(\.\d{0,2})*$", ErrorMessage = "The field Price must be a positive number with maximum two decimals.")]
[Range(0, 9999999999999999.99)]
[Range(0.01, 1000)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

View File

@@ -11,11 +11,12 @@ namespace BlazorAdmin.Services.CatalogItemServices
[Required(ErrorMessage = "The Name field is required")]
public string Name { get; set; } = string.Empty;
[Required(ErrorMessage = "The Description field is required")]
public string Description { get; set; } = string.Empty;
// decimal(18,2)
[RegularExpression(@"^\d+(\.\d{0,2})*$", ErrorMessage = "The field Price must be a positive number with maximum two decimals.")]
[Range(0, 9999999999999999.99)]
[Range(0.01, 1000)]
[DataType(DataType.Currency)]
public decimal Price { get; set; } = 0;

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BlazorAdmin.Services.CatalogItemServices
namespace BlazorAdmin.Services.CatalogItemServices
{
public class CreateCatalogItemResult
{

View File

@@ -1,31 +1,19 @@
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace BlazorAdmin.Services.CatalogItemServices
{
public class Create
{
private readonly AuthService _authService;
private readonly HttpService _httpService;
public Create(AuthService authService)
{
_authService = authService;
_httpService = new HttpService(authService.GetHttpClient(), authService.ApiUrl);
}
public async Task<CatalogItem> HandleAsync(CreateCatalogItemRequest catalogItem)
{
var catalogItemResult = new CatalogItem();
var result = await _authService.HttpPost("catalog-items", catalogItem);
if (result.StatusCode != HttpStatusCode.OK)
{
return catalogItemResult;
}
catalogItemResult = JsonConvert.DeserializeObject<CreateCatalogItemResult>(await result.Content.ReadAsStringAsync()).CatalogItem;
return catalogItemResult;
return (await _httpService.HttpPost<CreateCatalogItemResult>("catalog-items", catalogItem)).CatalogItem;
}
}
}

View File

@@ -1,31 +1,19 @@
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace BlazorAdmin.Services.CatalogItemServices
{
public class Delete
{
private readonly AuthService _authService;
private readonly HttpService _httpService;
public Delete(AuthService authService)
{
_authService = authService;
_httpService = new HttpService(authService.GetHttpClient(), authService.ApiUrl);
}
public async Task<string> HandleAsync(int catalogItemId)
{
var catalogItemResult = string.Empty;
var result = await _authService.HttpDelete("catalog-items", catalogItemId);
if (result.StatusCode != HttpStatusCode.OK)
{
return catalogItemResult;
}
catalogItemResult = JsonConvert.DeserializeObject<DeleteCatalogItemResult>(await result.Content.ReadAsStringAsync()).Status;
return catalogItemResult;
return (await _httpService.HttpDelete<DeleteCatalogItemResult>("catalog-items", catalogItemId)).Status;
}
}
}

View File

@@ -1,31 +1,19 @@
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace BlazorAdmin.Services.CatalogItemServices
{
public class Edit
{
private readonly AuthService _authService;
private readonly HttpService _httpService;
public Edit(AuthService authService)
{
_authService = authService;
_httpService = new HttpService(authService.GetHttpClient(), authService.ApiUrl);
}
public async Task<CatalogItem> HandleAsync(CatalogItem catalogItem)
{
var catalogItemResult = new CatalogItem();
var result = await _authService.HttpPut("catalog-items", catalogItem);
if (result.StatusCode != HttpStatusCode.OK)
{
return catalogItemResult;
}
catalogItemResult = JsonConvert.DeserializeObject<EditCatalogItemResult>(await result.Content.ReadAsStringAsync()).CatalogItem;
return catalogItemResult;
return (await _httpService.HttpPut<EditCatalogItemResult>("catalog-items", catalogItem)).CatalogItem;
}
}
}

View File

@@ -1,31 +1,19 @@
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace BlazorAdmin.Services.CatalogItemServices
{
public class GetById
{
private readonly AuthService _authService;
private readonly HttpService _httpService;
public GetById(AuthService authService)
{
_authService = authService;
_httpService = new HttpService(authService.GetHttpClient(), authService.ApiUrl);
}
public async Task<CatalogItem> HandleAsync(int catalogItemId)
{
var catalogItemResult = new CatalogItem();
var result = await _authService.HttpGet($"catalog-items/{catalogItemId}");
if (result.StatusCode != HttpStatusCode.OK)
{
return catalogItemResult;
}
catalogItemResult = JsonConvert.DeserializeObject<EditCatalogItemResult>(await result.Content.ReadAsStringAsync()).CatalogItem;
return catalogItemResult;
return (await _httpService.HttpGet<EditCatalogItemResult>($"catalog-items/{catalogItemId}")).CatalogItem;
}
}
}

View File

@@ -1,32 +1,20 @@
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace BlazorAdmin.Services.CatalogItemServices
{
public class ListPaged
{
private readonly AuthService _authService;
private readonly HttpService _httpService;
public ListPaged(AuthService authService)
{
_authService = authService;
_httpService = new HttpService(authService.GetHttpClient(), authService.ApiUrl);
}
public async Task<List<CatalogItem>> HandleAsync(int pageSize)
{
var catalogItems = new List<CatalogItem>();
var result = await _authService.HttpGet($"catalog-items?PageSize={pageSize}");
if (result.StatusCode != HttpStatusCode.OK)
{
return catalogItems;
}
catalogItems = JsonConvert.DeserializeObject<PagedCatalogItemResult>(await result.Content.ReadAsStringAsync()).CatalogItems;
return catalogItems;
return (await _httpService.HttpGet<PagedCatalogItemResult>($"catalog-items?PageSize={pageSize}")).CatalogItems;
}
}

View File

@@ -1,46 +1,25 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Newtonsoft.Json;
namespace BlazorAdmin.Services.CatalogTypeServices
{
public class List
{
private readonly AuthService _authService;
private readonly HttpClient _httpClient;
public List(AuthService authService)
public List(AuthService authService, HttpClient httpClient)
{
_authService = authService;
_httpClient = httpClient;
}
public async Task<List<CatalogType>> HandleAsync()
{
var types = new List<CatalogType>();
if (!_authService.IsLoggedIn)
{
return types;
}
try
{
var result = await _authService.HttpGet("catalog-types");
if (result.StatusCode != HttpStatusCode.OK)
{
return types;
}
types = JsonConvert.DeserializeObject<CatalogTypeResult>(await result.Content.ReadAsStringAsync()).CatalogTypes;
}
catch (AccessTokenNotAvailableException)
{
return types;
}
return types;
return (await _httpClient.GetFromJsonAsync<CatalogTypeResult>($"{_authService.ApiUrl}catalog-types"))?.CatalogTypes;
}
public static string GetTypeName(IEnumerable<CatalogType> types, int typeId)

View File

@@ -0,0 +1,85 @@
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace BlazorAdmin.Services
{
public class HttpService
{
private readonly HttpClient _httpClient;
private readonly string _apiUrl;
public HttpService(HttpClient httpClient, string apiUrl)
{
_httpClient = httpClient;
_apiUrl = apiUrl;
}
public async Task<T> HttpGet<T>(string uri)
where T : class
{
var result = await _httpClient.GetAsync($"{_apiUrl}{uri}");
if (!result.IsSuccessStatusCode)
{
return null;
}
return await FromHttpResponseMessage<T>(result);
}
public async Task<T> HttpDelete<T>(string uri, int id)
where T : class
{
var result = await _httpClient.DeleteAsync($"{_apiUrl}{uri}/{id}");
if (!result.IsSuccessStatusCode)
{
return null;
}
return await FromHttpResponseMessage<T>(result);
}
public async Task<T> HttpPost<T>(string uri, object dataToSend)
where T : class
{
var content = ToJson(dataToSend);
var result = await _httpClient.PostAsync($"{_apiUrl}{uri}", content);
if (!result.IsSuccessStatusCode)
{
return null;
}
return await FromHttpResponseMessage<T>(result);
}
public async Task<T> HttpPut<T>(string uri, object dataToSend)
where T : class
{
var content = ToJson(dataToSend);
var result = await _httpClient.PutAsync($"{_apiUrl}{uri}", content);
if (!result.IsSuccessStatusCode)
{
return null;
}
return await FromHttpResponseMessage<T>(result);
}
private StringContent ToJson(object obj)
{
return new StringContent(JsonSerializer.Serialize(obj), Encoding.UTF8, "application/json");
}
private async Task<T> FromHttpResponseMessage<T>(HttpResponseMessage result)
{
return JsonSerializer.Deserialize<T>(await result.Content.ReadAsStringAsync(), new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
}
}

View File

@@ -0,0 +1,22 @@
using BlazorAdmin.Services.CatalogItemServices;
using Microsoft.Extensions.DependencyInjection;
namespace BlazorAdmin
{
public static class ServicesConfiguration
{
public static IServiceCollection AddBlazorServices(this IServiceCollection service)
{
service.AddScoped<Create>();
service.AddScoped<ListPaged>();
service.AddScoped<Delete>();
service.AddScoped<Edit>();
service.AddScoped<GetById>();
service.AddScoped<BlazorAdmin.Services.CatalogBrandServices.List>();
service.AddScoped<BlazorAdmin.Services.CatalogTypeServices.List>();
return service;
}
}
}

View File

@@ -12,7 +12,6 @@
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.5" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.7.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -2,10 +2,10 @@
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.Infrastructure.Data;
using Newtonsoft.Json;
namespace Microsoft.eShopWeb.Infrastructure.Services
{
@@ -49,7 +49,7 @@ namespace Microsoft.eShopWeb.Infrastructure.Services
DataBase64 = Convert.ToBase64String(fileData),
FileName = fileName
};
var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
using var message = await _httpClient.PostAsync(_url, content);
if (!message.IsSuccessStatusCode)

View File

@@ -15,6 +15,7 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
[Required]
public string Name { get; set; }
public string PictureBase64 { get; set; }
public string PictureUri { get; set; }
public string PictureName { get; set; }
[Range(0.01, 10000)]
public decimal Price { get; set; }

View File

@@ -42,7 +42,7 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
existingItem.UpdateBrand(request.CatalogBrandId);
existingItem.UpdateType(request.CatalogTypeId);
if (string.IsNullOrEmpty(request.PictureBase64))
if (string.IsNullOrEmpty(request.PictureBase64) && string.IsNullOrEmpty(request.PictureUri))
{
existingItem.UpdatePictureUri(string.Empty);
}

View File

@@ -19,6 +19,7 @@ using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Mime;
using BlazorAdmin;
using BlazorAdmin.Services;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Authentication.Cookies;
@@ -149,6 +150,7 @@ namespace Microsoft.eShopWeb.Web
services.AddBlazoredLocalStorage();
services.AddServerSideBlazor();
services.AddScoped<AuthService>();
services.AddBlazorServices();
_services = services; // used to debug registered services
}