OData InvalidOperationException.Неверный запрос - ошибка в синтаксисе запроса - PullRequest
1 голос
/ 26 марта 2019

Работа с ASP.NET Core и OData v4

Я получаю

InvalidOperationException: шаблон пути 'Классы ({key}) / Bookings ({bookingKey}) "по действию" GetBooking "в Контроллер 'Классы' не является допустимым шаблоном пути OData. Неверный запрос - Ошибка в синтаксисе запроса.

Я не вижу ошибки в синтаксисе запроса. Вот полный код этого метода в моем контроллере «Классы»

    /// <summary>
    /// Get a specific booking
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [ODataRoute("Classes({key})/Bookings({bookingKey})")]
    public async Task<IActionResult> GetBooking([FromODataUri] Guid key, [FromODataUri] Guid bookingKey)
    {
        var @class = await _context.Classes.FirstOrDefaultAsync(y => y.Id == key);

        if (@class == null)
        {
            return NotFound();
        }

        var booking = _context.Bookings.Where(y => y.Class.Id == key && y.Id == bookingKey);

        if (!booking.Any())
        {
            return NotFound();
        }

        return Ok(SingleResult.Create(booking));
    }

Этот метод определен в контроллере «Классы». У меня также есть метод GeBookings и 2 метода действий, которые не вызывают проблем. Когда я комментирую свой метод GetBooking (), у меня нет ошибок.

Бронирование - это [Содержится] ICollection of Booking

public class Class
{
    [Key]
    public Guid Id { get; set; }

    // Others properties

    [Contained]
    public ICollection<Booking> Bookings {get; set;}
}

Я действительно вижу свою ошибку. Стоит ли искать?

