gpt4 book ai didi

.net - .Net WebApi OData Controller 中的多个 get 方法

转载 作者:行者123 更新时间:2023-12-05 03:41:29 25 4
gpt4 key购买 nike

我想知道是否有可能在同一个 ODataController 中实现两个带参数的不同 get 方法。这就是我想要做的,但它不起作用。我能做什么?

在 ODataController 中:

public class ProductsController : ODataController
{
private readonly ProductsService _service;

public ProductsController()
{
_service = new ProductsService();
}

[EnableQuery]
public IQueryable<Product> Get()
{
return _service.GetAll();
}

[EnableQuery]
public Product Get(int key)
{
return _service.GetById(key);
}

[EnableQuery]
public IQueryable<Product> Get(string key)
{
return _service.GetByFilter(key);
}

在 WebApiConfig.cs 文件中我有下一个配置:

ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.Routes.MapODataServiceRoute("odata", "api/odata", builder.GetEdmModel());

我可以同时使用不带参数的“get”方法和带参数的“get”方法之一,但我不能同时使用这两种带参数的方法。我已经看到了 OdataRoute,但我没有开始工作。我知道我可以通过通用方法使用 OData 过滤器功能,但我想尝试不使用它。还有其他解决方案吗?

谢谢!

最佳答案

OData 路由不支持 overloads OOTB,这实际上是您在此处描述的两种 GET Collection 方法,但您希望其中一种具有与GET Resource 方法。

第一个问题是为什么您要让相同的路由指向两个不同的方法,尤其是当其中一个路由返回单个资源而另一个路由返回一个集合时。 p>

Built-In OData Routing Conventions
The built in conventions will route known URLs to methods that match the expected signatures. All other routes need to be registered with the Edm Model either as discrete Functions or Actions. You could also implement your own routes

The arguments are more or less the same if you had intended the Get(string key) to return a single item or a collection. There is still a clash between a default route and 2 different methods to handle the request for that route. There is a direct duplicate isssue on SO for this type of issue: OData route exception

在 OData 中,我们对资源的 key 进行了区分,它适合默认的 ~/Controller(key) 路由和有效的所有其他路由。对于所有其他非默认路由,我们只需要在 OData EdmModel 中声明它们以使其有效

还有其他可能的解决方案,如 Implementing your own version of the DefaultODataPathHandler as explained herecustom IODataRoutingConvention as explained here .
然而,我发现最好尽可能地尝试并坚持 OData 标准约定,因此当遇到路由问题时,可以在 OData 常规方式 和我们的业务需求之间定义一个简单的映射, AND 你想在全局范围内支持这种语法,那么你可以使用一个简单的 url 重写模块。

  1. 在 Edm 模型中将您的自定义方法端点声明为单独的函数
  2. 创建一个 Url Rewrite 以在旧路由和 OData 路由之间进行映射。

在 Edm 模型中声明自定义函数:

要通过 Edm 模型访问您的自定义函数,我们需要进行两项更改:

  1. 将方法名称更改为不同于 Get 的名称。在此示例中,我们将使用术语 Search

     [HttpGet]
    [EnableQuery]
    public IQueryable<Product> Search(string key)
    {
    return _service.GetByFilter(key);
    }
  2. 修改您的构建器流利表示法:

    ODataModelBuilder builder = new ODataConventionModelBuilder();
    var products = builder.EntitySet<Product>("Products");
    products.EntityType.Collection.Function(nameof(ProductsController.Search))
    .ReturnsCollectionFromEntitySet<Facility>("Products")
    .Parameter<string>("key");
    config.Routes.MapODataServiceRoute("odata", "api/odata", builder.GetEdmModel());

    NOTE: The name of the route must match the name of the method for this configuration to work, to enforce this nameof(ProductsController.Search) was used however, "Search" is all that is necessary.

将匹配此模板的最终 URL:

GET: ~/api/odata/Products/Search(key='Foo')

URL重写模块

public class ODataConventionUrlRewriter : OwinMiddleware
{
/// <summary>
/// Create a Url Rewriter to manipulate incoming OData requests and rewrite or redirect to the correct request syntax
/// </summary>
/// <param name="next"></param>
public ODataConventionUrlRewriter(OwinMiddleware next)
: base(next)
{
}
/// <summary>
/// Process the incoming request, if it matches a known path, rewrite accordingly or redirect.
/// </summary>
/// <param name="context">OWin Request context to process</param>
/// <returns>Chains the next processor if the url is OK or rewritten, otherwise the response is to redirect</returns>
public override async Task Invoke(IOwinContext context)
{
// Match ANY /Controller(NonNumeric)
// Rewrite to /Controller/Search(key='NonNumeric')
var regex = new System.Text.RegularExpressions.Regex(@"\(([^\d=\'\(]+)\)$");
match = regex.Match(context.Request.Path.Value);
if (match != null && match.Success)
{
// We have to use redirect here, we can't affect the query inflight
context.Response.Redirect($"{context.Request.Uri.GetLeftPart(UriPartial.Authority)}{regex.Replace(context.Request.Path.Value, $"/Search(key='{match.Groups[1].Value}')")}");
}
else
await Next.Invoke(context);
}
}

最后,在 StartUp.cs 或配置 OWin 上下文的地方,将此模块添加到管道 之前 OData 配置:

public void Configuration(IAppBuilder app)
{
...
// Rewrite URLs
app.Use(typeof(ODataConventionUrlRewriter));
...
// Register routes
config.MapHttpAttributeRoutes();

ODataModelBuilder builder = new ODataConventionModelBuilder();
var products = builder.EntitySet<Product>("Products");
products.EntityType.Collection.Function(nameof(ProductsController.Search))
.ReturnsCollectionFromEntitySet<Facility>("Products")
.Parameter<string>("key");
config.Routes.MapODataServiceRoute("odata", "api/odata", builder.GetEdmModel());

...
// Start Web API
app.UseWebApi(config);

}

现在我们的自定义函数支持的最终 Url 是这样的:

GET: ~/api/odata/Products(Foo)

Try to use the conventions when you can, you have chosen OData for a reason, if you do use a rewrite module, try to be as specific in your conditional logic as you can be to avoid breaking other standard routes that might be in use.

I try to reserve rewrite solutions for common legacy query routes.

关于.net - .Net WebApi OData Controller 中的多个 get 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67726201/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com