我已经从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方法验证用户,然后调用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);
}
该函数如下所示(最初来自此处,但具有更新的引用:https://github.com/OData/ODataSamples/blob/master/RESTier/Trippin/Trippin/Helpers.cs)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Routing;
using Microsoft.AspNet.OData.Extensions;
using Microsoft.AspNet.OData.Routing;
using Microsoft.OData.UriParser;
namespace Project1.Extensions
{
public class Helpers
{
public static TKey GetKeyFromUri<TKey>(HttpRequestMessage request, Uri uri)
{
if (uri == null)
{
throw new ArgumentNullException("uri");
}
var urlHelper = request.GetUrlHelper() ?? new UrlHelper(request);
var pathHandler = (IODataPathHandler)request.GetRequestContainer().GetService(typeof(IODataPathHandler));
string serviceRoot = urlHelper.CreateODataLink(
request.ODataProperties().RouteName,
pathHandler, new List<ODataPathSegment>());
var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());
var keySegment = odataPath.Segments.OfType<KeySegment>().FirstOrDefault();
if (keySegment == null)
{
throw new InvalidOperationException("The link does not contain a key.");
}
var value = keySegment.Keys.FirstOrDefault().Value;
return (TKey)value;
}
}
}
此行代码现在抛出以下错误:找不到段'odata‘的资源
var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());
这在使用OData 6.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);
}
发布于 2020-05-20 04:06:57
我知道我来晚了一点,但我在升级到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;
}
事实证明,IODataPathHandler.Parse(...)可以接受绝对URI并根据serviceRoot解析它。
另一个关键区别是KeySegment.Keys已经有了键值的映射,其中的值已经被解析-它只需要转换即可。
作为参考,我使用的是Microsoft.AspNet.OData 7.4.0
希望这能有所帮助!
发布于 2018-12-21 01:11:54
我把routePrefix
从null
改成了odata
,就像你做的那样,这也给自己造成了同样的问题。只要您不需要路由前缀(例如/odata/
),将routePrefix
设置为null
将允许您的代码完全正常工作。
https://stackoverflow.com/questions/53241904
复制相似问题