Error when Search() Action Method returns Index View() - asp.net

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

Dynamically created Dropdown list does not return a value

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..

How to put just distinct values into select control MVC ASP.NET?

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>
}

ASP MVC 6: sending multiselectselect as POST

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

HTTP Status 500 - Expected session attribute 'consent'

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.

How to implement sort function in ASP.NET MVC

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);

Resources