C# 中的 Odata 自定义操作给出找不到页面

问题描述 投票:0回答:1

我是 odata 新手,正在尝试按照教程进行操作

https://learn.microsoft.com/en-us/odata/webapi-8/fundamentals/routing-overview?tabs=net60

我正在尝试创建一个可访问的操作 http://localhost:5207/odata/Customers/Get12345

但它给出“找不到本地主机页面”

enter image description here

我遇到的一个选项是添加

  1. [Route("odata/Customers/Get12345")] 在操作之上,但我不希望这样,因为我觉得如果“odata”发生变化,我将不得不进行多次更改,并感觉可能有更好的选择。

  2. 我遇到的另一个选择是使用 Action,但我无法使其工作,因为我完全不理解它。有人可以帮忙吗?

var customersType = modelBuilder.EntitySet<Customer>("Customers").EntityType;
customersType.Collection.Action("Get12345")
    .ReturnsFromEntitySet<Customer>("Customers");

// 程序.cs

// Program.cs
using Lab01.Models;
using Microsoft.AspNetCore.OData;
using Microsoft.OData.ModelBuilder;
using Microsoft.VisualBasic;

var builder = WebApplication.CreateBuilder(args);

var modelBuilder = new ODataConventionModelBuilder(); 
modelBuilder.EntityType<Order>(); 
modelBuilder.EntitySet<Customer>("Customers");
// It means if you have an entity set named Customers based on Customer entity type
// Odata type returned here returns the data in the form of Customer entity type as is named as "Customers" in the odata context
// It indicates that this payload comes from Customer entity set

var customersType = modelBuilder.EntitySet<Customer>("Customers").EntityType;
customersType.Collection.Action("Get12345")
    .ReturnsFromEntitySet<Customer>("Customers");

builder.Services.AddControllers().AddOData(
    options => options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(null).AddRouteComponents("odata", modelBuilder.GetEdmModel()));

var app = builder.Build();

app.UseRouting();

app.UseEndpoints(endpoints => endpoints.MapControllers());
// Customers is being defined as the name of the entity set
// so seeing if changing the controller to Customer gives the data - No it does not give the data

app.Run();

CustomersController.cs

using Lab01.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;
using Microsoft.AspNetCore.OData.Routing.Controllers;

namespace Lab01.Controllers
{
    public class CustomersController : ODataController
    {
        private static Random random = new Random();
        private static List<Customer> customers = new List<Customer>(
            Enumerable.Range(1, 3).Select(idx => new Customer
            {
                Id = idx,
                Name = $"Customer {idx}",
                Orders = new List<Order>(
                    Enumerable.Range(1, 2).Select(dx => new Order
                    {
                        Id = (idx - 1) * 2 + dx,
                        Amount = random.Next(1, 9) * 10
                    }))
            }));

        [EnableQuery]
        public ActionResult<IEnumerable<Customer>> Get()
        {
            return Ok(customers);
        }

        [EnableQuery]
        public ActionResult<string> Get([FromRoute] int key)
        {
            var item = customers.SingleOrDefault(d => d.Id.Equals(key));

            if (item == null)
            {
                return NotFound();
            }

            return Ok("abcd");
        }

        // Create an action to be accessible at the odata endpoint for Get1234567


        // For this the endpoint localhost:5207/Customers
        // /Get12345 is working - But it is not Odata compatible as odata is not coming in response
        // The endpoint this is not working - "http://localhost:5207/odata/Customers/Get12345"
        [EnableQuery]
        public ActionResult<Customer> Get12345()
        {
            var item = customers.SingleOrDefault(d => d.Id.Equals(1));

            if (item == null)
            {
                return NotFound();
            }

            return Ok(item);
        }

        [EnableQuery]
        [Route("odata/Customers/Get1234567")]
        public ActionResult<Customer> Get1234567()
        {
            return new Customer();
        }
    }
}

客户.cs

namespace Lab01.Models
{
    using System.Collections.Generic;

    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<Order> Orders { get; set; }
    }
}

订单.cs

namespace Lab01.Models
{
    using System.Collections.Generic;

    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<Order> Orders { get; set; }
    }
}
c# odata asp.net-web-api-routing
1个回答
0
投票

问题在于操作仅支持

HttpPost
请求。要解决此问题,您需要使用
[HttpPost]
属性标记您的方法。

Microsoft 文档 中描述的操作如下

操作是一种添加不易定义的服务器端逻辑的方法 作为对实体的 CRUD(创建、读取、更新和删除)操作。一个 动作可能会产生副作用,这就是为什么它们是用 HTTP POST 方法。操作可以针对单个实体或集合 的实体。在 OData 术语中,这是具有约束力的。您还可以拥有 “未绑定”操作,基本上是 OData 上的静态操作 服务。

[EnableQuery]
[HttpPost]
public ActionResult<Customer> Get12345()
{
    ...
}

此外,请注意,在浏览器中输入 URL 将导致

HttpGet
请求。

© www.soinside.com 2019 - 2024. All rights reserved.