I have two OData Controllers:
PersonsController
PersonsUnrestrictedController
The only way in which they will differ is that a couple of properties has to get their values from different columns in the persons table depending on the controller.
The PersonsController will send back a list of Persons where the persons givenname, familyname etc are alias names whereas PersonsUnrestrictedController will send back a list of Persons with the persons real names. All other properties will be exactly the same, including navigation properties and their relationships with other tables.
It is extremely important that PersonsController under no circumstances reveals a persons real name.
Is it possible to dynamically switch between:
[Column("AltGivenName")]
public string GivenName { get; set; }
and
[Column("GivenName")]
public string GivenName { get; set; }
depending on controller?
Or alternatively have two properties GivenName and AltGivenName and dynamically hide/reveal 1 of them depending on controller:
[DataMember(Name="GivenName")] //Either should this one be ignored
public string AltGivenName { get; set; }
public string GivenName { get; set; } //or this one, depending on controller
Or are there any other possible workarounds?
Edit: Added my code
Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<PersonContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("MyConnection")); });
services.AddOData();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapODataRoute("odata", "odata", GetEdmModel());
endpoints.Select().Expand().MaxTop(null).Count();
});
}
private static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
var persons = builder.EntitySet<Person>("Persons");
return builder.GetEdmModel();
}
}
PersonContext.cs
public class PersonContext : DbContext
{
public DbSet<DbPerson> Persons { get; set; }
public PersonContext(DbContextOptions<PersonContext> options) : base(options)
{
}
}
DbPerson.cs
[Table("Person")]
public class DbPerson
{
[Key]
public int Id { get; set; }
public string GivenName { get; set; }
public string AltGivenName { get; set; }
}
Person.cs
public class Person
{
[Key]
public int Id { get; set; }
public string GivenName { get; set; }
}
MappingHelper.cs
public static class MappingHelper
{
public static Person ToPerson(this DbPerson dbPerson)
{
return new Person
{
Id = dbPerson.Id,
GivenName = dbPerson.GivenName,
};
}
public static Person ToAnonymousPerson(this DbPerson dbPerson)
{
return new Person
{
Id = dbPerson.Id,
GivenName = dbPerson.AltGivenName,
};
}
}
PersonsController.cs
public class PersonsController : ODataController
{
private readonly PersonContext _context;
public PersonsController(PersonContext context)
{
_context = context;
}
[EnableQuery]
public IActionResult Get()
{
return new ObjectResult(_context.Persons.Select(MappingHelper.ToPerson));
}
}
Running the following query takes 5-10 seconds http://localhost:4871/odata/persons?$top=10
If I instead change:
return new ObjectResult(_context.Persons.Select(MappingHelper.ToPerson));
to
return new ObjectResult(_context.Persons);
and change
var persons = builder.EntitySet<Person>("Persons");
to
var persons = builder.EntitySet<DbPerson>("Persons");
the same query takes 50-100 ms
There are about 150k persons in the person table.