2013-08-15 2 views
4
다음과 같이 저는 현재 중 하나로, OData 필터 요청을 웹 API를 실행하고있어

:ASP.NET MVC 웹 API 및 통과 중 하나로, OData 쿼리

public FindOrganizationsQueryResult Execute(FindOrganizationsQuery request) 
{ 
    var organizations = request.ODataQuery.ApplyTo(_mgpQueryContext.Organizations).Cast<Organization>();    
    return new FindOrganizationsQueryResult(organizations); 
} 

쿼리 클래스 :

public IQueryable<OrganizationViewModel> Get(ODataQueryOptions<Organization> oDataQuery) 
{ 
    var query = new FindOrganizationsQuery(oDataQuery); 
    var result =_findOrganizationsQueryHandler.Execute(query); 
    return result.Organizations.Select(o => new OrganizationViewModel { Id = o.PublicId, Name = o.Name }); 
} 

핸들러의 모습 모양은 다음과 같습니다.

public class FindOrganizationsQuery 
{ 
    public FindOrganizationsQuery(ODataQueryOptions<Organization> oDataQuery) 
    { 
     ODataQuery = oDataQuery; 
    } 
    public ODataQueryOptions<Organization> ODataQuery { get; set; } 
} 

요청과 함께 oData 필터를 전달하면 잘 처리되며이 모든 것이 fin으로 작동합니다. 이자형.

하지만 지금은 대신 가져 오기 작업에 형 ODataQueryOptions을 통과, 나는처럼 FindOrganizationsQuery 클래스를 가지고 싶다 :

public IQueryable<OrganizationViewModel> FindOrganizations(FindOrganizationsQuery query) 
{ 
    // query is null 
} 

그러나 쿼리 매개 변수는 항상 null입니다. ODataQueryOptions 매개 변수가 다른 클래스에 있으면 oData 필터를 전달할 수 있습니까?

+0

'FindOrganizationsQuery' 란 무엇이며 왜 필요합니까? 내부 O'''ODataQueryOptions ''FindOrganizations'가'IQueryable '을 반환하는 이유 – Aron

+0

CQS를 사용하기 때문에, 웹 API 내에서 실행해야하는 응용 프로그램 계층에서 쿼리와 명령이 있습니다. 내 서비스 계층. 실제 조직에서 대신 프로젝션을 사용하여 뷰 모델을 반환합니다. 예를 들어 내비게이션 속성을 공개하지 않기 위해 어떤 속성을 공개할지 결정해야하기 때문입니다. 그러나 이것은 모두 작동합니다. –

+0

좋습니다 ...하지만 왜 다운 스트림은'Organization'에 대한 쿼리를 지정하고'OrganizationViewModel'을 수신해야합니까? 다음과 같은 탐색 속성을 계속 노출하게됩니다. – Aron

답변

1

당신은 FindOrganizationsQuery 우리가 ODataQueryOptions 위해 무엇을하고 그 속성으로 FindOrganizationsQuery을 속성 same way에 대한 사용자 지정 매개 변수 바인딩 속성을 작성할 수 있습니다.

아래에 일부 샘플 코드,

public class CustomQueryBindingAttribute : ParameterBindingAttribute 
{ 
    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter) 
    { 
     return new CustomQueryBinding(parameter); 
    } 

    internal class CustomQueryBinding : HttpParameterBinding 
    { 
     public CustomQueryBinding(HttpParameterDescriptor parameter) 
      : base(parameter) 
     { 
     } 

    internal class CustomQueryBinding : HttpParameterBinding 
    { 
     public CustomQueryBinding(HttpParameterDescriptor parameter) 
      : base(parameter) 
     { 
     } 

     public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, 
      HttpActionContext actionContext, CancellationToken cancellationToken) 
     { 
      IEdmModel model = actionContext.Request.GetEdmModel() ?? actionContext.ActionDescriptor.GetEdmModel(typeof(Organization)); 
      ODataQueryContext queryContext = new ODataQueryContext(model, typeof(Organization)); 

      object customQuery = CreateCustomQuery(queryContext, actionContext.Request); 
      SetValue(actionContext, customQuery); 

      return Task.FromResult(0); 
     } 

     private object CreateCustomQuery(ODataQueryContext queryContext, HttpRequestMessage request) 
     { 
      Type parameterType = Descriptor.ParameterType; 
      // Assuming all custom queries have this public property. 
      Type oDataQueryOptionsOfTType = parameterType.GetProperty("ODataQuery").PropertyType; 

      object odataQueryOptions = Activator.CreateInstance(oDataQueryOptionsOfTType, queryContext, request); 
      return Activator.CreateInstance(parameterType, odataQueryOptions); 
     } 
    } 
} 

하고 공공 아니므로 나는 웹 API 소스 코드에서 복사 한 확장 방법.

public static class HttpActionDescriptorExtensions 
{ 
    internal const string EdmModelKey = "MS_EdmModel"; 

    internal static IEdmModel GetEdmModel(this HttpActionDescriptor actionDescriptor, Type entityClrType) 
    { 
     // save the EdmModel to the action descriptor 
     return actionDescriptor.Properties.GetOrAdd(EdmModelKey + entityClrType.FullName, _ => 
     { 
      ODataConventionModelBuilder builder = new ODataConventionModelBuilder(actionDescriptor.Configuration, isQueryCompositionMode: true); 
      EntityTypeConfiguration entityTypeConfiguration = builder.AddEntity(entityClrType); 
      builder.AddEntitySet(entityClrType.Name, entityTypeConfiguration); 
      IEdmModel edmModel = builder.GetEdmModel(); 
      return edmModel; 
     }) as IEdmModel; 
    } 
} 

전체 샘플은 here입니다.

+0

감사합니다. FindOrganizationsQuery는 CustomQueryBinding에서 사용되므로 조직/FindOrganizationsQuery뿐만 아니라 모든 유형의 클래스에서 작동하도록 일반화 할 수 있습니까? –

+0

바인딩에서 매개 변수 유형을 사용할 수 있습니다. ODataQueryOptions 의 'T'유형을 파악해야합니다.이 유형은 사용자 정의 쿼리에 필요합니다. 모든 사용자 지정 쿼리에 이름이 ODataQuery 인 공용 속성이 있다고 가정하고 샘플 코드를 업데이트했습니다. 또한이 특성을 모든 사용자 지정 쿼리에 배치해야합니다. 이 속성은 기본 클래스에도 배치 할 수 있으며 상속받습니다. –

관련 문제