Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET MVC Web API和传递oData查询_C#_Asp.net Web Api_Odata_Asp.net Web Api Odata - Fatal编程技术网

C# ASP.NET MVC Web API和传递oData查询

C# ASP.NET MVC Web API和传递oData查询,c#,asp.net-web-api,odata,asp.net-web-api-odata,C#,Asp.net Web Api,Odata,Asp.net Web Api Odata,我目前正在使用oData筛选器请求执行Web API,如下所示: public IQueryable<OrganizationViewModel> Get(ODataQueryOptions<Organization> oDataQuery) { var query = new FindOrganizationsQuery(oDataQuery); var result =_findOrganizationsQueryHandler.Execute(que

我目前正在使用oData筛选器请求执行Web API,如下所示:

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 IQueryable Get(ODataQueryOptions-oDataQuery)
{
var查询=新的FindOrganizationsQuery(oDataQuery);
var result=\u findorOrganizationsQueryHandler.Execute(查询);
返回result.Organizations.Select(o=>neworganizationViewModel{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; }
}
公共FindOrganizationsQueryResult执行(FindOrganizationsQuery请求)
{
var organizations=request.ODataQuery.ApplyTo(_mgpQueryContext.organizations.Cast();
返回新的FindOrganizationsQueryResult(组织);
}
查询类如下所示:

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; }
}
公共类查找组织
{
公共FindOrganizationsQuery(ODataQueryOptions oDataQuery)
{
ODataQuery=ODataQuery;
}
公共ODataQueryOptions ODataQuery{get;set;}
}
所以,如果我将oData过滤器与请求一起传递,它会得到很好的处理,并且一切正常

但是现在,我希望使用FindOrganizationsQuery类,而不是将ODataQueryOptions类型传递给Get操作,如:

public IQueryable<OrganizationViewModel> FindOrganizations(FindOrganizationsQuery query)
{
    // query is null
}
公共可查询的FindOrganizations(FindOrganizationsQuery)
{
//查询为空
}

但是,查询参数始终为空。如果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);
        }
    }
}
以及我从WebAPI源代码复制的扩展方法,因为它不是公共的

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

我有完整的样本。

什么是
FindOrganizationsQuery
,为什么需要它?为什么内部
ODataQueryOptions
FindOrganizations
返回
IQueryable
我使用CQS,因此我的应用层中有查询和命令,需要从我的服务层的web api中执行。我返回一个视图模型,而不是使用投影的实际组织,因为我想决定要公开哪些属性(例如,我不公开导航属性)。但这一切都是可行的。好吧……但为什么下游指定对
组织的查询
并接收
组织视图模型
?您仍然会像这样公开导航属性…一点也不。视图模型与实际数据实体不同。我想只有在使用的属性名称在Organization和OrganizationViewModel中相等时,查询才会起作用?谢谢。FindOrganizationsQuery用于CustomQueryBinding,那么如何将其设置为泛型,以便它能够与任何类型的类一起工作,而不仅仅是Organization/FindOrganizationsQuery?参数类型在绑定中可用。您需要找出在自定义查询的ctor中预期的ODataQueryOptions的
T
类型。我已经更新了示例代码,假设您的所有自定义查询都有一个名为ODataQuery的公共属性。此外,您需要将此属性放置在所有自定义查询上。您还可以将该属性放置在基类上,并将其继承。