我正在尝试使用ODATA-4(内部Web API 2.2项目)创建一个ODATA API端点,在此我需要在ODATA Controller中进行我的GET ACTION之一,以接受多个字符串参数(除了创建ODATA控制器的实体中的属性外,它们是自定义搜索属性)。
但是,到目前为止,我已经进行了所有试验,在访问浏览器中的特定操作时,我总是会遇到一个或另一个错误。到目前为止修复我的错误。
代码如下:
package.config:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.Mvc" version="5.1.2" targetFramework="net45" />
<package id="Microsoft.AspNet.OData" version="5.3.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="3.1.2" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.OData" version="5.1.2" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="3.1.2" targetFramework="net45" />
<package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net45" />
<package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net45" />
<package id="Microsoft.OData.Core" version="6.5.0" targetFramework="net45" />
<package id="Microsoft.OData.Edm" version="6.5.0" targetFramework="net45" />
</packages>
Webapiconfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<DocumentsModel>("SampleData");
var function = builder.Function("SampleFunction");
function.Parameter<string>("catGUIDOrText");
function.Parameter<string>("type");
function.Parameter<string>("isAutoCompSearch");
function.ReturnsCollectionFromEntitySet<DocumentsModel>("SampleData");
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
ODATA控制器:
[ODataRoutePrefix("SampleData")]
public class SampleDataController : ODataController
{
[EnableQuery]
[HttpGet]
[ODataRoute("SampleFunction(catGUIDOrText={catGUIDOrText},type={type},isAutoCompSearch={isAutoCompSearch})")]
public IEnumerable<DocumentsModel> GetSampleData([FromODataUri] string catGUIDOrText, [FromODataUri] string type, [FromODataUri] string isAutoCompSearch)
{
return new List<DocumentsModel>().AsQueryable<DocumentsModel>();
}
}
注意: - DocumentModel是一个具有所有字符串属性的类。
错误详细信息
现在,通过下面的URL访问浏览器时,我会遇到错误:
url:http://localhost/virtualDirectoryNameIiniis/odata/sampledata/samemfunction(catguidortext ='752',type ='230',isautocsearch ='false'')
错误:
路径模板 'sampledata/samplefunction(catguidortext = {catguidortext},type = {type},isautocompSearch = {isautocompSearch})' 在控制器"采样"中的动作" getsampledata"上不是 有效的ODATA路径模板。请求URI无效。自从 细分"采样"是指收藏品,这必须是最后一个 请求URI中的段,或必须遵循功能或 可以绑定到它的动作,否则所有中间段 必须参考单个资源。
请在代码或我用来访问给定方法的URL中帮助我使用您可能拥有的任何输入。谢谢。
我遵循的一些参考可以解决此问题或确保我遵循正确的方向/语法:
Web API和ODATA-传递多个参数
https://damienbod.com/2014/06/13/web-api-and-and-anda-v4-v4-v4-vories-functions-functions-and-attribute-routing-part-part-part-2/
li>
编辑webapiconfig.cs添加一个显式命名空间
builder.Namespace = "MyNamespace";
- 如果您不明确说明,则默认名称空间为"默认":)
编辑Webapiconfig.cs更改函数声明
FunctionConfiguration function = builder.EntityType<DocumentsModel>().Collection.Function("SampleFunction");
function.Parameter<string>("catGUIDOrText");
function.Parameter<string>("type");
function.Parameter<string>("isAutoCompSearch");
function.ReturnsCollectionFromEntitySet<DocumentsModel>("SampleData");
- 使用" .entityType()"您针对实体文档的控制器,您已命名为" SampleData"
- 使用" .Collection",您针对实体的集合;否则,如果您省略,则针对一个实体
更改ODATA控制器
//[ODataRoutePrefix("SampleData")]
public class SampleDataController : ODataController
{
//[ODataRoute("SampleData/MyNamespace.SampleFunction(catGUIDOrText={catGUIDOrText},type={type},isAutoCompSearch={isAutoCompSearch})")]
[EnableQuery]
[HttpGet]
public IHttpActionResult SampleFunction(string catGUIDOrText, string type, string isAutoCompSearch)
{
return new List<DocumentsModel>().AsQueryable<DocumentsModel>();
}
}
- 您可以评论[odatarouteprefix(" sampledata")]:命名约定的路由为 entitySetname 控制器,然后使用" builil.entitysetsetsements
- 返回类型不能是一种可观的;如果您使用ihttpactionResult,您将永远不会遇到问题。
- 如果您使用命名公约,您可以评论Odataroute
更改添加ODATA名称空间的URL
http://localhost/virtualdircorectorynameiniis/odata/sampledata/sampledata/mynamespace.samplefunction(catguidortext ='752',type ='230'
在您的代码中,您声明了一个未结合的函数,但是您像绑定功能一样呼叫
您可以在本教程中找到所需的信息
我正在尝试实现类似的东西,但我直接使用odataqueryOptions,因此我的控制器就是这样:
[HttpGet]
public ODataList<DTO> Get(ODataQueryOptions<POCO> options) {
using (var db = new Entities()) {
var param = Request.RequestUri.ParseQueryString().Get("CompanyCode");
return _oData.Query<POCO, DTO>(options, db.POCO.AsQueryable());
}
}
如果我尝试在签名中添加其他参数,我会遇到错误,因此试图找到一种与所有ODATA参数一起传递公司码的方法,并且仍然具有所有分页/过滤/分类工作。
这对我来说像魅力一样工作 - 我只是在请求中添加额外的参数,例如:
api/dto?compandcode = blah&amp; $ skip = 50&amp; $ top = 50
.net Odata的东西似乎忽略了我的额外参数,并且没有问题 - 我只是手动解析了参数,而不是将其放在函数签名中。对我来说足够好!
我能够通过: -
解决此问题将以下代码添加到startup.cs
public void ConfigureServices(IServiceCollection services) { // your code services.AddMvc(); services.AddOData(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // your code app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.Select().Filter().OrderBy().Expand().Count().MaxTop(50); endpoints.MapODataRoute("api", "api", GetEdmModel()); }); } private IEdmModel GetEdmModel() { var edmBuilder = new ODataConventionModelBuilder(); edmBuilder.EntitySet<Student>("Students"); var pullRequestsByProjectByContributor = edmBuilder.EntityType<Student>().Collection .Function("GetStudents") .ReturnsCollectionFromEntitySet<Student>("Students"); pullRequestsByProjectByContributor.Parameter<int>("id").Required(); pullRequestsByProjectByContributor.Parameter<int>("classId").Required(); return edmBuilder.GetEdmModel(); }
在控制器中
[ODataRouting] [ODataRoutePrefix("students")] public class StudentsController : ODataController { //http://localhost:5112/api/students/GetStudents(id=3,classId=6)?$orderby=id%20desc&$skip=1&$top=2 [HttpGet] [EnableQuery] [ODataRoute("GetStudents(id={id},classId={classId})")] public async Task<IActionResult> GetStudents(int id, int classId, ODataQueryOptions<Student> options) { } }