Asp.net mvc Web API、OData、$inlinecount和测试

Asp.net mvc Web API、OData、$inlinecount和测试,asp.net-mvc,asp.net-web-api,odata,Asp.net Mvc,Asp.net Web Api,Odata,我以前有一个Web API控制器,看起来像这样: public IQueryable<ApiDesignOverview> GetList( string brandIds = "", string categoryIds = "", string query = "", string categoryOp = "or") public PageResult<ApiDesignOverview

我以前有一个Web API控制器,看起来像这样:

    public IQueryable<ApiDesignOverview> GetList(
        string brandIds = "", 
        string categoryIds = "", 
        string query = "",
        string categoryOp = "or")
    public PageResult<ApiDesignOverview> GetList(
        ODataQueryOptions<ApiDesignOverview> options,
        string brandIds = "", 
        string categoryIds = "", 
        string query = "",
        string categoryOp = "or")
public IQueryable-我不想大量使用OData,因为这需要对应用程序进行大量的重新架构,所以我选择了
PageResult
选项

现在我的控制器看起来像这样:

    public IQueryable<ApiDesignOverview> GetList(
        string brandIds = "", 
        string categoryIds = "", 
        string query = "",
        string categoryOp = "or")
    public PageResult<ApiDesignOverview> GetList(
        ODataQueryOptions<ApiDesignOverview> options,
        string brandIds = "", 
        string categoryIds = "", 
        string query = "",
        string categoryOp = "or")
publicpageresult GetList(
ODataQueryOptions选项,
字符串brandIds=“”,
字符串categoryId=“”,
字符串查询=”,
字符串categoryOp=“或”)
我现在的问题是:

  • 如何模拟用于单元测试的ODataQueryOptions
  • 如果他们不能被嘲笑,我如何创造一个呢?我需要一个
    ODataQueryContext
    来构造一个,它需要一个
    Microsoft.Data.Edm.iedmodel
    ,它需要。。。什么?我找不到这方面的任何文档

真的,如果我能像以前一样从控制器签名中删除ODataQueryOptions,那就更好了。这可能吗?

如果您希望返回IQueryable,但又希望获得$inlinecount的支持,那么仍然可以通过修改QueryableAttribute来实现这一点

public class InlineCountQueryableAttribute : QueryableAttribute
{
    private static MethodInfo _createPageResult =
        typeof(InlineCountQueryableAttribute)
        .GetMethods(BindingFlags.Static | BindingFlags.NonPublic)
        .Single(m => m.Name == "CreatePageResult");

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        base.OnActionExecuted(actionExecutedContext);

        HttpRequestMessage request = actionExecutedContext.Request;
        HttpResponseMessage response = actionExecutedContext.Response;

        IQueryable result;
        if (response.IsSuccessStatusCode
            && response.TryGetContentValue<IQueryable>(out result))
        {
            long? inlineCount = request.GetInlineCount();
            if (inlineCount != null)
            {
                actionExecutedContext.Response = _createPageResult.MakeGenericMethod(result.ElementType).Invoke(
                    null, new object[] { request, request.GetInlineCount(), request.GetNextPageLink(), result }) as HttpResponseMessage;
            }
        }
    }

    internal static HttpResponseMessage CreatePageResult<T>(HttpRequestMessage request, long? count, Uri nextpageLink, IEnumerable<T> results)
    {
        return request.CreateResponse(HttpStatusCode.OK, new PageResult<T>(results, nextpageLink, count));
    }
}
公共类InlineCountQueryableAttribute:QueryableAttribute
{
私有静态方法信息\u createPageResult=
类型(InlineCountQueryableAttribute)
.GetMethods(BindingFlags.Static | BindingFlags.NonPublic)
.Single(m=>m.Name==“CreatePageResult”);
公共覆盖无效OnActionExecuted(HttpActionExecuteContext ActionExecuteContext)
{
base.OnActionExecuted(actionExecutedContext);
HttpRequestMessage request=ActionExecuteContext.request;
HttpResponseMessage response=actionExecutedContext.response;
可预测的结果;
如果(response.issusccessstatuscode
&&响应.TryGetContentValue(输出结果))
{
long?inlineCount=request.GetInlineCount();
if(inlineCount!=null)
{
actionExecutedContext.Response=\u createPageResult.MakeGenericMethod(result.ElementType).Invoke(
null,新对象[]{request,request.GetInlineCount(),request.GetNextPageLink(),result})作为HttpResponseMessage;
}
}
}
内部静态HttpResponseMessage CreatePageResult(HttpRequestMessage请求、长计数、Uri下一步消息链接、IEnumerable结果)
{
return request.CreateResponse(HttpStatusCode.OK,new PageResult(results,nextpageLink,count));
}
}
请注意,我正在使用反射创建PageResult。您可以返回您喜欢的对象,该对象可以由您使用的格式化程序进行格式化。如果您使用Json格式化程序,带有结果和计数的匿名对象也可以使用。

如果您不想(或不能像我的情况那样)改变使用ODataQueryOptions和PageResult的方式,下面是如何为单元测试创建ODataQueryOptions实例:

//arrange
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/MyProject/api/Customers?$filter=CustomerID eq 1");
var controller = new CustomersController
{
    Request = request
};

ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); 
modelBuilder.EntitySet<Customer>("Customers"); 
var opts = new ODataQueryOptions<Customer>(new ODataQueryContext(modelBuilder.GetEdmModel(),typeof(Customer)), request);

//act
var result = controller.Get(opts);

//assert
Assert.AreEqual(1, result.Items.First().CustomerID);
//排列
var request=newhttprequestmessage(HttpMethod.Get)http://localhost/MyProject/api/Customers?$filter=客户ID等式1“;
var控制器=新CustomerController
{
请求=请求
};
ODataModelBuilder modelBuilder=新ODataConventionModelBuilder();
modelBuilder.EntitySet(“客户”);
var opts=新的ODataQueryOptions(新的ODataQueryContext(modelBuilder.GetEdmModel(),typeof(Customer)),请求);
//表演
var结果=controller.Get(opts);
//断言
Assert.AreEqual(1,result.Items.First().CustomerID);

在最新的
ODataController
中,有一个
允许的查询选项
解决了这个问题

public class MyOdataController : ODataController

    {
        [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
        public IQueryable<Product> Get()
        {
            return Products.AsQueryable();
        }
    }
公共类MyOdataController:ODataController
{
[可查询(AllowedQueryOptions=AllowedQueryOptions.All)]
公共IQueryable Get()
{
退货产品。AsQueryable();
}
}

是否有一种方法可用于具有许多相关实体的EntitySet,这些实体都与您的测试逻辑无关?请参阅:为了单元测试,我需要通过Top并跳过。我该怎么做呢?这些字段是只读的。