question

MJ-8053 avatar image
0 Votes"
MJ-8053 asked AgaveJoe edited

problem with API

I have the following in my ApiController
public IEnumerable<Game> GetAllGames()
{
Game game = new Game();
List<Game> Games = game.ListGames();
return Games;
}


I have also tried
public IHttpActionResult GetAllGames()
{
Game game = new Game();
List<Game> Games = game.ListGames();
return Ok(Games);
}

When i run in postman i get the following
{
"GameId": null,
"GameName": null,
"RecommendedAges": null,
"Synopsis": null,
"Link": null,
"Playtime": null,
"CheckedOut": false,
"MinPlayers": 0,
"MaxPlayers": 0,
"MinPlaytime": 0,
"SearchType": 0,
"Num": 0,
"Genre": null,
"GenreName": null,
"Email": null,
"DateCheckedOut": "0001-01-01T00:00:00",
"RowId": null,
"GamePhoto": [],
"GameGenre": []
}

I know the method ListGames works because it works on the mvc page

What am I doing wrong?

dotnet-aspnet-webapi
· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

You did not share any of the relevant code but the results look like an empty Game type.

Is there anyway you can share the Game class and ListGames() method? Also, have you tried simply running the code through the Visual Studio debugger? Maybe a problem with a try...catch block?

0 Votes 0 ·

222514-game-class.txt

As I mentioned this method works on the MVC side. Here is a link Games It uses the Game class and the ListGames() method to display this page.

I use the API to deliver to our local group site that does not have a database. The only thing I use on the API is get method in various classes. (Events, Games, Speakers) We do all of the crud operations on my site as that is password protected and I don't have to worry about people messing with stuff. .


0 Votes 0 ·
game-class.txt (2.2 KiB)

Hi @MJ-8053,
Is there any error message?
I recommend you to check the database connection and confirm that the database has values.
Best regards,
Lan Huang

0 Votes 0 ·
Show more comments

As I mentioned this method works on the MVC side.

That may be the case but you must understand the community does not have your code or database.

The response is an empty Game type not a List<Game>. Are you sure the results are from invoking the GetAllGames() action? Perhaps the client code is calling a different Web API action. Have you verified? Can you provide the client code that calls the the action?

Have you tried running the code through the Visual Studio debugger?


0 Votes 0 ·
Show more comments
AgaveJoe avatar image
0 Votes"
AgaveJoe answered AgaveJoe edited

I'm not sure if you read my last post. I think the problem is you do not understand REST (Web API) fundamentals.

If you are using the default Web API template in Visual Studio then "getallgames" in the URL below is a route parameter NOT an action name.

 http://dataconnective.com/api/games/getallgames

