问题
Note: This is not a duplicate since I'm using a completely new implementation version of OData in AspNetCore
.
Based on this confusing article by Microsoft, I'm trying to use AttributeRoutingConvetion
and ultimately using ODataRoutePrefix
and ODataRoute
to route OData requests using Asp.net Core 5 Web API and Microsoft.AspNetCore.OData Version="8.0.0-preview3"
(please pay attention to version).
Here is my code :
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.TryAddEnumerable(ServiceDescriptor.Transient<IODataControllerActionConvention, AttributeRoutingConvention>());
services.AddOData(
opt => opt.AddModel("odata",GetEdmModel()).Select().Count().Filter().OrderBy().SetAttributeRouting(true)
);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
public IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<WeatherForecast>("WeatherForecast2");
return builder.GetEdmModel();
}
and here is my controller :
[ODataRoutePrefix("WFC")]
public class WeatherForecast2Controller : ODataController
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecast2Controller> _logger;
public WeatherForecast2Controller(ILogger<WeatherForecast2Controller> logger)
{
_logger = logger;
}
[HttpGet]
[EnableQuery]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
[HttpGet]
[EnableQuery]
[ODataRoute("AnotherGet")]
public IEnumerable<WeatherForecast> AnotherGet()
{
var rng = new Random();
return Enumerable.Range(1, 3).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
Now what I expect is calling the https://localhost:44346/WFC/AnotherGet return the 3 Weatherforcast result by executing AnotherGet method but I get a 404 error. I have also tried the followings:
~/odata/WeatherForecast2 - executes Get and returns array of 5 Weatherforcast
~/odata/WFC/ - 404 not found
~/odata/WFC/AnotherGet - 404 not found
~/WFC/ - 404 not found
~/WFC/AnotherGet - 404 not found
How can I execute a specific controller and its method ?
回答1:
@nAvid
Thanks for trying ASP.NET Core OData 8.0.
First, in the blog, I mentioned:
1. ODataRoutePrefixAttribute is an attribute that can, and only can be placed on an OData controller to specify the prefix that will be used for all actions of that controller.
2. ODataRouteAttribute is an attribute that can, and only can be placed on an action of an OData controller to specify the OData URLs that the action handles.
Second, the path route template defined in the attribute should follow up OData convention spec. That is, the concatenated string from 'ODataRoutePrefixAttribute' and 'ODataRouteAttribute' should pass the OData uri parser.
As an example:
[ODataRoutePrefix("WFC")]
public class WeatherForecast2Controller : ODataController
{
...
[ODataRoute("AnotherGet")]
public IEnumerable<WeatherForecast> AnotherGet()
{
}
}
The concatenated string for action 'AnotherGet' is "WFC/AnotherGet'.
From OData convention URI, WFC/AnotherGet
should be a valid OData URI (template).
BUT, the Edm model (you built in GetEdmModel) doesn't have anything related "WFC" or "AnotherGet".
So, It's expected that you will get the following response:
- ~/odata/WFC/ - 404 not found
- ~/odata/WFC/AnotherGet - 404 not found
- ~/WFC/ - 404 not found
- ~/WFC/AnotherGet - 404 not found
For
- '~/odata/WeatherForecast2 - executes Get and returns array of 5 Weatherforcast ',
that's not OData attribute routing, however it works because it's OData convention routing.
The convention routing looks the "EntitySetName" + Controller for the controller.
So, public class WeatherForecast2Controller
meets that convention.
and public IEnumerable<WeatherForecast> Get()
meets the query entity set convention routing. So, it works.
来源:https://stackoverflow.com/questions/65551331/using-odatarouteprefix-and-odataroute-for-odata-attributerouting-is-not-working