5

I am trying to get a list of entries from database. But I am getting an error.

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<models.DbModels.GrantProgram>' to 'Microsoft.AspNetCore.Mvc.ActionResult<System.Collections.Generic.IEnumerable<models.DbModels.GrantProgram>>' [API]

Please help me. How can I solve this?

Controller.cs

public async Task<ActionResult<IEnumerable<GrantProgram>>> GetGrants()
{
  //This is where the error is showing. 
  return await _grants.GetGrants(); 
}

Business layer

IGrants.cs

Task<IEnumerable<GrantProgram>> GetGrants(); 

Grants.cs

public async Task<IEnumerable<GrantProgram>> GetGrants()
{
    return await _grantRepository.GetGrants(); 
}

Data access layer

IGrantsRepository.cs

Task<IEnumerable<GrantProgram>> GetGrants(); 

GrantsRepository.cs

public async Task<IEnumerable<GrantProgram>> GetGrants()
{
    return await _context.GrantProgram.ToListAsync();
}
Soleil
  • 6,404
  • 5
  • 41
  • 61
StarLord
  • 707
  • 1
  • 8
  • 21
  • @The General Yes, I know that. I wanted to learn three-layer architecture. How can I solve this problem in this scenario? – StarLord Dec 18 '20 at 05:16
  • https://github.com/aspnet/Mvc/issues/7981 – mjwills Dec 18 '20 at 05:21
  • 1
    I suspect the code you want is something like `return new ActionResult>(await _grants.GetGrants());` – mjwills Dec 18 '20 at 05:27
  • @mjwills Thank you so much! My question was closed by someone telling it's a duplicate. But the answer to the question mentioned didn't solve my problem. But your solution worked! – StarLord Dec 18 '20 at 05:42

3 Answers3

6

I suspect the code you want is something like

return new ActionResult<IEnumerable<GrantProgram>>(await _grants.GetGrants());

Why does your existing code not work? Because (as per the docs):

C# doesn't support implicit cast operators on interfaces.

It suggests:

Consequently, conversion of the interface to a concrete type is necessary to use ActionResult.

which is not strictly speaking true. It is an option, yes (e.g. call ToList), but it isn't necessary. Another option (as I show) is to new up ActionResult yourself rather than rely on the implicit conversion).

Other reading:

mjwills
  • 23,389
  • 6
  • 40
  • 63
  • 1
    With C# 9.0 [Target-typed new expressions](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/target-typed-new), your answer can now be simplified to `return new(await _grants.GetGrants());`. – Marc Sigrist Dec 21 '21 at 15:21
3

since you are using ActionResult consider to use this

public async Task<ActionResult<IEnumerable<GrantProgram>>> GetGrants()
{
 
  return Ok ( await _grants.GetGrants() ); 
}
Serge
  • 40,935
  • 4
  • 18
  • 45
0

According to the Docs (Controller action return types in ASP.NET Core web API, published in February 2022), consider only using ActionResult as the return type if your method could return different ActionResults. Since this example only has one return path, you could instead use simpler code that defines a specific type as the return value. Here is what your code would look like with this change:

Controller.cs

public async Task<IEnumerable<GrantProgram>> GetGrants()
{
  //This is where the error is showing. 
  return await _grants.GetGrants(); 
}
Steve Nyholm
  • 806
  • 9
  • 9