Here's an example of the sequence of code to implement a (specific) call from the server:
MyProject/MyProject.Client/Components/Application/PostsBrowser.razor.cs (client)
public partial class PostsBrowser : ComponentBase { ... [Inject] public ClientDbAccess DbAccess { get; set; } = null!; private string SearchTerm = ""; public async Task<IEnumerable<PostObject>> GetPostsOfCurrentPage_Async() { var search = new ClientDbAccess.GetPostsByCriteriaParams( bodyPattern: this.SearchTerm ); IEnumerable<PostObject> posts = await this.DbAccess.GetPostsByCriteria_Async( search ); return posts; }}MyProject/MyProject.Client/Services/DbAccess_Posts.cs (client)
public partial class ClientDbAccess { ... public class GetPostsByCriteriaParams( string bodyPattern ) { public string BodyPattern { get; } = bodyPattern; }; public async Task<IEnumerable<PostObject>> GetPostsByCriteria_Async( GetPostsByCriteriaParams parameters ) { HttpResponseMessage msg = await this.Http.PostAsJsonAsync( "Post/GetByCriteria", parameters ); msg.EnsureSuccessStatusCode(); IEnumerable<PostObject>? ret = await msg.Content.ReadFromJsonAsync<IEnumerable<PostObject>>(); if (ret is null) { throw new InvalidDataException("Could not deserialize IEnumerable<PostEntry>"); } return ret; }}MyProject/MyProject/Controllers/Post.cs (server)
[ApiController][Route("[controller]")]public class PostController : ControllerBase { private readonly ServerDbAccess DbAccess; public PostController(ServerDbAccess dbAccess) { this.DbAccess = dbAccess; } ... [HttpPost("GetByCriteria")] public async Task<IEnumerable<PostObject>> GetByCriteria_Async( ClientDbAccess.GetPostsByCriteriaParams parameters ) { using IDbConnection dbCon = await this.DbAccess.ConnectDb_Async(); return await this.DbAccess.GetPostsByCriteria_Async(dbCon, parameters); }}MyProject/MyProject/Data/DbAccess_Posts.cs (server)
public partial class ServerDbAccess { public class PostEntryData { public long Id; public DateTime Created; public string Body = ""; public async Task<PostObject> CreatePost_Async(IDbConnection dbCon, ServerDbAccess dbAccess) { return new PostObject( id: this.Id, created: this.Created, body: this.Body ); } } ... private (string sql, IDictionary<string, object> sqlParams) GetPostsByCriteriaSql(ClientDbAccess.GetPostsByCriteriaParams parameters ) { string sql = $"SELECT * FROM Posts AS MyPosts "; var sqlParams = new Dictionary<string, object>(); if (!string.IsNullOrEmpty(parameters.BodyPattern)) { sql += "WHERE MyPosts.Body LIKE REPLACE(REPLACE(REPLACE(@Body, '[', '[[]'), '_', '[_]'), '%', '[%]')"; sqlParams["@Body"] = $"%{parameters.BodyPattern}%"; } return (sql, sqlParams); } public async Task<IEnumerable<PostObject>> GetPostsByCriteria_Async( IDbConnection dbCon, ClientDbAccess.GetPostsByCriteriaParams parameters ) { if (parameters.PostsPerPage == 0) { return Enumerable.Empty<PostObject>(); } (string sql, IDictionary<string, object> sqlParams) = this.GetPostsByCriteriaSql(parameters, false); return await dbCon.QueryAsync<PostEntryData>( sql, new DynamicParameters(sqlParams) ); }}What are my options to reduce/improve this pile of code? Preferably ones that exist within Blazor, ASP.NET Core, and the standard libraries only. I'm not asking for improvement upon this specific code; it is just an example of the mess that's happened, and an indication of how it works. I simply need ideas for any available resources or libraries to reduce this boilerplate.