C#OData GetKeyFromUri-未找到段';奥达塔';
我已将Microsoft.AspNet.OData版本6.0.0更新为OData版本7.0.1。升级破坏了我在将一个对象链接到另一个对象时从路径获取Id的能力。以下是使用OData标准向特定用户添加角色的Web API调用:C#OData GetKeyFromUri-未找到段';奥达塔';,odata,Odata,我已将Microsoft.AspNet.OData版本6.0.0更新为OData版本7.0.1。升级破坏了我在将一个对象链接到另一个对象时从路径获取Id的能力。以下是使用OData标准向特定用户添加角色的Web API调用: POST: http://localhost:61506/odata/users('bob')/roles/$ref Request body: {"@odata.id":"http://localhost:61506/odata/roles(1)"} Web API方法
POST: http://localhost:61506/odata/users('bob')/roles/$ref
Request body: {"@odata.id":"http://localhost:61506/odata/roles(1)"}
Web API方法验证用户,然后调用Helpers.GetKeyFromUri从请求主体获取角色Id值
[HttpPost, HttpPut]
public IHttpActionResult CreateRef([FromODataUri] string key, string navigationProperty, [FromBody] Uri link)
{
// Ensure the User exists
User user = new User().GetById(key);
if (user == null)
{
return NotFound();
}
// Determine which navigation property to use
switch (navigationProperty)
{
case "roles":
// Get the Role id
int roleId;
try
{
roleId = Helpers.GetKeyFromUri<int>(Request, link);
}
catch (Exception ex)
{
return BadRequest();
}
// Ensure the Role exists
Role role = new Role().GetById(roleId);
if (role == null)
{
return NotFound();
}
// Add the User/Role relationship
user.Roles.Add(role);
user.Update();
break;
default:
return StatusCode(HttpStatusCode.NotImplemented);
}
return StatusCode(HttpStatusCode.NoContent);
}
这在使用OData6.0.0时运行良好,但在7.0.1中失败。解析我的odata段或根本找不到它似乎有点问题。以下是我的路由设置(如果有帮助):
public static void Register(HttpConfiguration config)
{
// Setup the OData routes and endpoints
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: "odata",
model: GetEdmModel());
// Enable OData URL querying globally
config.Count().Filter().Select().OrderBy().Expand().MaxTop(null);
}
我将
routePrefix
从null
更改为odata
也造成了同样的问题,就像您所做的那样。只要不需要路由前缀(如/odata/
),将routePrefix
设置为null
将允许代码正常工作 我知道我来晚了一点,但我在升级到Microsoft.AspNet.OData 7.x时遇到了同样的问题。经过一点调试和修补,我发现这段代码对我来说很有用——而不必删除routePrefix:
public static TKey GetKeyFromUri<TKey>(HttpRequestMessage request, Uri uri)
{
if (uri == null)
{
throw new ArgumentNullException(nameof(uri));
}
var urlHelper = request.GetUrlHelper() ?? new UrlHelper(request);
string serviceRoot = urlHelper.CreateODataLink(
request.ODataProperties().RouteName,
request.GetPathHandler(),
new List<ODataPathSegment>());
var odataPath = request.GetPathHandler().Parse(
serviceRoot,
uri.AbsoluteUri,
request.GetRequestContainer());
var keySegment = odataPath.Segments.OfType<KeySegment>().FirstOrDefault();
if (keySegment == null)
{
throw new InvalidOperationException("The link does not contain a key.");
}
return (TKey)keySegment.Keys.FirstOrDefault().Value;
}
公共静态TKey GetKeyFromUri(HttpRequestMessage请求,Uri)
{
if(uri==null)
{
抛出新ArgumentNullException(nameof(uri));
}
var urlHelper=request.GetUrlHelper()??新的urlHelper(请求);
字符串serviceRoot=urlHelper.CreateODataLink(
request.ODataProperties().RouteName,
request.GetPathHandler(),
新列表());
var odataPath=request.GetPathHandler().Parse(
serviceRoot,
uri.AbsoluteUri,
GetRequestContainer());
var keySegment=odataPath.Segments.OfType().FirstOrDefault();
if(keySegment==null)
{
抛出新的InvalidOperationException(“链接不包含密钥”);
}
返回(TKey)keySegment.Keys.FirstOrDefault()值;
}
事实证明,它可以获取一个绝对URI并根据serviceRoot解析它
另一个关键区别是KeySegment.Keys已经有了键值的映射,其中的值已经被解析了——只需要对其进行强制转换
作为参考,我使用的是7.4.0
希望这有帮助
public static void Register(HttpConfiguration config)
{
// Setup the OData routes and endpoints
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: "odata",
model: GetEdmModel());
// Enable OData URL querying globally
config.Count().Filter().Select().OrderBy().Expand().MaxTop(null);
}
public static TKey GetKeyFromUri<TKey>(HttpRequestMessage request, Uri uri)
{
if (uri == null)
{
throw new ArgumentNullException(nameof(uri));
}
var urlHelper = request.GetUrlHelper() ?? new UrlHelper(request);
string serviceRoot = urlHelper.CreateODataLink(
request.ODataProperties().RouteName,
request.GetPathHandler(),
new List<ODataPathSegment>());
var odataPath = request.GetPathHandler().Parse(
serviceRoot,
uri.AbsoluteUri,
request.GetRequestContainer());
var keySegment = odataPath.Segments.OfType<KeySegment>().FirstOrDefault();
if (keySegment == null)
{
throw new InvalidOperationException("The link does not contain a key.");
}
return (TKey)keySegment.Keys.FirstOrDefault().Value;
}