Я обновил Microsoft.AspNet.OData версии 6.0.0 до OData версии 7.0.1. Обновление сломало мою способность получать Id из пути при связывании одного объекта с другим. Вот мой вызов Web API для добавления роли конкретному пользователю с использованием стандарта OData:
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. Кажется, у меня какая-то проблема с анализом моего сегмента данных или невозможностью его найти вообще. Вот мои настройки маршрутизации, если это поможет:
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);
}