I have a Search Form which goes to my Search() action method within my Home Controller. and returns View("Index")
Search() method:
public IActionResult Search(SearchQuery FormData)
{
List<Flight> flights = new List<Flight>();
flights = (from flight in _context.Flights
where flight.FlightDateTime.Date == FormData.PreferredFlightTime.Date
&& flight.ArrivalAirportId == FormData.ArrivalAirportId
&& flight.DepartureAirportId == FormData.DepartureAirportId
select flight).ToList();
ViewBag.FlightSearchResults = flights;
return View("Index");
}
Upon the initial load of the homepage it works fine when loading my Index() method and returning the view.
public IActionResult Index()
{
HomeViewModel mymodel = new HomeViewModel();
mymodel.Airports = GetAirports();
return View(mymodel);
}
However once the search form is submitted and the Search() action method is called, when the method returns return View("Index"); the page will not load due System.NullReferenceException: 'Object reference not set to an instance of an object.'
The above exception is thrown when it reaches #foreach (Airport airport in Model.Airports)
Search form:
#using FlightBooker;
#model FlightBooker.Models.HomeViewModel;
<form asp-controller="Home" asp-action="Search" method="post">
<div class="form-group">
<label for="fromAirport">Flying from:</label>
<select name=" {DepartureAirportId" class="form-control">
#foreach (Airport airport in Model.Airports)
{
<option value="#airport.AirportId">#airport.AirportCode</option>
}
</select>
<div class="form-group">
<label for="toAirport">Flying to:</label>
<select name="ArrivalAirportId" class="form-control">
#foreach (Airport airport in Model.Airports)
{
<option value="#airport.AirportId">#airport.AirportCode</option>
}
</select>
</div>
<label for="fromAirport">Departure Date:</label>
<br />
<input type="date" / id="date" name="PreferredFlightTime">
<br />
<label for="fromAirport">No. passengers:</label>
<select class="form-control" name="TotalPassengers">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
<button type="submit" class="btn btn-primary mt-3">Search Flights</button>
</div>
</form>
Comment from Codecaster above solved this. I updated my Search() action method passing the model to the Index view and repeating the code in my index method.
Updated Search() action method:
public IActionResult Search(SearchQuery FormData)
{
List<Flight> flights = new List<Flight>();
flights = (from flight in _context.Flights
where flight.FlightDateTime.Date == FormData.PreferredFlightTime.Date
&& flight.ArrivalAirportId == FormData.ArrivalAirportId
&& flight.DepartureAirportId == FormData.DepartureAirportId
select flight).ToList();
ViewBag.FlightSearchResults = flights;
HomeViewModel mymodel = new HomeViewModel();
mymodel.Airports = GetAirports();
return View("Index", mymodel);
}
Related
I create my dropdown based on values from an enum, then try to return the value by using the th:value="${parameterName}" like for other fields, but the return value is null.
Controller get method:
#GetMapping("/createorupdatebusvehicle/{id}")
public String createBusVehicleDisplay(Model model, #PathVariable(value = "id") long id, HttpServletResponse response) throws IOException {
BusVehicle busVehicle = busVehicleRepository.findById(id).get();
if(busVehicle == null){
response.sendRedirect("/createorupdatebusvehicle");
return null;
}
model.addAttribute("busVehicleId", id);
model.addAttribute("busVehicleColor", busVehicle.getColor().toString());
model.addAttribute("busVehicleType", busVehicle.getType().toString());
// all attributes are set
return "createOrUpdateBusVehicle";
}
Page view:
<form action="#" th:action="#{/createorupdatebusvehicle}" method="post">
<input type="hidden" name="busVehicleId" th:value="${busVehicleId}" />
<p>Plate number: <input type="text" name="busVehiclePlateNumber" th:value="${busVehiclePlateNumber}" /></p>
<p>Passenger capacity: <input type="text" name="busVehiclePassengerCapacity" th:value="${busVehiclePassengerCapacity}" /></p>
//== Here are the selects ==
<select name="color">
<option th:each="colorOpt : ${T(com.grazzini.model.BusVehicleColor).values()}"
th:value="${busVehicleColor}" th:text="${colorOpt}" th:selected="${busVehicleColor} == colorOpt"></option>
</select>
<select name="type">
<option th:each="typeOpt : ${T(com.grazzini.model.BusVehicleType).values()}"
th:value="${busVehicleType}" th:text="${typeOpt}" th:selected="${busVehicleType} == typeOpt"></option>
</select>
Then get the selected value back in the controller:
#PostMapping("/createorupdatebusvehicle")
public String checkAndCreateBusVehicle (HttpServletRequest request, HttpServletResponse response) throws IOException {
String busVehicleId = request.getParameter("busVehicleId");
//...
String busVehicleColor = request.getParameter("busVehicleColor"); //null
String busVehicleType = request.getParameter("busVehicleType"); //null
/// the rest
Color and Type are enums. All other requests return the correct value, for a text field for example. Any idea why this one behave differently?
You have name="..." on the fields that are working. You need to add name="busVehicleColor" and name="busVehicleType" on your respective <select /> tags..
This is my index view. I tried with ViewBag but it doesn't work, maybe because I want to get values from foreign key. I am new to ASP.NET.
<form id="forma" action="/InspekcijskeKontrole/VratiKontrole" method="get">
<div class="form-group">
<label for="Select1">Odaberite inspekcijsko tijelo:</label>
<select name="Select1" id="Select1" class="form-control" onchange="sacuvaj()">
<option value="-1">Selektujte inspekcijsko tijelo:</option>
#foreach (var i in ViewBag.Select1) {
<option value="#i.Value">#i.Text</option>
}
</select><br />
<label for="Select2">Odaberite vremenski period kontrole:</label>
<select name="Select2" id="Select2" class="form-control" onchange="sacuvaj1()">
<option value="-1">Selektujte vremenski period kontrole:</option>
#foreach(var i in Model)
{
<option value="#i.DatumInspekcijskeKontrole.ToString("dd.MM.yyyy")">#i.DatumInspekcijskeKontrole.ToString("dd.MM.yyyy")</option>
}
</select>
</div>
This is my controller
public ActionResult VratiKontrole(int Select1, string Select2)
{
IEnumerable<string> tijelaNaziv = db.InspekcijskaKontrolas.OrderBy(i => i.InspekcijskoTijelo.NazivInspekcijskogTijela).Select(i => i.InspekcijskoTijelo.NazivInspekcijskogTijela).Distinct();
ViewBag.Select1 = new SelectList(tijelaNaziv);
IQueryable<InspekcijskaKontrola> listaKontrola = db.InspekcijskaKontrolas.Select(i => i);
if (!string.IsNullOrEmpty(Select1.ToString())&&!string.IsNullOrEmpty(Select2.ToString()))
{
string[] parts = Select2.Split('.');
DateTime datum = new DateTime(int.Parse(parts[2]), int.Parse(parts[1]), int.Parse(parts[0]));
listaKontrola = listaKontrola.Where(l => l.InspekcijskoTijeloId == Select1).Where(l => l.DatumInspekcijskeKontrole == datum).Select(l => l);
}
return View(listaKontrola.ToList());
}
(Posted on behalf of the OP).
This is solved. I just put into view:
#foreach (var i in Model.Select(i=>i.InspekcijskoTijelo).Distinct()) {
<option value="#i.InspekcijskoTijeloId">#i.NazivInspekcijskogTijela</option>
}
I have a view in my app, that allows user to set up 2 multiselects.
The problem is: how can I send contents of those multiselects back to controller.
So far I have:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div id="member-list">
<div class="row" id="transfer">
<div class="col-md-6">
<select multiple="multiple" id="right-select">
#foreach (var item in Model.AnotherContacts)
{
<option value="#item.Id" onclick="transfer(this)">
#item.Email - #item.Name
</option>
}
</select>
</div>
<div class="col-md-6">
<select multiple="multiple" id="left-select">
#foreach (var item in Model.Group.Members)
{
<option value="#item.Contact.Id" onclick="transfer(this)">
#item.Contact.Email - #item.Contact.Name
</option>
}
</select>
</div>
</div>
</div>
<div class="col-md-3">
<input type="submit" class="btn btn-grey" value="Save" />
</div>
</div>
And now: how to write a controller to have there list of items, hat I have in both multiselects?
[HttpPost]
public ActionResult Manage(int id)
{
return View();
}
Well first for a form post to be successful you need to add name attributes to your inputs.
<select multiple="multiple" id="left-select" name="leftSelect">
<select multiple="multiple" id="right-select" name="rightSelect">
Then your controller would be
[HttpPost]
public ActionResult Manage(int[] leftSelect, int[] rightSelect)
{
//your code
return View();
}
Notice the names of method parameters are the same as the name attributes on the select lists.
Note: I assumed your #item.Contact.Id and #item.Id are of type
int.
Make your controller expect several parameters
[HttpPost]
public ActionResult Manage(int id, int id2)
{
//your code
return View();
}
This of course depends on what you want to send to to the controller, but I hope you get the idea. You havent shown the code required, but I would guess you have selectLists that return strings, and if that is the case, change the parameters in the Manage Action to expect string variables
this is my html form of consents. after posting the inputs i get error on the browser
<form th:object="${consent}" action="../users/userDetails.html" th:action="#{${#httpServletRequest.servletPath}}" method="post">
<fieldset>
<div class="col-sm-7 col-md-6 col-lg-5">
<label for="last_name">Service Provider</label>
<select id="provider" name="provider" class="form-control" th:onchange="'javascript:showPIIDoc(this.value);'">
<option th:value="0" >Select a Service Provider</option>
<option th:each="provider : ${user.providers}" name="name" th:value="${user.id} +','+ ${provider.id}" th:text="${provider.name}" >[name]</option>
</select>
</div>
<div style="clear:both"></div>
<div class="col-sm-7 col-md-6 col-lg-5">
<label for="last_name">PII Document</label>
<select id ="documentdiv" class="form-control">
</select>
</div>
<div style="clear:both"></div>
<div class="col-sm-7 col-md-6 col-lg-5">
<label for="last_name">Share with</label>
<select class="form-control">
<option th:value="0" >Select a user you want share the document to</option>
<option name="name" th:each="user : ${users}" th:value="${user.id}" th:text="${user.firstName} + ' ' + ${user.lastName}">[name]</option>
</select>
</div>
<div style="clear:both"></div>
<div class="col-sm-7 col-md-6 col-lg-5">
<label for="last_name">Consent</label>
<div style="clear:both"></div>
<input type="checkbox" name="share" th:value="1" th:text="Share" />
</div>
<div style="clear:both"></div>
<div style="margin-top:10px;margin-left:10px" class="form-actions">
<button class="btn btn-primary" type="submit">Add Consent</button>
</div>
</fieldset>
</form>
this is my controller
#RequestMapping(value = "/users/{userId}/providers/{providerId}/documents/{documentId}/consents/new", method = RequestMethod.POST)
public String processNewConsentForm(#PathVariable("userId") int userId, #PathVariable("providerId") int providerId,
#PathVariable("documentId") int documentId, #ModelAttribute("consent") Consent consent, BindingResult result, SessionStatus status) {
User user = this.clinicService.findUserById(userId);
Provider provider = this.clinicService.findProviderById(providerId);
System.out.println("daghade");
System.out.println(provider);
Document doc = this.clinicService.findDocumentById(userId);
Consent c =new Consent();
c.setProvider(provider);
c.setDocument(doc);
c.setUser(user);
c.setStatus(c.getStatus());
c.setFriend(c.getFriend());
System.out.println(c);
if (result.hasErrors()) {
return "providers/createOrUpdateConsentForm";
} else {
this.clinicService.saveConsent(c);
status.setComplete();
return "redirect:/users/{userId}";
}
}
I get this error on the browser
HTTP Status 500 - Expected session attribute 'consent'
after submitting the form
This is the code of Controller for GET Method. it used to call the consent form
#RequestMapping(value = "/users/{userId}/providers/{providerId}/documents/{documentId}/consents/new", method = RequestMethod.GET)
public String initNewConsentForm(#PathVariable("userId") int userId,#PathVariable("providerId") int providerId,#PathVariable("documentId") int documentId, Model model) {
User user = this.clinicService.findUserById(userId);
Provider provider = this.clinicService.findProviderById(providerId);
Document document = this.clinicService.findDocumentById(documentId);
Collection<User> users = this.clinicService.AllUsers();
Consent consent = new Consent();
model.addAttribute("provider",provider);
model.addAttribute("document", document);
model.addAttribute("user", user);
model.addAttribute("users", users);
return "providers/createOrUpdateConsentForm";
}
add model.addAttribute("consent", consent); in your GET method.
Now I am creating application using MVC Music Store tutorial. I want to implement sort function. I got stuck in implementation of Post Browse action.
Browse.cshtml
#model Overstock.Models.Category
#{
ViewBag.Title = "Browse Albums";
}
<div class="product">
<h3><em>#Model.Name</em> Products</h3>
<form action="/Store/Browse" method="POST">
Sort
<select id="Category" name="Category">
<option value="All">All</option>
<option value="Electronics">Electronics</option>
<option value="Sports">Sports</option>
<option value="Watches">Watches</option>
<option value="Office">Office</option>
<option value="Beauty">Beauty</option>
</select>
products by
<select id="SortType" name="SortType">
<option selected="selected" value="Name">Name</option>
<option value="Price">Price</option>
</select>
in
<select id="OrderBy" name="OrderBy">
<option selected="selected" value="Ascending">Ascending</option>
<option value="Descending">Descending</option>
</select>
order
<input type="submit" value="Set" />
</form>
<ul id="product-list">
#foreach (var product in Model.Products)
{
<li id="product">
<a href="#Url.Action("Details", new { id = product.ProductId })">
<img id="image" alt="#product.Title" src="#product.PictureUrl" />
<span>#product.Title</span>
</a>
</li>
}
</ul>
</div>
StoreController.cs
// GET: /Store/Browse
public ActionResult Browse(string category)
{
var varCategory = MyDB.Categories.Include("Products").Single(c=> c.Name==category);
return View(varCategory);
}
[HttpPost]
public ActionResult Browse(string Category, string SortType, string OrderBy)
{
//What should I put here?
return View();
}
What should I write in Browse Post action? Please help.
Using OrderBy and OrderByDesceding for example:
if(SortType == "Name") && (OrderBy == "Ascending")
MyDB.Categories.Where(x => x.Name == Category).OrderBy(x => x.Name);