Web API does not use action names in the URL. Take a look at the App_Start\WebApiConfig.cs.

 config.Routes.MapHttpRoute(
     name: "DefaultApi",
     routeTemplate: "api/{controller}/{id}",
     defaults: new { id = RouteParameter.Optional }

As you can see there's no action in the route template.

To prove this fact let's look at your sample application. You can enter either of the two URLs below yet the same result is returned.

http://dataconnective.com/api/games/getallgames
http://dataconnective.com/api/games/blah

The reason your break point is not hit is because the getallgames action is NOT being hit. The action that is invoked is the one with a route parameter.

Look at the following example.

 public class GameController : ApiController
 {
     public IHttpActionResult GetAllGames()
     {
         Game game = new Game();
         List<Game> Games = game.ListGames();
         return Ok(Games);
     }
    
     public IHttpActionResult Getbyid(string id)
     {
         return Ok(id);
     }
 }

If I enter https://localhost:44310/api/game/getallgames in the browser, the result is "getallgames" which is the "id" route parameter found in the Getbyid(string id) action.

 <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">getallgames</string>


The Getbyid(string id) is invoked not GetAllGames(). This is a fundamental building block in REST and this type of information is openly covered in every Web API getting started tutorial.

FYI, when I enter http://dataconnective.com/api/games in the browser's address bar, your API returns an 500 Internal Server Error.

 <Error>
 <Message>An error has occurred.</Message>
 </Error>
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you!!!

I must not be looking at the same tutorials as you are because not a single one explained at as you just did.

The ones i saw basically say just do this and don't explain how it works.

I have it working now

0 Votes 0 ·

I must not be looking at the same tutorials as you are because not a single one explained at as you just did.

Get Started with ASP.NET Web API 2 (C#)

For the GetProduct method, the id in the URI is a placeholder. For example, to get the product with ID of 5, the URI is api/products/5.

Routing in ASP.NET Web API

To determine which action to invoke, the framework uses a routing table. The Visual Studio project template for Web API creates a default route:

 routes.MapHttpRoute(
     name: "API Default",
     routeTemplate: "api/{controller}/{id}",
     defaults: new { id = RouteParameter.Optional }
 );




0 Votes 0 ·
AgaveJoe avatar image
0 Votes"
AgaveJoe answered AgaveJoe edited

Joe, I included the class and method as an attachment in my previous response

The JSON results in your first post do not match the Game model or a collection. Therefore, I can only assume the JSON results you've posted are not coming from GetAllGames() or you did not share the correct JSON results. Also, the Game model properties do not exactly match the result set from the stored procedure!?

I crafted a test using your Game class and Web API action. The JSON has the following format. Notice the properties that do not have a procedure result are null or a default value.

 [
     {
         "GameId": "1",
         "GameName": "Game 1",
         "RecommendedAges": "18",
         "Synopsis": "Synopsis 1",
         "Link": "Link 1",
         "Playtime": "Playtime",
         "CheckedOut": false,
         "MinPlayers": 1,
         "MaxPlayers": 4,
         "MinPlaytime": 3,
         "SearchType": 0,
         "Num": 0,
         "Genre": null,
         "GenreName": null,
         "Email": null,
         "DateCheckedOut": "0001-01-01T00:00:00",
         "RowId": null
     },
     {
         "GameId": "2",
         "GameName": "Game 2",
         "RecommendedAges": "14",
         "Synopsis": "Synopsis 1",
         "Link": "Link 2",
         "Playtime": "Playtime",
         "CheckedOut": false,
         "MinPlayers": 2,
         "MaxPlayers": 3,
         "MinPlaytime": 4,
         "SearchType": 0,
         "Num": 0,
         "Genre": null,
         "GenreName": null,
         "Email": null,
         "DateCheckedOut": "0001-01-01T00:00:00",
         "RowId": null
     }
 ]

Please troubleshoot your code!



· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

No the class has more properties in it. It has a property for every column in the table. This sproc does not pull all columns.

When I run the code in debugger, it does not hit the breakpoints and shows
false0001-01-01T00:00:0000000

how do I get it to hit a breakpoint?

0 Votes 0 ·

When I run the code in debugger...how do I get it to hit a breakpoint?

Make sure the configuration manager is set to debug. Click the run button. Then use your browser to access the Web API URL.

As I've mentioned several times now, the Game class's properties DO NOT match the JSON sample you shared in your first post. If the project is configured for debug mode but the break point is not hit, it's probably because you are hitting a different Web API action.

222797-capture.png

No the class has more properties in it. It has a property for every column in the table. This sproc does not pull all columns.

I'm not a fan of the design. The view model is inside the same class as data access. The view model should be in the MVC project's model folder or in a separate class library. The data access should exist in a separate class library or namespace as well. This design will be a nightmare to maintain.





0 Votes 0 ·
capture.png (33.7 KiB)

I have altered the class and moved properties into some other classes. I have attached the new class.

Why do you say having the properties and methods in one file makes for a nightmare to maintain? I put them that way so that I would know where to find them instantly. The classes reside in the models directory on the MVC side. I am self taught so if that is a bad practice please let me know what I should do instead. I am willing to listen and learn.

I have it set to Debug Any CPU I click on the start debugging button when it opens the site I change the URL to be
localhost:44392/API/Games/GetAllGames

and this xml is returned
<Game><CheckedOut>false</CheckedOut><GameGenre/><GameId i:nil="true"/><GameName i:nil="true"/><GamePhoto/><Link i:nil="true"/><MaxPlayers>0</MaxPlayers><MinPlayers>0</MinPlayers><MinPlaytime>0</MinPlaytime><Playtime i:nil="true"/><RecommendedAges i:nil="true"/><Synopsis i:nil="true"/></Game>

I don't understand why it won't hit the breakpoints.

This is the only part that is not working all of the other APIs work.

My thought now is to create a separate project for the API and have that one use Entity and Linq, which I don't use on the MVC side. I could then have it in a subdomain off of my site or even in a different folder if needed

223346-new-class.txt


[1]: http://dataconnective.com/API/Games/GetAllGames

0 Votes 0 ·
new-class.txt (2.4 KiB)
Show more comments
LanHuang-MSFT avatar image
0 Votes"
LanHuang-MSFT answered MJ-8053 commented

Hi @MJ-8053,
I wrote an example based on the code you provided. You can refer to it.

I don't understand why it won't hit the breakpoints.

Where did you hit the breakpoint?I suggest you still check the database.

  public class GameController : ApiController
     {
         // GET: Game
         public IHttpActionResult GetAllGames()
         {
               
             Game game = new Game();
             List<Game> list = game.ListGames();
                
             return Ok(list);
         }
     }


 public class Game
     {
         public string GameId { get; set; }
         [Required, Display(Name = "Game Name"), StringLength(200)]
         public string GameName { get; set; }
         [Required, Display(Name = "Recommended Age"), StringLength(25)]
         public string RecommendedAges { get; set; }
    
         [StringLength(100)]
         public string Link { get; set; }
    
    
    
         public List<Game> ListGames()
         {
             using (SqlConnection oConn = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
             {
                 using (SqlCommand oCmd = new SqlCommand())
                 {
                     try
                     {
                         oCmd.CommandText = "ListGames";
                         oCmd.CommandType = CommandType.StoredProcedure;
                         oCmd.Connection = oConn;
                         oConn.Open();
                         using (SqlDataReader reader = oCmd.ExecuteReader())
                         {
                             List<Game> myList = new List<Game>();
                             while (reader.Read())
                             {
                                 Game game = new Game
                                 {
                                     GameId = reader[0].ToString(),
                                     GameName = reader[1].ToString(),
                                     RecommendedAges = reader[2].ToString(),
                                     Link = reader[3].ToString(),
                                 };
                                 myList.Add(game);
                             }
                             return myList;
                         }
                     }
                     catch (Exception ex)
                     {
    
                         return null;
                     }
                     finally
                     {
                         oCmd.Dispose();
                         oConn.Close();
                     }
                 }
             }
         }
     }

223600-image.png
223694-image.png
Best regards,
Lan Huang


If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



image.png (14.1 KiB)
image.png (39.2 KiB)
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

The database works. I have mentioned multiple times that is not the issue.

If you don't take my word for it click this link then click on the Games link in the navbar. this calls the same method of the class as the api does.

Then there is a link in the page which shows the code for that controller and it also shows it never hitting a breakpoint.

you can see that it does work on MVC side but not for API the other APIs work, but not this single one. And It NEVER hits the breakpoint. I am stumped!


0 Votes 0 ·