Изменение выходного DTO (возвращаемого значения) метода GetAll в AsyncCrudAppService

Я использую AsyncCrudAppService ABP в своих AppServices. Вот мой интерфейс:

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

И обслуживание:

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

Теперь я считаю, что все эти стандартные методы CRUD вернут тип по умолчанию (в моем случае это AssetRequisitionDto). Но я хочу вернуть другой тип для методов Get() и GetAll().

Get() должен иметь гораздо более подробный DTO с подсвойствами свойств навигации. Но GetAll() должен иметь гораздо менее подробную информацию только для заполнения таблицы.

Есть ли способ каким-то образом переопределить возвращаемые типы?


person Emre Can Serteli    schedule 16.07.2018    source источник


Ответы (2)


Да, есть какой-то способ.

// 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);
}

Ссылка: https://github.com/aspnetboilerplate/aspnetboilerplate/issues/2859

person aaron    schedule 16.07.2018
comment
Хм, я пытался, но эти аннотации (ActionName и NonAction) используются в коде контроллера, я полагаю. Мне нужно что-то для прикладного уровня. Хотя я также вижу, что вы упомянули здесь библиотеку AspNetCore. Я должен подчеркнуть, что мой проект использует шаблон MVC. Не ядро. - person Emre Can Serteli; 16.07.2018
comment
NonActionAttribute находится в System.Web.Mvc для MVC5. - person aaron; 20.08.2018

Ну, я заметил, что в конечном итоге мне все равно понадобятся более сложные методы фильтрации. Итак, я создал свои собственные типы и методы.

Сначала я создал свой собственный GetAllInput, производный от PagedAndSortedResultRequestDto. Он подходит для большинства моих сервисов, так как мне обычно нужно запрашивать данные, связанные с сотрудниками и местоположениями:

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

После этого я написал метод GetAll для каждого из своих сервисов. Все они возвращают PagedResultDto<>, поэтому я могу использовать их функции на уровне представления. Вот один из примеров ниже:

//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);
    }

Кстати, ответ Аарона, вероятно, подходит для проектов ASP.NET Core. Но мой проект находится в MVC EF6, поэтому эти аннотации для меня недоступны.

Теперь я отмечаю это как ответ, но если есть более элегантный способ, я рад видеть, и тогда я изменю свою оценку.

person Emre Can Serteli    schedule 20.08.2018
comment
Вы просили переопределить возвращаемый тип GetAll, а ваш ответ — создать несвязанный метод? - person aaron; 20.08.2018