1

I'm using ABP's AsyncCrudAppService in my AppServices. Here's my interface:

public interface IAssetRequisitionAppService : IAsyncCrudAppService
    <AssetRequisitionDto, Guid, GetAllInput, AssetRequisitionDto, AssetRequisitionDto, AssetRequisitionDetailsDto>
{ }

And the service:

public class AssetRequisitionAppService : AsyncCrudAppService
    <AssetRequisition, AssetRequisitionDto, Guid, GetAllInput, AssetRequisitionDto, AssetRequisitionDto, AssetRequisitionDetailsDto>, 
    IAssetRequisitionAppService
{
    public AssetRequisitionAppService(IRepository<AssetRequisition, Guid> repository) : base(repository)
    { }
}

Now, I believe all these standard CRUD methods will return the default type (which is AssetRequisitionDto in my case). But, what I want to do is to return a different type for Get() and GetAll() methods.

Get() should have a much more detailed DTO with subproperties of the Navigation props. But GetAll() should have a much less detailed one just to populate a table.

Is there a way to override the return types in some way?

Emre Can Serteli
  • 389
  • 1
  • 7
  • 17

2 Answers2

1

Yes, there is some way.

// using Microsoft.AspNetCore.Mvc;

[ActionName(nameof(GetAll))]
public PagedResultRequestDto MyGetAll(PagedResultRequestDto input)
{
    return input;
}

[NonAction]
public override Task<PagedResultDto<UserDto>> GetAll(PagedResultRequestDto input)
{
    return base.GetAll(input);
}

Reference: https://github.com/aspnetboilerplate/aspnetboilerplate/issues/2859

aaron
  • 39,695
  • 6
  • 46
  • 102
  • Umm, I tried but those annotations (`ActionName` and `NonAction`) are used in the controller code I believe. I need something for the Application layer. Though I also see you mentioned AspNetCore library here. I should emphasize my project uses the MVC template. Not Core. – Emre Can Serteli Jul 16 '18 at 20:11
  • `NonActionAttribute` is in `System.Web.Mvc` for MVC5. – aaron Aug 20 '18 at 13:59
1

Well I noticed I'll eventually need more complex filtering methods anyway. So, I created my custom types and methods.

First, I created my own GetAllInput derived from PagedAndSortedResultRequestDto. It's suited for most of my services, as I usually need to query the data related to employees and locations:

public class GetAllInput : PagedAndSortedResultRequestDto
{
    public long? PersonId { get; set; }
    public long? LocationId { get; set; }
    public EEmployeeType? EmployeeType { get; set; }
}

After that I wrote a GetAll method for each of my services. They all return a PagedResultDto<> so I can use it's functionalities in presentation layer. Here's one example below:

//MovableAppService

    public PagedResultDto<MovableLineDto> GetAllLinesRelatedToUser(GetAllInput input)
    {
        Logger.Info("Loading all movables related to current user");

        IQueryable<Movable> queryable = null;
        if (input.PersonId.HasValue)
        {
            if (input.EmployeeType == EEmployeeType.Recorder)
            {
                var recorder = _personRepository.GetAll()
                .OfType<Employee>()
                .FirstOrDefault(x => x.Id == input.PersonId);
                var authorizedStorageIds = recorder.StoragesAuthorized.Select(y => y.Id);

                queryable = _repository.GetAll()
                    .Where(x => authorizedStorageIds.Contains(x.StorageOfOriginId));
            }
            else if (input.EmployeeType == EEmployeeType.UnitManager)
            {
                var locationCodes = _locationRepository.GetAll()
                    .Where(x => x.ManagerInChargeId == input.PersonId)
                    .Select(x => x.Code);

                foreach (var code in locationCodes)
                {
                    queryable = _locationRepository.GetAll()
                        .Where(x => x.Code.StartsWith(code))
                        .SelectMany(x => x.AssignmentDocs)
                        .SelectMany(x => x.Movements)
                        .OfType<Assignment>()
                        .Where(x => x.TimeOfReturn == null)
                        .Select(x => x.Asset)
                        .OfType<Movable>();
                    queryable = queryable.Concat(queryable);
                }
            }
            else if (input.TenantIdsOversee.Count() > 0)
            {
                var overseer = _personRepository.GetAll()
                    .OfType<Overseer>()
                    .FirstOrDefault(x => x.Id == input.PersonId);
                var overseeingTenantIds = overseer.TenantsOversee.Select(y => y.Id);

                queryable = _repository.GetAll()
                   .Where(x => overseeingTenantIds.Contains((int)x.TenantId));
            }
            else if (input.EmployeeType == EEmployeeType.Employee)
            {
                queryable = _personRepository.GetAll()
                    .OfType<Employee>()
                    .Where(x => x.Id == input.PersonId)
                    .SelectMany(x => x.AssignmentDocs)
                    .SelectMany(x => x.Movements)
                    .OfType<Assignment>()
                    .Where(x => x.TimeOfReturn == null)
                    .Select(x => x.Asset)
                    .OfType<Movable>();
            }
        }
        var list = queryable.ToList()
                .OrderBy(x => x.Category.Definition);
        var items = _objectMapper.Map<IReadOnlyList<MovableLineDto>>(list);

        return new PagedResultDto<MovableLineDto>(items.Count, items);
    }

Btw, aaron's answer is probably valid for ASP.NET Core projects. But my project is in MVC EF6, so those annotations are not available for me.

Now I'm marking this as the answer but if there's a more elegant way, I'm happy to see and I'll change my mark then.

Emre Can Serteli
  • 389
  • 1
  • 7
  • 17
  • You asked to override the return type of `GetAll` and your answer is to create an unrelated method? – aaron Aug 20 '18 at 13:55