diff --git a/Demos/Demo.AspNetCore.Mvc.OData/Controllers/Api/PersonApiController.cs b/Demos/Demo.AspNetCore.Mvc.OData/Controllers/Api/PersonApiController.cs index 472f2c9..5b95c03 100644 --- a/Demos/Demo.AspNetCore.Mvc.OData/Controllers/Api/PersonApiController.cs +++ b/Demos/Demo.AspNetCore.Mvc.OData/Controllers/Api/PersonApiController.cs @@ -4,7 +4,7 @@ namespace Demo.Extenso.AspNetCore.Mvc.OData.Controllers.Api { - public class PersonApiController : GenericODataController + public class PersonApiController : BaseODataController { public PersonApiController(IRepository repository) : base(repository) diff --git a/Demos/Demo.Data.InfoSchema/Main.cs b/Demos/Demo.Data.InfoSchema/Main.cs index f6bde8d..7a17643 100644 --- a/Demos/Demo.Data.InfoSchema/Main.cs +++ b/Demos/Demo.Data.InfoSchema/Main.cs @@ -80,7 +80,7 @@ private void cmbDatabase_SelectedIndexChanged(object sender, EventArgs e) break; case DataSource.MySql: - lbTables.DataSource = (connection as MySqlConnection).GetTableNames(); + lbTables.DataSource = (connection as MySqlConnection).GetTableNames(includeViews: true); lbTables.Select(); break; @@ -105,7 +105,7 @@ private void cmbSchema_SelectedIndexChanged(object sender, EventArgs e) switch (SelectedDataSource) { case DataSource.SqlServer: lbTables.DataSource = (connection as SqlConnection).GetTableNames(includeViews: true, SelectedSchema); break; - case DataSource.MySql: lbTables.DataSource = (connection as MySqlConnection).GetTableNames(); break; + case DataSource.MySql: lbTables.DataSource = (connection as MySqlConnection).GetTableNames(includeViews: true); break; case DataSource.PostgreSql: lbTables.DataSource = (connection as NpgsqlConnection).GetTableNames(includeViews: true, SelectedSchema); break; default: break; } diff --git a/Demos/Demo.Extenso.AspNetCore.Blazor.OData/Controllers/Api/PersonApiController.cs b/Demos/Demo.Extenso.AspNetCore.Blazor.OData/Controllers/Api/PersonApiController.cs index a0836cf..cde6985 100644 --- a/Demos/Demo.Extenso.AspNetCore.Blazor.OData/Controllers/Api/PersonApiController.cs +++ b/Demos/Demo.Extenso.AspNetCore.Blazor.OData/Controllers/Api/PersonApiController.cs @@ -4,7 +4,7 @@ namespace Demo.Extenso.AspNetCore.Blazor.OData.Controllers.Api { - public class PersonApiController : GenericODataController + public class PersonApiController : BaseODataController { public PersonApiController(IRepository repository) : base(repository) diff --git a/Extenso.AspNetCore.OData/Extenso.AspNetCore.OData.csproj b/Extenso.AspNetCore.OData/Extenso.AspNetCore.OData.csproj index 36e4d19..4f00276 100644 --- a/Extenso.AspNetCore.OData/Extenso.AspNetCore.OData.csproj +++ b/Extenso.AspNetCore.OData/Extenso.AspNetCore.OData.csproj @@ -6,7 +6,7 @@ en-US https://raw.githubusercontent.com/gordon-matt/Extenso/master/LICENSE.txt https://github.com/gordon-matt/Extenso - 6.0.1 + 6.0.2 diff --git a/Extenso.AspNetCore.OData/GenericODataController.cs b/Extenso.AspNetCore.OData/GenericODataController.cs index fe89f19..7add038 100644 --- a/Extenso.AspNetCore.OData/GenericODataController.cs +++ b/Extenso.AspNetCore.OData/GenericODataController.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.OData.Deltas; using Microsoft.AspNetCore.OData.Formatter; using Microsoft.AspNetCore.OData.Query; +using Microsoft.AspNetCore.OData.Results; using Microsoft.AspNetCore.OData.Routing.Controllers; using Microsoft.EntityFrameworkCore; @@ -17,6 +18,7 @@ namespace Extenso.AspNetCore.OData /// /// /// + [Obsolete("Use BaseODataController instead")] public abstract class GenericODataController : ODataController, IDisposable where TEntity : class { @@ -90,7 +92,7 @@ public virtual async Task Get(ODataQueryOptions options) // NOTE: Change due to: https://github.com/OData/WebApi/issues/1235 var connection = GetDisposableConnection(); var query = connection.Query(); - query = ApplyMandatoryFilter(query); + query = await ApplyMandatoryFilterAsync(query); var results = options.ApplyTo(query, IgnoreQueryOptions); return Ok(results); } @@ -303,10 +305,10 @@ protected virtual bool EntityExists(TKey key) /// /// The System.Linq.IQueryable`1 upon which to apply the filter. /// A System.Linq.IQueryable`1 that may have had filters applied. - protected virtual IQueryable ApplyMandatoryFilter(IQueryable query) + protected virtual async Task> ApplyMandatoryFilterAsync(IQueryable query) { // Do nothing, by default - return query; + return await Task.FromResult(query); } /// @@ -421,4 +423,41 @@ public void Dispose() #endregion IDisposable Support } + + /// + /// A generic, abstract CRUD controller for OData, with support for checking policy based permissions for users. + /// Get(TKey) in BaseODataController allows for OData query options, such as $expand, whereas GenericODataController does not + /// + /// + /// + public abstract class BaseODataController : GenericODataController + where TEntity : BaseEntity + { + protected BaseODataController(IRepository repository) + : base(repository) + { + } + + [EnableQuery] + public override async Task Get([FromODataUri] TKey key) + { + var connection = GetDisposableConnection(); + var query = connection.Query(x => x.Id.Equals(key)); + query = await ApplyMandatoryFilterAsync(query); + var result = SingleResult.Create(query); + + var entity = result.Queryable.FirstOrDefault(); + if (entity == null) + { + return NotFound(); + } + + if (!await CanViewEntity(entity)) + { + return Unauthorized(); + } + + return Ok(result); + } + } } \ No newline at end of file