Skip to content

IModelManager implementation with other technologies

Ushakov Michael edited this page Sep 22, 2025 · 4 revisions

Introduction

This page describes how to extend the default behavior and add to specific controllers additional methods. One-line controllers can't have additional methods (at the present moment).

Extend Controllers and Methods

To add new methods to controller you should do the following:

  1. Derive required basic controller and add custom method, i.e. code from an our CBS (Core Banking Solution) project and see GetLoanHistoryAsync method:
namespace Wissance.Ubs.WebApi.Controllers
{

    public class LoanController: BasicCrudController<LoanDto, LoanEntity, Guid, LoanFilter>
    {
        public LoanController(EdgeDBClient edgeDbClient, ILoggerFactory loggerFactory, IHttpContextAccessor httpContextAccessor)
        {
            _manager = new LoanManager(edgeDbClient, LoanFactory.Create, LoanFactory.Create, CrudMasks.ReadUpdate, 
                loggerFactory, httpContextAccessor);
            Manager = _manager;
        }

        [HttpGet]
        [Route("api/[controller]/{loanId}/history")]
        public async Task<LoanHistoryItemDto[]> GetLoanHistoryAsync([FromRoute]Guid loanId)
        {
            OperationResultDto<LoanHistoryItemDto[]> result = await _manager.GetLoanHistoryAsync(loanId);
            if (result != null)
            {
                Response.StatusCode = result.Status;
                if (result.Success)
                    return result.Data;
            }

            Response.StatusCode = (int)StatusCodes.Status500InternalServerError;
            return null;
        }

        private readonly LoanManager _manager;
    }

Manager is a property from the base class, and to use custom manager methods in controller methods, we must store a variable of the exact manager type in a class field. Also, it should be mentioned that in the example above, LoanManager is using EdgeDb, not the EntityFramework, therefore it has a different number of arguments than EfModekManager.

  1. Implement logic of appropriate method in custom manager class, in the example above - GetLoanHistoryAsync, for example see this manager method impl:
public async Task<OperationResultDto<LoanHistoryItemDto[]>> GetLoanHistoryAsync(Guid loanId)
{
     try
     {
          LoanEntity loan = await _edgeDbClient.WithGlobals(_edgeDbGlobals).QuerySingleAsync<LoanEntity>(SelectLoanQuery,
                    new Dictionary<string, object?>()
                    {
                        {ParametersCatalog.IdParam, loanId}
                    });
          if (loan == null)
              return new OperationResultDto<LoanHistoryItemDto[]>(false, (int)StatusCodes.Status400BadRequest, "Loan does not exists", null);
                
          List<LoanHistoryItemDto> history = new List<LoanHistoryItemDto>();
          IDictionary<string, object?> parameters = new Dictionary<string, object?>()
          {
               {ParametersCatalog.LoanIdParam, loanId},
               {ParametersCatalog.DateParam, loan.Date}
          };
                
          IReadOnlyCollection<LoanStatusHistoryEntity> loanHistoryItems = await _edgeDbClient.WithGlobals(_edgeDbGlobals).QueryAsync<LoanStatusHistoryEntity>(SelectLoanStatusHistoryQuery, parameters);
          IReadOnlyCollection<LoanAccrualsEntity> loanAccrualsItems = await _edgeDbClient.WithGlobals(_edgeDbGlobals).QueryAsync<LoanAccrualsEntity>(SelectLoanAccrualsQuery, parameters);
          IReadOnlyCollection<LoanPaymentsEntity> loanPaymentsItems = await _edgeDbClient.WithGlobals(_edgeDbGlobals).QueryAsync<LoanPaymentsEntity>(SelectLoanPaymentsQuery, parameters);
          IReadOnlyCollection<LoanParametersHistoryEntity> loanParametersHistoryItems = await _edgeDbClient.WithGlobals(_edgeDbGlobals).QueryAsync<LoanParametersHistoryEntity>(SelectLoanParametersHistory, parameters);

           if (loanHistoryItems != null && loanHistoryItems.Any())
           {
               history.AddRange(loanHistoryItems.Select(h => LoanHistoryItemFactory.Create(h)));
           }
                
           if (loanAccrualsItems != null && loanAccrualsItems.Any())
           {
               history.AddRange(loanAccrualsItems.Select(h => LoanHistoryItemFactory.Create(h)));
           }
                
           if (loanPaymentsItems != null && loanPaymentsItems.Any())
           {
               history.AddRange(loanPaymentsItems.Select(h => LoanHistoryItemFactory.Create(h)));
           }
                
           if (loanParametersHistoryItems != null && loanParametersHistoryItems.Any())
           {
               history.AddRange(loanParametersHistoryItems.Select(h => LoanHistoryItemFactory.Create(h)));
           }

           history = history.OrderByDescending(f => f.Date).ToList();
                
           return new OperationResultDto<LoanHistoryItemDto[]>(true, (int)HttpStatusCode.OK, string.Empty, history.ToArray());
    }
    catch (Exception e)
    {
        return new OperationResultDto<LoanHistoryItemDto[]>(false, (int)StatusCodes.Status500InternalServerError, 
                    $"An error occurred during getting LoanHistory: {e.Message}", null);
    }
}

Clone this wiki locally