BreezeJs:错误:无法将此端点转换为IQueryable

时间:2017-12-06 20:13:51

标签: breeze

我有asp.net核心1.1.0项目并尝试CodeCamp示例模型。在这个我们一个控制器,它返回如下的Lookup数据:

[BreezeController]
public class BreezeController : ApiController
{

[HttpGet]

public object Lookups()
{
    var rooms = _repository.Rooms;
    var tracks = _repository.Tracks;
    var timeslots = _repository.TimeSlots;
    return new { rooms, tracks, timeslots };
}

上面的Lookups在dataContext.js中调用如下:

function getLookups() {
    return EntityQuery.from('Lookups')
        .using(manager).execute()
        .to$q(querySucceeded, _queryFailed);

    function querySucceeded(data) {
        log('Retrieved [Lookups]', data, true);
        return true;
    }
}

现在,我试图在我的项目中按照上面的说法进行操作,它给出了如下错误:

获取http://Localhost:12345//breeze/demo/Lookups 500(内部服务器错误) 未接受(承诺)

错误:无法将此端点转换为IQueryable

上述问题的任何解决方案......在John Papa的Code camper项目中工作正常。如果我在浏览器中运行它而不是使用breezejs,我的web api查找代码工作正常。

1 个答案:

答案 0 :(得分:0)

Breeze的.NET Core实现需要一个隐藏的第一个参数。它使用它执行REST操作的IQueryable过滤。例如,如果您有一个如下所示的操作:

[HttpGet]
public IQueryable<Order> Orders()

您想获取状态为123且价格低于$ 10的所有订单,则第一个参数将如下所示:

{ 
   "where":{ 
      "Status":123,      
      "Cost":{ 
         "lt":10
      }
   },
   "select":[ 
      "OrderId"
   ]
}

与以前的版本有很大不同。可以通过添加以下内容来更改客户端以传递与此兼容的参数:

breeze.config.initializeAdapterInstance("uriBuilder", "json");

我将此添加到了fetchMetadata调用中。

但是,如果您有带有参数的特定get方法,并且想从Swagger或其他应用程序中调用它,则会导致很多问题。

类似这样的东西:

[HttpGet]
public IQueryable<Order> GetOrdersByStatusAndLessThanCost(int status, int cost)

将生成这样的网址:

GetOrdersByStatusAndLessThanCost?status=123&cost=10

Breeze假定第一个参数(status = 123)是其JSON。因此,它尝试将其解析出来。

在将Breeze迁移到.NET Core时,这是第一个最常见的错误:

  

此EntityQuery ctor需要一个有效的json字符串。以下不是json:status = 123

如果您碰巧通过了Json,但结果不是IQueryable,那么您将收到此错误:

  

无法将此端点转换为IQueryable

所有这些的关键是轻而易举地寻找所需的内容。对于上面的示例,以下URL将起作用:

GetOrdersByStatusAndLessThanCost?{}&status=123&cost=10

请注意添加的{}&作为第一个参数。这告诉微风,就过滤而言,没有任何期望。

要使其适用于Swashbuckle(并扩展为Swagger \ Open API),请将其添加到ConfigureServices调用内的Startup.cs services.AddSwaggerGen(c =>方法中:

c.OperationFilter<AddBreezeParameter>();

然后创建所需的文件:

public class AddBreezeParameter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (context.MethodInfo.ReturnType.Name.StartsWith("IQueryable"))
        {
            if (operation.Parameters == null)
            {
                operation.Parameters = new List<OpenApiParameter>();
            }

            var exampleString = "<br>\":{}," +
                                "<br>&nbsp;&nbsp;&nbsp;&nbsp;\"where\":{" +
                                "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"Status\":123," +
                                "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"Cost\":{" +
                                "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"lt\":10" +
                                "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}" +
                                "<br>&nbsp;&nbsp;&nbsp;}," +
                                "<br>&nbsp;&nbsp;&nbsp;\"select\":[" +
                                "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"OrderId\"," +
                                "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"OrderDateTime\"" +
                                "<br>&nbsp;&nbsp;&nbsp;]" +
                                "<br>}";


            var breezeJsonParam = new OpenApiParameter
            {
                Name = "{\"breezeJson",
                In = ParameterLocation.Query,
                AllowEmptyValue = true,
                Description =
                    "Json used to query a REST resource.  <br>Due to Breeze's nonstandardness and Swashbuckle's not able to customize to allow for it, this MUST start with \":{} and end with }   In between those you can put your query if it is appropriate.  If you do you must add a comma after the starting value and before you value.  Here is an example: " +
                    exampleString,
                AllowReserved = true
            };
            var schema = new OpenApiSchema {Type = "json", Default = new OpenApiString("\":{}}")};
            breezeJsonParam.Schema = schema;
            operation.Parameters.Insert(0, breezeJsonParam);
        }
        else
        {
            if (operation.Parameters == null)
            {
                operation.Parameters = new List<OpenApiParameter>();
            }

            var breezeJsonParam = new OpenApiParameter();
            // Breeze looks for the first parameter so it can do an IQueryable Filter on it.
            // We want it to not have anything for that parameter if it is not an IQueryable.
            breezeJsonParam.Name = "{}&";
            breezeJsonParam.In = ParameterLocation.Query;
            breezeJsonParam.Description = "Do NOT modify this parameter.  (It is here for Breeze compatibility.)";
            var schema = new OpenApiSchema {Example = new OpenApiString(" ")};
            //var schema = new OpenApiSchema {Type = "string", Default = new OpenApiString("\":{}}")};
            breezeJsonParam.Schema = schema;
            operation.Parameters.Insert(0, breezeJsonParam);
        }

    }
}