I have a fictional website in ASP.NET MVC4 that's designed to simulate a private jet hire company ticket booking system. However, I am struggling a bit when it comes to implementing the features I want to have, one of which is using a dropdown menu to store data into another database
To give you a better idea of what I'm really aiming towards
Users to log in to the website
Go to the flights page
Have a look at the flights
Eventually go on to the make a booking page
Then
Select their desired flight from a dropdown menu
Input the number of tickets they want to purchase. (The dropdown is working but the reset isn't implemented)
The user database should then check for the user's age (which is already
stored in the database) is between 18 and 64
If they're outside of that range, an error message should appear
and prevent them from booking a ticket.
If they're within that range, the amount of seats left should decrement by the number of tickets "purchased"
Also
The booking page should prompt the user to log in if they haven't already done so.
This is where it gets really confusing for me.
I have two pages related to the flights:
Page 1 (Flights.cshtml - shows a table of the available flights): http://gyazo.com/2ab67e35bdd1967e4a24706e398ba759
Page 2 (BookFlight shows a dropdown menu, allowing the user to select the flight they want): http://gyazo.com/67948e5e8be82c72f7ee0914dfa9b5f6
(Screenshot of the project files in solution explorer)
Here are my relevant files related to the flights table (on page 1)
https://gist.github.com/anonymous/144ed06e1d4f2011161e
Page 2 reads from the list on page 1 and here's how it's done:
View:
#model List<Project_v3.Models.FlightsTable>
#{
ViewBag.Title = "Book Flight | Open Airlines";
Layout = "~/Views/Shared/_MyLayout.cshtml";
}
<h2>Book A Flight</h2>
<select id='SelectedFlight' name='SelectedFlight'>
#foreach (var flight in Model)
{
<option value='#flight.FlightID'>#String.Format("{0} to {1}", flight.Departure, flight.Arrival)</option>
}
</select>
Controller:
public ActionResult BookFlight()
{
using (var context = new FlightsDBEntities())
{
// Get all of the flights within your table
var flights = context.FlightsTables.ToList();
// Pass the flights to your View
return View(flights);
}
}
My Question is
How do I make the data from the dropdown menu a field in another database table named 'Booking' for example? (I have not made this table yet). If that makes sense?
How do I take the information (from the dropdown) that the user has selected and store it with a press of a button? Is this even possible? Would anyone be able to show me a working example of this based on the code I listed above?
First you have to create a model where you will store the item that will be selected.
public class BookingModel
{
public string SelectedFlightId {get;set;}
public List<SelectListItem> Flights {get;set;}
}
You need to modify the Action that make use of the new model.
public ActionResult BookFlight()
{
using (var context = new FlightsDBEntities())
{
// Get all of the flights within your table
var flights = context.FlightsTables.ToList();
var booking = new BookingModel();
booking.Flights = flights.Select(f => new SelectListItem
{
Text = String.Format("{0} to {1}", f.Departure, f.Arrival),
Value = f.FlightID.ToString()
}).ToList();
return View(booking);
}
}
Modify the View to make use of our new Model
#model Project_v3.Models.BookingModel
#{
ViewBag.Title = "Book Flight | Open Airlines";
Layout = "~/Views/Shared/_MyLayout.cshtml";
}
<h2>Book A Flight</h2>
#using(Html.BeginForm())
{
#Html.DropDownListFor(x => x.SelectedFlightId, Model.Flights)
<input type="submit" value="Submit" />
}
Create a new Action that have the same name as the first action, but put HttpPost attribute. In this action you will get SelectedFlightId after the form was submited
[HttpPost]
public ActionResult BookFlight(BookingModel booking)
{
using (var context = new FlightsDBEntities())
{
if(ModelState.IsValid)
{
var flightId = Int32.Parse(booking.SelectedFlightId);
var flight = context.FlightsTables.First(f => f.FlightID == flightId);
var user = context.UsersTables.First(u => u.UserId == User.Identity.GetUserId());
user.Flights.Add(flight)
context.SaveChanges();
}
// repopulate again the flights (this can be cached and/or be refactored a under method)
var flights = context.FlightsTables.ToList();
booking.Flights = flights.Select(f => new SelectListItem
{
Text = String.Format("{0} to {1}", f.Departure, f.Arrival),
Value = f.FlightID.ToString()
}).ToList();
}
return View(booking);
}
Related
Currently trying to build a bulletin in my application where the logged in user simply types in something in a text box and the results are then displayed with a list of other bulletins.
My problem is that I don't want to display the dropdown box of names, I just want the admins' ID who is logged in to post. FYI, I messed up my admin in this app, their ID is different to their userID but their usernames are the same and that is how I get their ID.
I want to store the result of a linq query in the HiddenFor in my razor page. I've been trying with ViewBags but I just get cannot implicitly convert type 'int' to 'system.collections.ienumerable'
Here is my Create part of my controller:
// GET: Bulletins/Create
public ActionResult Create()
{
string username = Membership.GetUser().UserName;
var getAdmin = (from a in db.Admins
where username == a.AdminUsername
select a.AdministrationId).SingleOrDefault();
ViewBag.AdministrationId = new SelectList(db.Admins, "AdministrationId", "AdministratorName");
return View();
}
// POST: Bulletins/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "BulletinsID,DetailsOfBulletin,AdministrationId")] Bulletins bulletins)
{
if (ModelState.IsValid)
{
string username = Membership.GetUser().UserName;
var getAdmin = (from a in db.Admins
where username == a.AdminUsername
select a.AdministrationId).SingleOrDefault();
db.Bulletins.Add(bulletins);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.AdministrationId = new SelectList(db.Admins, "AdministrationId", "AdministratorName", bulletins.AdministrationId);
return View(bulletins);
}
And my Razor View:
#Html.HiddenFor(model => model.AdministrationId)
Honestly couldn't find anything so any help would be appreciated. x
First, you should materialize your query to get all admin object from your db:
var adminIds = db.admins.Select(a => a.Id).ToList();
ViewBag.AdministrationIds = adminIds;
Then, if you are using ViewBag to access those admin ids in the view, you will need to foreach over them and render a hidden input with the ID as the value:
#{
foreach (var item in ViewBag.AdministrationIds)
{
<input type ="hidden" value="#item" />
}
}
Hello again stackoverflow! Newbie still learning here, I am now trying to create a small MVC with entity framework application(website?). I've gotten to the point where I can create, a new user, edit, delete them. Now I've created a new page and from a dropdownlist I want to select a persons name (that I've entered on the other base) from the database, now after the dropdownlist is populated, I want to be able to click on their name and either automatically redirect to the persons edit page, or click an edit button that takes me to their page.
[dropddownlist] < This contains the names
[John Smith 1] < Now I would click on a name, the 1 represents his student ID and both "john" and "smith" are separate parts of the table in the database.
[John Smith 1] [Edit] < now that I have his name selected in the dropdownlist I can click the little edit button and it takes me to another part of my little project the edit page! localhost/employees/edit/1
In my drop down list controller I have this (FirstN is First Name and LastN is Last Name in the database).
public ActionResult Index(string ddl)
{
ViewBag.ddl = (from r in db.Students select r.FirstN + "," + r.LastN);
}
public ActionResult Edit(string ddl)
{
Student student = db.Students.Find(ddl);
if (student== null)
{
return HttpNotFound();
}
return View(student);
}
Under the view I have this
#Html.DropDownList("Edit", new SelectList(ViewBag.ddl));
#Html.ActionLink("Edit", "Edit", new SelectList(ViewBag.ddl))
This doesn't seem to be working and I'm not really getting anywhere. So I want to try a different approach on how to get there.
My question I'm asking help for is: I want to set their names to a value of their studentID (this is from the database and can't be hard coded FirstN: John LastN=Smith StudentID=1) but then click the edit or search button and go from localhost/EditStudent to localhost/student/edit/1 and it would take you to the "John Smith" edit page.
Thanks to anyone who takes the time to read this!
Ok... Let me explain you the way that I know.. Maybe someone else will have a more simple way...
I am explaining this without trying it in a code editor, So if there is any error that anyone notice, then please notify me.
I hope you need to get the selected value to the post method in controller.
Consider we have a Model name as Students. So getting our job done We need to create a Model as
public class StudentListModel
{
public List<Student> StudentList{ get; set;}
public SelectList StudentSelectList { get; set;}
public int SelectedStudentId { get; set;}
}
[HttpGet]
public ActionResult StudentList()
{
StudentListModel studentList = new StudentListModel();
studentList.StudentList = //Code to load the student.
studentList.StudentSelectList = new SelectList(studentList.StudentList, "StudentId", "StudentName");
return View(studentList);
}
And in View
#Html.DropDownListFor(m=>m.SelectedStudentId , Model.StudentSelectList, "Select Student")
Then in controller the post method will be like.
[HttpPost]
public ActionResult StudentList(StudentListModel studentListModel)
{
int SelectedStudentValue = studentListModel.SelectedStudentId;
// Do other operations with the id
return View();
}
I want to display records of different entities relating to a single entity.
A tenant for example has a collection of rents, rents in turn have collection of payments.
I want to display in the view, all tenants with the rents and payments.
Here is my current implementation in my view.
#foreach (var t in Model.Tenants)
{
<tr>
<td>#t.Fullname</td>
#foreach (var rents in t.Rents)
{
<td>#rents.Apartment.BedroomType</td>
<td>#rents.Apartment.MonthlyFee.ToString("N0")</td>
<td>#($"{#rents.Total.ToString("N0")}/{#rents.Type}")</td>
<td>#($"{#rents.DueDate.ToString("MMM yyy")}")</td>
foreach (var payments in rents.Payments)
{
<td>#payments.PaymentDate.ToString("MMM dd,yyyy")</td>
<td>#payments.AmountPaid.ToString("N0")</td>
<td>#payments.Balance</td>
}
}
</tr>
}
This currently works fine but I don't want to be doing lots of filtering on the client which I think its not a good practice, so I want to move the logic to my controller to handle all filtering of records.
What I want to do is change this implementation using a list and add each collection into its own list. Payments for instance would be in its own list relating to its rent. Rents would be in its own list relating to the specific tenant. By doing this I can maybe filter rents based on rental status or only show payments that have been actually paid. This current implementation does not give me that.
I could really use some help with guidelines here...
I would say you just need to make a small change. In your view model, have a list of payments instead of tenants (do it the other way round). Have a look at the example below for an idea of what I mean:
[HttpGet]
public ActionResult Index(string bedRoomType = "", double amountPaid = 0)
{
var viewModel = new TenantIndexVm();
using (var context = new RentEntities())
{
viewModel.Payments = context.Payment.Where(x => (x.Rent.BedRoomType == bedRoomType || bedRoomType == "") && (x.AmountPaid >= amountPaid)).Include("Rent.Tenant");
}
return View(viewModel);
}
In the view, you would loop through the payments:
#foreach (var p in Model.Payments)
{
<tr>
<td>#p.Rent.Tenant.Fullname</td>
<td>#p.Rent.Apartment.BedroomType</td>
<td>#p.Rent.Apartment.MonthlyFee.ToString("N0")</td>
<td>#($"{#p.Rent.Total.ToString("N0")}/{#p.Rent.Type}")</td>
<td>#($"{#p.Rent.DueDate.ToString("MMM yyy")}")</td>
<td>#p.PaymentDate.ToString("MMM dd,yyyy")</td>
<td>#p.AmountPaid.ToString("N0")</td>
<td>#p.Balance</td>
</tr>
}
I have loosely followed: specify name and id to Drop down razor technique asp dot net mvc4
What my desired end result is is that I have a view which has two dropdowns which are populated with values from the 'ww' column in a DB. Once a user selects a start and end and clicks a submit button, it would then pass the selected values to another ActionMethod that then takes those values and performs a similar query and directs to a different view with a different set of controls.
However, I'm getting a
"Cannot convert type 'ViewModels.DropDownVM' to
'System.Web.Mvc.SelectList'"
error at the following line in my code and haven't been able to figure out how to fix the issue so that everything runs smoothly.
#Html.DropDownList("WWStart", (SelectList)ViewBag.DDLWWStart, " -- Select Starting Work Week -- ")
I have the following:
ViewModels/DropDownVM.cs snippet:
public class DropDownVM
{
public int SelectedCategory { get; set; }
//public string CategoryName { get; set; }
public SelectList Categories { get; set; }
}
IndicatorController Index():
public ActionResult Index()
{
using (var context = new taskDBContext())
{
var DDLWWQuery = (from wq in context.taskSet
select new
{
wq.ww
}).Distinct().OrderByDescending(x => x.ww);
// The controls have a Work Week Range so we need both a start and end control
var DDLWWStartVM = new DropDownVM();
DDLWWStartVM.Categories = new SelectList(DDLWWQuery, "ww", "ww");
ViewBag.DDLWWStart = DDLWWStartVM;
//ViewBag.DDLWWStart = new SelectList(DDLWWQuery.AsEnumerable(), "ww", "ww", "-- Select Starting WW --");
//ViewBag.DDLWWEnd = new SelectList(DDLWWQuery.AsEnumerable(), "ww", "ww", "-- Select Ending WW --");
var DDLWWEndVM = new DropDownVM();
DDLWWEndVM.Categories = new SelectList(DDLWWQuery, "ww", "ww");
ViewBag.DDLWWEnd = DDLWWEndVM;
}
return View();
}
Index View Snippet:
#model IEnumerable<TaskTracker.ViewModels.DropDownVM>
#{
ViewBag.Title = "Create Indicator: Step One of Two";
}
<h2>Indicators</h2>
<p>This is currently being refined.</p>
<div>Create Indicator: Step One of Two - Select Work Week Range</div>
using (Html.BeginForm("StepTwo", "Indicator", new { wwStartSelect = WWStart.Categories.Text, wwEndSelect = WWEnd.Categories.Text }))
{
<div>Select Starting Work Week</div>
#Html.DropDownList("WWStart", (SelectList)ViewBag.DDLWWStart, " -- Select Starting Work Week -- ")
<div>Select Ending Work Week</div>
#Html.DropDownList("WWEnd", (SelectList)ViewBag.DDLWWEnd, " -- Select Ending Work Week -- ")
#Html.AntiForgeryToken()
<input type="submit" title="Next Step" value="Next Step" />
}
How can I resolve this error by fixing my code to get the desired result?
You are not casting the right object. You should cast it to the Categories Property ... see below
#Html.DropDownList("WWStart", (SelectList)ViewBag.DDLWWStart.Categories, " -- Select Starting Work Week -- ")
#Html.DropDownList("WWEnd", (SelectList)ViewBag.DDLWWEnd.Categories, " -- Select Ending Work Week -- ")
I'll explain a quiet better here. I've this method wich returns me some lines of ma table according to a searchstring I informed in my textbox.
public ActionResult Index(string site, string searchString)
{
var user = from m in db.OrderDetails
select m;
if (!String.IsNullOrEmpty(searchString))
{
user = user.Where(s => s.Order.ClientID.Contains(searchString));
}
if (!String.IsNullOrEmpty(site))
{
user = user.Where(c => c.Order.SiteNumber.Contains(site));
}
return View(user);
}
In the same class, I've an other method which generate a pdf file (all the backend process is set up in a second project include in the first).
public ActionResult PrintOrders()
{
var user = from m in db.OrderDetails
select m;
return this.ViewPdf("Facture", "PrintView", user);
}
This second method, when it generate my pdf file, displays all the entries of my table. I would like that, when I click on my link (on the same page view wich display my table entries) for generate my pdf file, if I did a search before, I juste have fields that match my searchstring (or site string).
How can I implement it ? There is a way do to it ?
Thanks for your help, and sorry for the title which is maybe not too relevant. Also sorry for my english, hope you'll understand my aim.
EDIT INFORMATIONS
After looking, when I set up my PrintOrders() method like my Index() method as follow :
public ActionResult PrintOrders(string searchString, string username)
{
var user = from m in db.OrderDetails select m;
if (!String.IsNullOrEmpty(searchString))
{
user = user.Where(s => s.Order.ClientID.Contains(searchString));
}
if (!String.IsNullOrEmpty(site))
{
user = user.Where(c => c.Order.SiteNumber.Contains(site));
}
return this.ViewPdf("Facture Krys-Group", "PrintView", user);
}
and set my view like this :
#using (Html.BeginForm("PrintOrders", "Historic", FormMethod.Get))
{
Seach by ID : #Html.TextBox("searchString")
Search by Site : #Html.TextBox("site")
<input type="submit" value="Search" /></p>
}
then it works. But I've already the same form in my view for "Index" instead of "PrintOrders". How can I combine both ?
I am not sure I follow you completely but I think you achieve what you are looking for with the use of partial views. The form you mention can be a partial view that gets rendered into the pdf view and like that you really have one form but displayed in both pages. Hopefully I understood what you were after and this helps you.