30

OData クエリ可能属性で装飾された、このような単純な WebApi メソッドがあります。

    [Queryable]
    public virtual IQueryable<PersonDto> Get()
    {
        return uow.Person().GetAll()); // Currently returns Person instead of PersonD
    }

私がやりたいことは、WebAPI が結果を JSON に変換する前に、AutoMapper を使用してクエリの結果を Person 型から PersonDto 型に変換することです。

どうすればこれができるか知っている人はいますか?GetAll() 呼び出しの後に Mapper.Map を適用してから IQueryable に戻すこともできますが、これにより、OData フィルターが適用される前にテーブル全体が返されてマップされることになります (良くありません!)。

この質問ASP.NET Web APIはクエリ可能なDTOを返しますか? 同じ問題をカバーしています (より良い回答については、2 番目の回答を参照してください)。提案は、カスタム MediaTypeFormatter を使用してチェーンの最後で AutoMapper を使用することですが、私が見た例に基づいてそれを行う方法がわかりません。

どんな助けでもありがたく受け取られます!

-- 詳細情報

IQueryable のソース コードを見てきましたが、残念ながら、この目的でコードを利用する方法が見当たりません。機能しているように見える追加のフィルターを作成することができましたが、エレガントではないことは確かです。

public class PersonToPersonDtoConvertAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
    {
        HttpResponseMessage response = actionExecutedContext.Response;

        if (response != null)
        {
            ObjectContent responseContent = response.Content as ObjectContent;
            var query = (responseContent.Value as IQueryable<Student>).ToList();
            response.Content = new ObjectContent<IEnumerable<StudentResource>>(query.ToList().Select(Mapper.Map<Person, PersonDto>), responseContent.Formatter);
        }
    }
}

次に、アクションを次のように装飾しました

    [Queryable]
    [PersonToPersonDtoConvert]
    public IQueryable<Person> Get()
    {
        return uow.GetRepo<IRepository<Person>>().GetAll();
    }
4

3 に答える 3

30

AutoMapper のQueryable Extensionsを使用します。

まず、マッピングを定義します。

// Old AutoMapper API
// Mapper.CreateMap<Person, PersonDto>();

// Current AutoMapper API
Mapper.Initialize(cfg => 
   cfg.CreateMap<Person, PersonDto>()
);

次に、次のようなものを使用できます。

[EnableQuery]
public IQueryable<PersonDto> Get() {
    // Old AutoMapper API
    // return this.dbContext.Persons.Project().To<PersonDto>();

    // New AutoMapper API
    return this.dbContext.Persons.ProjectTo<PersonDto>();
}

編集 2019 年 4 月: 現在の AutoMapper API を反映するように更新しました。

于 2015-02-25T17:01:48.890 に答える
30

より良い解決策があります。これを試して:

public virtual IQueryable<PersonDto> Get(ODataQueryOptions<Person> query)
{
    var people = query.ApplyTo(uow.Person().GetAll());
    return ConvertToDtos(people);
}

これにより、クエリが PersonDTO ではなく Person で実行されるようになります。コードではなく属性を介して変換を行う場合でも、作成したものと同様のアクション フィルターを実装する必要があります。

于 2013-01-23T22:12:32.500 に答える