Search code examples
asp.net-coreodata

Does OData actually work in AspNetCore on Linux?


I work in an environment where all new work is done in AspNetCore, one of the primary reasons being so we can run it on Linux servers. We have an API to access one of our databases that I've been asked to add OData to. No problem.

The Problem

I've got a lovely example working in a test project and I'm moving it over to the real API in a branch of the code annnnnnd.....what's that? It's a reference to Microsoft.AspNet.

My test project is .NetCore 2.1, and the only NuGet packages installed are:

  • Microsoft.AspNetCore.App v2.1.1
  • Microsoft.AspNetCore.OData v7.0.1 (tried v7.1.0 too)
  • Microsoft.AspNetCore.Razor.Design v2.1.2
  • Microsoft.NETCore.App v2.1.0

This (truncated) code works great on my Windows development machine, but I foresee problems when we try to build it for Linux deployment.

Startup.cs - Notice the first 2 usings

using Microsoft.AspNet.OData.Builder;
using Microsoft.AspNet.OData.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.OData.Edm;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ODataTest.Models;

namespace ODataTest
{
    public class Startup
    {
        ...
        public void ConfigureServices(IServiceCollection services)
        {
            ...
            services.AddOData();
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ...
            app.UseMvc(b =>
            {
                b.Filter().Expand();
                b.MapODataServiceRoute("odata", "odata", GetEdmModel());
                b.EnableDependencyInjection();
            });
        }

        private static IEdmModel GetEdmModel()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<ThingDto>(nameof(ThingDto));
            return builder.GetEdmModel();
        }
    }
}

ThingController.cs - Notice using #3

using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.OData;
using Microsoft.AspNetCore.Mvc;
using ODataTest.Models;

namespace ODataTest.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ODataController
    {
        private readonly Db _db;
        public ValuesController(Db db)
        {
            this._db = db;
        }

        [HttpGet]
        [EnableQuery]
        public ActionResult<IEnumerable<ProductPricePointMarkdownDto>> Index()
        {
            var things =
                from thing in _db.Things
                select new ThingDto
                {
                    ThingID = thing.ID,
                    StyleID = thing.StyleID,
                    ColourID = thing.ColourID
                };

            return Ok(things);
        }
    }
}

ThingDto.cs - Notice the last using

using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNet.OData.Query;

namespace ODataTest.Models
{
    [Filter("ColourID", Disabled = true)]
    [Filter]
    public class ThingDto
    {
        [Key]
        public int ThingID { get; set; }
        public int StyleID { get; set; }
        public int ColourID { get; set; }
    }
}

Can anyone steer me away from my current thinking that OData "works with Core" is marketing, and in reality it doesn't?


Solution

  • So the answer is "Yes, it does work". I have not tracked down whether it's a bad namespace, or actually referring to .NET Standard. The motivation to find out went once I proved this ran on a Linux docker container.