Get() { re" /> Get() { re" /> Get() { re"/>

.Net Core API - oData Prefix is lost when passing arguments

355 Views Asked by At

This call works correctly and is mapped to /oData/Projects.

[HttpGet(Name = "GetProjects")]
    [EnableQuery]
    public IEnumerable<ProjectEntity> Get()
    {
        return _db.Projects;
    }

How can I make pass an argument with out losing the oData prefix in the URL?

This loses the oData Prefix:

[HttpGet("{id}", Name = "GetProjectById")]
    [EnableQuery]
    public ProjectEntity GetProjectById(int id)
    {
        return _db.Projects.Where(p => p.Id == id).FirstOrDefault();
    }

I am using .net core web api and oData 8.0

Here is the full controller:

[ApiController]
[Route("[controller]")]
public class ProjectsController : ControllerBase
{       
    private readonly ILogger<ProjectsController> _logger;
    private readonly ApplicationDbContext _db;

    public ProjectsController(ILogger<ProjectsController> logger, ApplicationDbContext db)
    {
        _logger = logger;
       _db = db;
    }

    [HttpGet("{id}", Name = "GetProjectById")]
    [EnableQuery]
    public ProjectEntity GetProjectById(int id)
    {
        return _db.Projects.Where(p => p.Id == id).FirstOrDefault();
    }

    [HttpGet(Name = "GetProjects")]
    [EnableQuery]
    public IEnumerable<ProjectEntity> Get()
    {
        return _db.Projects;
    }
}
1

There are 1 best solutions below

4
Md Farid Uddin Kiron On

To enable OData attribute routing to work, either in controller or action should decorate an attribute named ODataRoutingAttribute. It’s renamed as ODataAttributeRoutingAttribute in 8.0. since as you are using asp.net core controller so your controller action should be like below:

Model:

public class ProjectInfo
    {
        public int Id { get; set; }
        public string ApiVersion { get; set; }
        public string Name { get; set; }
        public string PhoneNumber { get; set; }
    }

Controller:

public class ProjectsController : ControllerBase
    {
        private ProjectInfo[] project= new ProjectInfo[]
        {
            new ProjectInfo
            {
                Id = 1,
                ApiVersion = "v1.0",
                Name = "Kiron",
                PhoneNumber = "111-222-3333"
            },
            new ProjectInfo
            {
                Id = 2,
                ApiVersion = "v1.0",
                Name = "Farid",
                PhoneNumber = "456-ABC-8888"
            }
        };

        [EnableQuery]
        [HttpGet("odata/Projects")]
        public IActionResult Get()
        {
            return Ok(project);
        }

        [ODataAttributeRoutingAttribute]
        [HttpGet("odata/Projects/{key}")]
        public IActionResult Get(int key)
        {
            var project = project.FirstOrDefault(c => c.Id == key);
            if (project == null)
            {
                return NotFound($"Cannot find project with Id={key}.");
            }

            return Ok(project);
        }
    }

Note: You can also set [ODataAttributeRoutingAttribute] on global controller so that you don't need to set on each action. in that case just get rid of [ApiController] and [Route("[controller]")]

Reference Required:

using Microsoft.AspNetCore.OData.Routing.Attributes;

Startup.cs:

 services.AddControllers().AddOData(opt => opt.Select());

Output:

enter image description here

Note: As you are using oData 8.0 you have to use ODataAttributeRoutingAttribute annotations either on your controller or action as you can see the above code and screenshot. It will resolve your problem.

In addition you could have a look more details on our official blog document here also here is the sample project