使用OData查询字符串

时间:2017-03-29 19:25:03

标签: c# asp.net-core odata

我有一个ASPNet Core Web API应用程序,该应用程序使用Microsoft.AspNetCore.OData.vNext包。当使用查询字符串尝试使用OData功能时,我收到MissingManifestResourceException。这是相关代码:

[EnableQuery]
[HttpGet()]
public class LocationsController : Controller
{
  public IActionResult GetLocations()
  {
    IQueryable<Location> locationEntities = _locationInfoRepo.GetLocations();
    if (locationEntities == null)
    {
        return NotFound();
    }

    var results = Mapper.Map<IEnumerable<LocationDTO>>(locationEntities);

    return Ok(results);
  }
}

注意:我已经尝试将方法上的类型从IActionResult更改为IQueryable&lt;&gt;无济于事。我还注释了Automapper Map方法,以确保那里没有问题。

这是使用EF返回数据的方法:

public IQueryable<Location> GetLocations()
{
    return _context.Locations;
}

以下是网址以及查询字符串:http://localhost/api/locations?$ filter =姓名%20eq%20&#39; Bob&#39;

&#39;名称&#39;是模型中指定的字符串字段,是数据库中的一列。

堆栈追踪:

System.Resources.MissingManifestResourceException: Could not find any resources appropriate for the specified culture or the neutral culture.  Make sure "Microsoft.AspNetCore.OData.SRResources.resources" was correctly embedded or linked into assembly "Microsoft.AspNetCore.OData.vNext" at compile time, or that all the satellite assemblies required are loadable and fully signed.
    at System.Resources.ManifestBasedResourceGroveler.HandleResourceStreamMissing(String fileName)
    at System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(CultureInfo culture, Dictionary`2 localResourceSets, Boolean tryParents, Boolean createIfNotExists, StackCrawlMark& stackMark)
    at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture, Boolean createIfNotExists, Boolean tryParents, StackCrawlMark& stackMark)
    at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
    at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
    at Microsoft.AspNetCore.OData.SRResources.GetString(String name, String[] formatterNames)
    at Microsoft.AspNetCore.OData.SRResources.get_ClrTypeNotInModel()
    at Microsoft.AspNetCore.OData.ODataQueryContext..ctor(IEdmModel model, Type elementClrType, ODataPath path)
    at Microsoft.AspNetCore.OData.EnableQueryAttribute.OnActionExecuted(ActionExecutedContext context)
    at Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute.<OnActionExecutionAsync>d__6.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__25.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
    at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
    at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()

有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:0)

我不知道你的解决方案中有什么,但是当我遇到这个问题时,我已经解决了从控制器中删除[RouteAttribute]的问题。让我告诉你一个有效的例子。

在Startup.cs中你应该:

public void ConfigureServices(IServiceCollection services)
{
    // Your stuff...
    services.AddOData(opt => opt.RoutingConventions
                                    .Insert(0, new DefaultODataRoutingConvention()));
    // Your stuff...
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Your stuff...
    var provider = app.ApplicationServices.GetRequiredService<IAssemblyProvider>();
    var model = GetEdmModel(provider);
    app.UseMvc(builder => builder
        .MapODataRoute("odata", model)
        .MapRoute("default", "api/{controller}/{id?}"));
}

private static IEdmModel GetEdmModel(IAssemblyProvider assemblyProvider)
{
    var builder = new ODataConventionModelBuilder(assemblyProvider);
    builder.EntitySet<Product>("Products");

    return builder.GetEdmModel();
}

然后,在您的控制器中,您应该:

[EnableQuery]
public class ProductsController : Controller
{        
    private readonly IProductDbContext _dbContext;

    public ProductsController(IProductDbContext dbContext)
    {
         _dbContext = dbContext;
    }        

    [HttpGet]
    public IQueryable<Product> Get()
    {
        return _dbContext.Products.AsQueryable();
    }
}

使用MapODataRoute,OData可以找到ProductController而不需要任何属性或自定义路由,您可以查看here

所以,不需要RouteAttribute和这个查询&#34; http://localhost:44302/odata/Products?$ top = 2&amp; $ skip = 2&#34;现在应该工作正常。

也许,您可以发布更详细的代码,以便我们为您提供帮助。希望你解决了你的问题。