РЕДАКТИРОВАТЬ Больше информации

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
    <edmx:DataServices>
        <Schema Namespace="Oyg" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityType Name="Owner">
                <Key>
                    <PropertyRef Name="Id" />
                </Key>
                <Property Name="Id" Type="Edm.Guid" Nullable="false" />
                <Property Name="Name" Type="Edm.String" />
                <Property Name="Email" Type="Edm.String" />
                <Property Name="PhoneNumber" Type="Edm.String" />
                <Property Name="Hash" Type="Edm.String" />
                <Property Name="ConfigurationString" Type="Edm.String" />
                <NavigationProperty Name="Teachers" Type="Collection(Oyg.Teacher)" ContainsTarget="true" />
                <NavigationProperty Name="Locations" Type="Collection(Oyg.Location)" ContainsTarget="true" />
                <NavigationProperty Name="Classes" Type="Collection(Oyg.Class)" ContainsTarget="true" />
            </EntityType>
            <EntityType Name="Student">
                <Key>
                    <PropertyRef Name="Id" />
                </Key>
                <Property Name="Id" Type="Edm.Guid" Nullable="false" />
                <Property Name="Name" Type="Edm.String" />
                <Property Name="Email" Type="Edm.String" />
                <Property Name="PhoneNumber" Type="Edm.String" />
                <Property Name="Hash" Type="Edm.String" />
                <Property Name="ConfigurationString" Type="Edm.String" />
            </EntityType>
            <EntityType Name="Class">
                <Key>
                    <PropertyRef Name="Id" />
                </Key>
                <Property Name="Id" Type="Edm.Guid" Nullable="false" />
                <Property Name="Title" Type="Edm.String" />
                <Property Name="Description" Type="Edm.String" />
                <Property Name="StartTime" Type="Edm.DateTimeOffset" Nullable="false" />
                <Property Name="EndTime" Type="Edm.DateTimeOffset" Nullable="false" />
                <Property Name="Status" Type="Oyg.ScheduleStatus" Nullable="false" />
                <Property Name="Positions" Type="Edm.Int32" Nullable="false" />
                <Property Name="Bookings" Type="Collection(Oyg.Booking)" />
                <NavigationProperty Name="Owner" Type="Oyg.Owner" />
                <NavigationProperty Name="Teacher" Type="Oyg.Teacher" />
                <NavigationProperty Name="Location" Type="Oyg.Location" />
            </EntityType>
            <ComplexType Name="Booking">
                <Property Name="Id" Type="Edm.Guid" Nullable="false" />
                <Property Name="Position" Type="Edm.Int32" Nullable="false" />
                <Property Name="ReservationTime" Type="Edm.DateTimeOffset" Nullable="false" />
                <Property Name="CancelTime" Type="Edm.DateTimeOffset" />
                <NavigationProperty Name="Class" Type="Oyg.Class" Nullable="false" />
                <NavigationProperty Name="Student" Type="Oyg.Student" Nullable="false" />
            </ComplexType>
            <EntityType Name="Teacher">
                <Key>
                    <PropertyRef Name="Id" />
                </Key>
                <Property Name="Id" Type="Edm.Guid" Nullable="false" />
                <Property Name="Name" Type="Edm.String" />
                <Property Name="Description" Type="Edm.String" />
                <Property Name="Email" Type="Edm.String" />
                <Property Name="PhoneNumber" Type="Edm.String" />
                <Property Name="Website" Type="Edm.String" />
                <NavigationProperty Name="Owner" Type="Oyg.Owner" />
            </EntityType>
            <EntityType Name="Location">
                <Key>
                    <PropertyRef Name="Id" />
                </Key>
                <Property Name="Id" Type="Edm.Guid" Nullable="false" />
                <Property Name="Title" Type="Edm.String" />
                <Property Name="Description" Type="Edm.String" />
                <Property Name="Geolocalisation" Type="Edm.String" />
                <Property Name="Address" Type="Edm.String" />
                <Property Name="Facilities" Type="Edm.String" />
                <NavigationProperty Name="Owner" Type="Oyg.Owner" />
            </EntityType>
            <EnumType Name="ScheduleStatus">
                <Member Name="Draft" Value="0" />
                <Member Name="Published" Value="1" />
                <Member Name="Cancelled" Value="2" />
            </EnumType>
            <EntityContainer Name="OygContainer">
                <EntitySet Name="Owners" EntityType="Oyg.Owner" />
                <EntitySet Name="Students" EntityType="Oyg.Student" />
                <EntitySet Name="Classes" EntityType="Oyg.Class">
                    <NavigationPropertyBinding Path="Bookings/Class" Target="Classes" />
                    <NavigationPropertyBinding Path="Bookings/Student" Target="Students" />
                    <NavigationPropertyBinding Path="Owner" Target="Owners" />
                </EntitySet>
            </EntityContainer>
        </Schema>
        <Schema Namespace="Oyg.Actions" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <Action Name="Register" IsBound="true">
                <Parameter Name="bindingParameter" Type="Oyg.Class" />
                <Parameter Name="studentId" Type="Edm.Guid" Nullable="false" />
                <ReturnType Type="Oyg.Booking" />
            </Action>
            <Action Name="CancelRegistration" IsBound="true">
                <Parameter Name="bindingParameter" Type="Oyg.Class" />
                <Parameter Name="studentId" Type="Edm.Guid" Nullable="false" />
            </Action>
        </Schema>
    </edmx:DataServices>
</edmx:Edmx>

Похоже, что моя ICollection of Booking не рассматривается как отдельное свойство навигации, действительно, как коллекция

{
    "@odata.context": "https://localhost:44375/odata/$metadata#Classes",
    "value": [
        {
            "Id": "dde8de4d-89ca-4ba3-cff7-08d6aac63c0f",
            "Title": "xxx",
            "Description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
            "StartTime": "2019-02-24T18:00:00+08:00",
            "EndTime": "2019-02-24T19:00:00+08:00",
            "Status": "Draft",
            "Positions": 22,
            "Bookings": []
        }
    ]
}

1 Ответ

0 голосов
/ 09 апреля 2019

Ответ от xuzhg https://github.com/OData/WebApi/issues/1789

Заказы настроены как «Структурное свойство», и их тип сложный тип. Сложный тип является структурным типом без ключа, поэтому шаблон вашего пути "Классы ({id}) / Бронирования ({bookingId})" не может работать.

Основной причиной является вызов «registerAction.Returns ()», эта строка будет настроить тип «Бронирование» как сложный тип. Я думаю, если вы позвоните "registerAction.ReturnsFromEntitySet (" Bookings ")" может разрешить проблема. Спасибо

...