ASP.NET MVC Web API和传递oData查询
本文关键字:oData 查询 API NET MVC Web ASP | 更新日期: 2023-09-27 18:27:41
我目前正在执行Web API,其中包含如下oData过滤器请求:
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 FindOrganizationsQueryResult Execute(FindOrganizationsQuery request)
{
var organizations = request.ODataQuery.ApplyTo(_mgpQueryContext.Organizations).Cast<Organization>();
return new FindOrganizationsQueryResult(organizations);
}
查询类看起来像:
public class FindOrganizationsQuery
{
public FindOrganizationsQuery(ODataQueryOptions<Organization> oDataQuery)
{
ODataQuery = oDataQuery;
}
public ODataQueryOptions<Organization> ODataQuery { get; set; }
}
因此,如果我在请求中通过oData过滤器,它会得到很好的处理,这一切都很好。
但是现在,我不想将类型ODataQueryOptions传递给Get操作,而是希望拥有FindOrganizationsQuery类,如:
public IQueryable<OrganizationViewModel> FindOrganizations(FindOrganizationsQuery query)
{
// query is null
}
但是,查询参数始终为null。如果ODataQueryOptions参数在另一个类中,我如何传递oData筛选器?
您可以像对待ODataQueryOptions
一样,为FindOrganizationsQuery
编写自定义参数绑定属性,然后用该属性为FindOrganizationsQuery
赋予属性。
下面的一些示例代码,
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);
}
}
}
以及我从web 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;
}
}
我这里有完整的样品。