Web Api OData v4 FromODataUri 总是返回 404 Not Found
Web Api OData v4 FromODataUri always returning 404 Not Found
我正在尝试调用从 uri 接收参数的 Web api odata 控制器方法,如下所示:
// GET /odata/People(3)
public SingleResult<Person> Get([FromODataUri] int key)
{
return SingleResult.Create(DemoDataSources.Instance.People.Where(p => p.ID == key.ToString()).AsQueryable());
}
上面的方法没有被 url http://localhost:port/odata/People(3) 总是返回 404 Not Found。
我已经使用以下文件从头开始配置了一个新的 Asp.Net OData Web 应用程序:
PeopleController.cs
[EnableQuery]
public class PeopleController : ODataController
{
// GET /odata/People
public IHttpActionResult Get()
{
return Ok(DemoDataSources.Instance.People.AsQueryable());
}
// GET /odata/People(3)
public SingleResult<Person> Get([FromODataUri] int key)
{
return SingleResult.Create(DemoDataSources.Instance.People.Where(p => p.ID == key.ToString()).AsQueryable());
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.MapODataServiceRoute("odata", "odata", GetEdmModel(), new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
config.EnsureInitialized();
}
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "Demos";
builder.ContainerName = "DefaultContainer";
builder.EntitySet<Person>("People");
builder.EntitySet<Trip>("Trips");
var edmModel = builder.GetEdmModel();
return edmModel;
}
}
DemoDataSources.cs
public class DemoDataSources
{
private static DemoDataSources instance = null;
public static DemoDataSources Instance
{
get
{
if (instance == null)
{
instance = new DemoDataSources();
}
return instance;
}
}
public List<Person> People { get; set; }
public List<Trip> Trips { get; set; }
private DemoDataSources()
{
this.Reset();
this.Initialize();
}
public void Reset()
{
this.People = new List<Person>();
this.Trips = new List<Trip>();
}
public void Initialize()
{
this.Trips.AddRange(new List<Trip>()
{
new Trip()
{
ID = "0",
Name = "Trip 0"
},
new Trip()
{
ID = "1",
Name = "Trip 1"
},
new Trip()
{
ID = "2",
Name = "Trip 2"
},
new Trip()
{
ID = "3",
Name = "Trip 3"
}
});
this.People.AddRange(new List<Person>
{
new Person()
{
ID = "001",
Name = "Angel",
Trips = new List<Trip>{Trips[0], Trips[1]}
},
new Person()
{
ID = "002",
Name = "Clyde",
Description = "Contrary to popular belief, Lorem Ipsum is not simply random text.",
Trips = new List<Trip>{Trips[2], Trips[3]}
},
new Person()
{
ID = "003",
Name = "Elaine",
Description = "It has roots in a piece of classical Latin literature from 45 BC, making Lorems over 2000 years old."
}
});
}
}
Person.cs
public class Person
{
[Key]
public String ID { get; set; }
[Required]
public String Name { get; set; }
public String Description { get; set; }
public List<Trip> Trips { get; set; }
}
Trip.cs
public class Trip
{
[Key]
public String ID { get; set; }
[Required]
public String Name { get; set; }
}
我 "think" 这个问题与 odata 路由有关,但我不知道为什么这种基本行为无法正常工作...
感谢任何帮助!
马科斯
由于 Person
class 的键 属性 的 string
类型,您需要对路由中的 ID 使用单引号:http://localhost:port/odata/People('3')
如果您按照 Andriy 的建议传递字符串值,您可能还需要更改 get 的签名。
所以改变:
public SingleResult Get([FromODataUri] int key)
收件人:
public SingleResult Get([FromODataUri] 字符串键)
然后我认为您可以按照 Andriy 的建议调用 OData 服务。
我正在尝试调用从 uri 接收参数的 Web api odata 控制器方法,如下所示:
// GET /odata/People(3)
public SingleResult<Person> Get([FromODataUri] int key)
{
return SingleResult.Create(DemoDataSources.Instance.People.Where(p => p.ID == key.ToString()).AsQueryable());
}
上面的方法没有被 url http://localhost:port/odata/People(3) 总是返回 404 Not Found。
我已经使用以下文件从头开始配置了一个新的 Asp.Net OData Web 应用程序:
PeopleController.cs
[EnableQuery]
public class PeopleController : ODataController
{
// GET /odata/People
public IHttpActionResult Get()
{
return Ok(DemoDataSources.Instance.People.AsQueryable());
}
// GET /odata/People(3)
public SingleResult<Person> Get([FromODataUri] int key)
{
return SingleResult.Create(DemoDataSources.Instance.People.Where(p => p.ID == key.ToString()).AsQueryable());
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.MapODataServiceRoute("odata", "odata", GetEdmModel(), new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
config.EnsureInitialized();
}
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "Demos";
builder.ContainerName = "DefaultContainer";
builder.EntitySet<Person>("People");
builder.EntitySet<Trip>("Trips");
var edmModel = builder.GetEdmModel();
return edmModel;
}
}
DemoDataSources.cs
public class DemoDataSources
{
private static DemoDataSources instance = null;
public static DemoDataSources Instance
{
get
{
if (instance == null)
{
instance = new DemoDataSources();
}
return instance;
}
}
public List<Person> People { get; set; }
public List<Trip> Trips { get; set; }
private DemoDataSources()
{
this.Reset();
this.Initialize();
}
public void Reset()
{
this.People = new List<Person>();
this.Trips = new List<Trip>();
}
public void Initialize()
{
this.Trips.AddRange(new List<Trip>()
{
new Trip()
{
ID = "0",
Name = "Trip 0"
},
new Trip()
{
ID = "1",
Name = "Trip 1"
},
new Trip()
{
ID = "2",
Name = "Trip 2"
},
new Trip()
{
ID = "3",
Name = "Trip 3"
}
});
this.People.AddRange(new List<Person>
{
new Person()
{
ID = "001",
Name = "Angel",
Trips = new List<Trip>{Trips[0], Trips[1]}
},
new Person()
{
ID = "002",
Name = "Clyde",
Description = "Contrary to popular belief, Lorem Ipsum is not simply random text.",
Trips = new List<Trip>{Trips[2], Trips[3]}
},
new Person()
{
ID = "003",
Name = "Elaine",
Description = "It has roots in a piece of classical Latin literature from 45 BC, making Lorems over 2000 years old."
}
});
}
}
Person.cs
public class Person
{
[Key]
public String ID { get; set; }
[Required]
public String Name { get; set; }
public String Description { get; set; }
public List<Trip> Trips { get; set; }
}
Trip.cs
public class Trip
{
[Key]
public String ID { get; set; }
[Required]
public String Name { get; set; }
}
我 "think" 这个问题与 odata 路由有关,但我不知道为什么这种基本行为无法正常工作...
感谢任何帮助! 马科斯
由于 Person
class 的键 属性 的 string
类型,您需要对路由中的 ID 使用单引号:http://localhost:port/odata/People('3')
如果您按照 Andriy 的建议传递字符串值,您可能还需要更改 get 的签名。
所以改变: public SingleResult Get([FromODataUri] int key)
收件人: public SingleResult Get([FromODataUri] 字符串键)
然后我认为您可以按照 Andriy 的建议调用 OData 服务。