I'm trying to create a form where a user can input their information. They click submit and on the next page, it list their information. I created to two pages. One view page (Book.cshtml) the template was create. On the other view page (Review.cshtml) the template was list. Both of their model class was taken from the Form.cs model. My problem is that when i click submit it gives me this error, "System.NullReferenceException: 'Object reference not set to an instance of an object.'." I'm guessing this is because there's no information stored in the Form.cs model from the Book.cshtml. How do I store the information the user inputs on the Book page, and display on the Review page. I tried to use [HttpGet] and [HttpPost], but nothing happened from that. I'm using visual studio asp.net core MVC 3.1
HomeController
using Hotel_Lodge.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Hotel_Lodge.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
[HttpGet]
public IActionResult Book()
{
return View();
}
[HttpPost]
public IActionResult Book(Form form)
{
return View();
}
public IActionResult Review()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
Form.cs model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Hotel_Lodge.Models
{
public class Form
{
public string Name { get; set; }
public string Arrival { get; set; }
public string Departure { get; set; }
public string RoomType { get; set; }
public string Misc { get; set; }
}
}
Book.cshtml (View)
@model Hotel_Lodge.Models.Form
@{
ViewData["Title"] = "Book";
}
<h1>Book</h1>
<h4>Form</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Book">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Arrival" class="control-label"></label>
<input asp-for="Arrival" class="form-control" />
<span asp-validation-for="Arrival" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Departure" class="control-label"></label>
<input asp-for="Departure" class="form-control" />
<span asp-validation-for="Departure" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="RoomType" class="control-label"></label>
<input asp-for="RoomType" class="form-control" />
<span asp-validation-for="RoomType" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Misc" class="control-label"></label>
<input asp-for="Misc" class="form-control" />
<span asp-validation-for="Misc" class="text-danger"></span>
</div>
<div>
<a type="submit" class="btn btn-dark" href="https://localhost:44348/Home/Review">Next</a>
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Review.cshtml (view)
@model IEnumerable<Hotel_Lodge.Models.Form>
@{
ViewData["Title"] = "Review";
}
<h1>Review</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Arrival)
</th>
<th>
@Html.DisplayNameFor(model => model.Departure)
</th>
<th>
@Html.DisplayNameFor(model => model.RoomType)
</th>
<th>
@Html.DisplayNameFor(model => model.Misc)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Arrival)
</td>
<td>
@Html.DisplayFor(modelItem => item.Departure)
</td>
<td>
@Html.DisplayFor(modelItem => item.RoomType)
</td>
<td>
@Html.DisplayFor(modelItem => item.Misc)
</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>
CodePudding user response:
you don't create any model in your actions, this is why you have an null reference error. For example Review should be like this
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly DbContext _context
public HomeController(
ILogger<HomeController> logger,
DbContext context
)
{
_logger = logger;
_context=context
}
public IActionResult Review()
{
var model= _context.Set<FormModel>().ToList();
return View(model);
}
CodePudding user response:
I would suggest you to use a submit button instead of href
(see ASP.NET MVC Form Submit with Link instead of Button).
Replace the following line in the Book.cshtml
<a type="submit" class="btn btn-dark" href="https://localhost:44348/Home/Review">Next</a>
by
<button type="submit" class="btn btn-primary">Next</button>
So, click on the Next will pass the Form
object to the Book(Form form)
.
And update the Book(Form form)
method to:
[HttpPost]
public IActionResult Book(Form form)
{
if (!ModelState.IsValid)
{
return RedirectToAction("Index", form);
}
// You should add the current a new record to a repository here
// and pass an updated list to the `Review`.
// Currently only a new `form` record is passed to the `Review` for demo purpose.
return View("Review", new List<Form> { form });
}