I am trying to add views for a project I completed online.
When I load the default web-page, my Index action in the Home controller loads up. When I navigate to /home, my Index action in the Home controller loads up. However, when I navigate to /home/index, an error pops up.
This is my default route in my startup class:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });
})
And this is my Index method in my home controller:
public class HomeController : Controller
{
private readonly IMovieRankService _movieRankService;
public HomeController(IMovieRankService movieRankService)
{
_movieRankService = movieRankService;
}
[HttpGet]
public async Task<ActionResult> Index()
{
var other = await _movieRankService.GetAllItemsFromDatabase();
return View(other);
}
My index view:
@using Movie_Rank.Contracts;
@model IEnumerable<MovieResponse>
@{
ViewData["Title"] = "movies";
}
<h2>movies</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.MovieName)
</th>
<th>
@Html.DisplayNameFor(model => model.Description)
</th>
<th>
@Html.DisplayNameFor(model => model.Ranking)
</th>
<th>
@Html.DisplayNameFor(model => model.TimeRanked)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.MovieName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Description)
</td>
<td>
@Html.DisplayFor(modelItem => item.Ranking)
</td>
<td>
@Html.DisplayFor(modelItem => item.TimeRanked)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</tbody>
</table>
When I run the program, my table of movies loads up fine. When I put /home into the url, my table of movies loads up fine. But when I put in /home/index, it gives this error:
NullReferenceException: Object reference not set to an instance of an object.
MovieRank.Libs.Mappers.Mapper.ToMovieContract(MovieDb movie) in Mapper.cs
-
18. }
19.
20. public MovieResponse ToMovieContract(MovieDb movie)
21. {
22. // Returns new MovieResponse which maps proprties of MovieDb (using DynamoDB table attributes
23. // For example, MovieName (from MovieResponse class) = movie.MovieName (from MovieDb)
**24.** return new MovieResponse
25. {
26. MovieName = movie.MovieName,
27. Description = movie.Description,
28. Actors = movie.Actors,
29. Ranking = movie.Ranking,
30. TimeRanked = movie.RankedDateTime
MovieRank.Services.MovieRankService.GetMovie(int userId, string movieName) in MovieRankService.cs
-
31.
32. // Get a movie from MovieDb in MovieRankRepository and map to MovieResponse
33. public async Task<MovieResponse> GetMovie(int userId, string movieName)
34. {
35. var response = await _movieRankRepository.GetMovie(userId, movieName);
36. // Uses MovieRankRepository response
**37.** return _map.ToMovieContract(response);
38. }
39.
40. // Get movies from MovieDb in MovieRankRepository and map to MovieResponse
41. public async Task<IEnumerable<MovieResponse>> GetUsersRankedMoviesByMovieTitle(int userId, string movieName)
42. {
43. var response = await _movieRankRepository.GetUsersRankedMoviesByMovieTitle(userId, movieName);
MovieRank.Controllers.HomeController.GetMovie(int userId, string movieName) in HomeController.cs
-
25. }
26.
27. [HttpGet]
28. [Route("{userId}/{movieName}")]
29. public async Task<ActionResult> GetMovie(int userId, string movieName)
30. {
**31.** var result = await _movieRankService.GetMovie(userId, movieName);
32.
33. return View(result);
34. }
35.
36. [HttpGet]
37. [Route("user/{userId}/rankedMovies/{movieName}")]
So we know that when you use /Home/Index
, it's using this action:
public async Task<ActionResult> GetMovie(int userId, string movieName)
That has to do with the route you gave it:
[Route("{userId}/{movieName}")]
Because the route, at this point, doesn't know the type that userId
should be, it's matching userId = "Home"
and movieName = "Index"
. Then when the values are mapped, the value types don't match, and I assume you're probably getting 0
for userId
in the method itself.
Try adding a constraint in the route, to make sure the route is only selected if userId
is an int
:
[Route("{userId:int}/{movieName}")]