Service Structure
The base structure for providing functionalities in the UpDevs SDK is the service structure. It can be invoked through a controller (the example we're using now) or other interfaces layers, like a console or mobile app, for example.
You can create all the files mentioned here manually, but we strongly advise against that. Please check Generators > Files for a better approach.
In all layers (Domain, Application and UserInterface) you will have access to four base types.
Application/Domain:
- Base[App|Domain]Service
- BaseList[App|Domain]Service
- BaseSearch[App|Domain]Service
- BaseEntity[App|Domain]Service
UserInterface:
- BaseApiController
- BaseListController
- BaseSearchController
- BaseEntityController
Base
Use this type if you will implement all your methods by yourself, in case you don't need the ones provided by the UpDevs SDK. This structure provides only the basic structure for using the UpDevs SDK.
Example
For our example, we'll assume a service named Purchase, the entity Purchase does not exist and, for the purposes of this example, we
don't need to list or search the purchases made.
Domain layer:
public interface IPurchaseDomainService : IDomainService
{
Task<PurchaseResult> MakePurchase(PurchaseData data);
}
public class PurchaseDomainService : BaseDomainService, IPurchaseDomainService
{
public PurchaseDomainService(IServiceProvider serviceProvider, IUnitOfWork unitOfWork)
: base(serviceProvider, unitOfWork) { }
public async Task<PurchaseResult> MakePurchase(PurchaseData data)
{
var order = await UnitOfWork.GetRepository<Order>().AddAsync(new Order
{
Products = GetProducts(data),
TotalAmount = data.TotalAmount
});
var transaction = await UnitOfWork.GetRepository<Transaction>()
.AddAsync(new Transaction
{
Order = order,
PaymentType = data.PaymentType
});
var result = GetResult(transaction);
return result;
}
}
Application layer:
public interface IPurchasesAppService : IAppService
{
Task<PurchaseResult> MakePurchase(PurchaseData data);
}
public class PurchasesAppService : BaseAppService, IPurchasesAppService
{
public PurchasesAppService(IServiceProvider serviceProvider)
: base(serviceProvider) { }
public Task<PurchaseResult> MakePurchase(PurchaseData data)
{
return GetDomainService<IPurchaseDomainService>().MakePurchase(data);
}
}
User Interface layer:
public class PurchasesController : BaseApiController
{
[HttpPost("make")]
public Task<IActionResult> MakePurchase([FromBody] PurchaseData data)
{
return GetService<IPurchasesAppService>().MakePurchase(data);
}
}
Since we didn't need any of the additional functionalities, this was the perfect choice.
List
For this example, let's imagine we have the Country entity and its associated input/response models. For this scenario, the only thing we
need is to allow this entity to be listed. Maybe we are loading static data into our database and will only allow others to list, nothing
else is required. A UI scenario for this, would be a select loading a list of countries.
Example
Domain layer:
public interface ICountriesDomainService : IListDomainService<CountryResponse> { }
public class CountriesDomainService
: BaseListDomainService<Country, CountryResponse>, ICountriesDomainService
{
public CountriesDomainService(
IServiceProvider serviceProvider,
IUnitOfWork unitOfWork
) : base(serviceProvider, unitOfWork) { }
}
Application layer:
public interface ICountriesAppService : IAppService { }
public class CountriesAppService
: BaseListAppService<ICountriesDomainService, CountryResponse>, ICountriesAppService
{
public CountriesAppService(IServiceProvider serviceProvider)
: base(serviceProvider) { }
}
User Interface layer:
public class CountriesController
: BaseListController<ICountriesAppService, CountryResponse, Guid> { }
With this implementation you'll be allowing your API consumers to list al countries and get specific ones by their identifiers.
Search
Now, let's imagine we'd like to allow our API consumers to search the countries in the database, we can use the same example as List
only changing everywhere we read List to Search. A UI scenario for this, would be a table loading the countries.
Entity
Finally, we decided to allow the countries to be edited, removed and created. A UI scenario for this, would be a form allowing CRUD on countries.
Example
Domain layer:
public interface ICountriesDomainService
: IEntityDomainService<CountryInput, CountryResponse> { }
public class CountriesDomainService
: BaseEntityDomainService<Country, CountryInput, CountryResponse>,
ICountriesDomainService
{
public CountriesDomainService(
IServiceProvider serviceProvider,
IUnitOfWork unitOfWork,
DomainExceptionMessagesResource domainExceptionMessagesResource
) : base(serviceProvider, unitOfWork, domainExceptionMessagesResource) { }
}
Application layer:
public interface ICountriesAppService : IAppService { }
public class CountriesAppService
: BaseDomainAppService<ICountriesDomainService, CountryInput, CountryResponse>,
ICountriesAppService
{
public CountriesAppService(IServiceProvider serviceProvider)
: base(serviceProvider) { }
}
User Interface layer:
public class CountriesController
: BaseEntityController<ICountriesAppService, CountryInput, CountryResponse, Guid> { }