Search code examples
c#asp.net-coreodataaspnetboilerplate

OData with ABP only returns 404 for entities


I'm developing a .NET Core 2.2 web app, using ABP and OData, and I've followed this guide. After setting everything up, I can query http://localhost:21021/odata and get the following result:

{"result":{"entitySets":[{"url":"Empresas","name":"Empresas","title":null,"typeAnnotation":null},{"url":"Users","name":"Users","title":null,"typeAnnotation":null}],"singletons":[],"functionImports":[],"typeAnnotation":null},"targetUrl":null,"success":true,"error":null,"unAuthorizedRequest":false,"__abp":true}

But anything I try with my entities, like hitting http://localhost:21021/odata/Empresas, just results in a 404.

What could be the problem?

Startup.cs

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // MVC
        services.AddMvc(
            options => options.Filters.Add(new CorsAuthorizationFilterFactory(_defaultCorsPolicyName))
        );

        services.AddOData();

        // Workaround: https://github.com/OData/WebApi/issues/1177
        services.AddMvcCore(options =>
        {
            foreach (var outputFormatter in options.OutputFormatters.OfType<ODataOutputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0))
            {
                outputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata"));
            }
            foreach (var inputFormatter in options.InputFormatters.OfType<ODataInputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0))
            {
                inputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata"));
            }
        });

        IdentityRegistrar.Register(services);
        AuthConfigurer.Configure(services, _appConfiguration);
        // ... SignalR, CORS, Swagger, etc ...

        return services.AddAbp<EcfWebHostModule>(
            // Configure Log4Net logging
            options => options.IocManager.IocContainer.AddFacility<LoggingFacility>(
                f => f.UseAbpLog4Net().WithConfig("log4net.config")
            )
        );

    public void Configure(IApplicationBuilder app)
    {
        app.UseAbp(options => { options.UseAbpRequestLocalization = false; }); // Initializes ABP framework.

        // ... UseCors, UseStaticFiles, UseAuthentication, UseAbpRequestLocalization, UseSignalR ...

        app.UseOData(builder =>
        {
            builder.EntitySet<EmpresaEntity>("Empresas").EntityType.Expand().Filter().OrderBy().Page();
            builder.EntitySet<User>("Users").EntityType.Expand().Filter().OrderBy().Page();
        });

        app.UseUnitOfWork(options =>
        {
            options.Filter = httpContext =>
            {
                return httpContext.Request.Path.Value.StartsWith("/odata");
            };
        });

        // ... Swagger ...

        app.UseMvc(routes =>
        {
            routes.MapODataServiceRoute(app);

            routes.MapRoute(
                name: "defaultWithArea",
                template: "{area}/{controller=Home}/{action=Index}/{id?}");

            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

EmpresaController.cs

public class EmpresaController : AbpODataEntityController<EmpresaEntity>, ITransientDependency
{
    public EmpresaController(IRepository<EmpresaEntity> repository)
        : base(repository)
    {

    }
}

EmpresaEntity.cs

public sealed class EmpresaEntity : FullAuditedEntity
{
    public string Cnpj { get; set; }
    public string Nome { get; set; }
}

Solution

  • Finally solved it.

    Just had to change the name of the controller to match the string passed as parameter in the startup class. It wasn't clear from the documentation that was how it worked.

    builder.EntitySet<EmpresaEntity>("Empresas").EntityType.Expand().Filter().OrderBy().Page();
    

    and

    EmpresasController