I have my order class created, you can make Orders and View the orders. However now I am trying to create a "Returns" page that basically allows the user to enter a return reason and then print the reason/invoice. I have the orders create form however I am not sure how to link the 2 to say This Returns Belongs To This Order all I can do is create a generic return that is linked to nothing. I have set up the relationship Im just not sure how to connect the return to the specific order. I know this is a basic question, I just couldn't find anything online to help me. Im a student and an explanation would be very beneficial as I need to use similar methods to this in other aspects
Here is my controller to view MyOrders and the ReturnsForm
namespace T_shirt_Company_v3.Controllers
{
public class MyOrderController : Controller
{
TshirtStoreDB db = new TshirtStoreDB();
/// <summary>
/// Returns a list of Orders made by the user
/// </summary>
/// <param name="date">choose date period viewing orders</param>
/// <param name="order">Orders being viewed</param>
/// <returns></returns>
[Authorize]
public ActionResult Index(string date, Order order)
{
TshirtStoreDB db = new TshirtStoreDB();
string currentUser = this.User.Identity.GetUserName();
List<T_shirt_Company_v3.ViewModels.MyOrdersViewModel> list = (from o in new TshirtStoreDB().Orders
.Where(o => o.Username == currentUser)
.OrderByDescending(o => o.OrderDate)
.Select(o => new MyOrdersViewModel()
{
OrderId = o.OrderId,
Address = o.Address,
FirstName = o.FirstName,
LastName = o.LastName,
City = o.City,
OrderDate = o.OrderDate,
PostalCode = o.PostalCode,
Total = o.Total,
HasBeenShipped = o.HasBeenShipped,
PostageList = o.PostageList,
Details = (from d in o.OrderDetails
select new MyOrderDetails
{
Colour = d.Product.Colour,
Quantity = d.Quantity,
Title = d.Product.Title,
UnitPrice = d.UnitPrice
}).ToList()
}).ToList() select o).ToList();
if (date != null)
{
DateTime today = DateTime.Now.AddDays(Convert.ToInt32(date) * -1);
return View(list.Where(x => x.OrderDate >= today).ToList());
}
return View(list);
}
public ActionResult ReturnsForm()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ReturnsForm([Bind(Include = "ReturnId,OrderId,ReturnDate,Reason")] returnDetails returnDetails)
{
if (ModelState.IsValid)
{
if (returnDetails != null)
{
returnDetails.ReturnDate = DateTime.Now;
}
db.returnDetails.Add(returnDetails);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(returnDetails);
}
}
}
and my MyOrders view
#model List<T_shirt_Company_v3.ViewModels.MyOrdersViewModel>
#{
ViewBag.Title = "My Orders";
}
<style>
table, th, td {
border: 0px solid black;
border-collapse: collapse;
margin-bottom:50px;
padding-bottom:50px;
}
th, td {
padding: 5px;
border-spacing: 10px;
text-align: center;
}
</style>
<center>
<h1>My Orders</h1>
<br />
#using (Html.BeginForm("Index", "MyOrder", FormMethod.Get))
{
<text>Orders Made </text><select id="date" name="date">
<option value="9999">All Orders</option>
<option value="1">In the last day</option>
<option value="7">In the last week</option>
<option value="30">In the last month</option>
<option value="365">In the last year</option>
</select>
<input type="submit" name="submit" value="Search" />
}
<table>
#foreach (var m in Model)
{
<tr>
#*<td style="background-color: #ffffe0"><b>Order Status</b> <br />#ViewBag.ShippedMessage</td>*#
<td style="background-color: #ffffe0"><b>Order Status</b> <br />#(m.HasBeenShipped ? "Order has been shipped" : "Order is being processed") <br /> #ViewBag.PostageStatus</td>
<td style="background-color: #ffffe0"><b>Order Placed</b> <br />#m.OrderDate <br /> #m.PostageList</td>
<td style="background-color: #ffffe0"><b>Dispatched to</b> <br />#m.FirstName #m.LastName</td>
<td style="background-color: #ffffe0"><b>Delivery Address</b><br /> #m.Address <br /> #m.City <br /> #m.PostalCode <br /> </td>
<td style="background-color: #ffffe0"><b>Total Cost</b><br /> £#m.Total</td>
<td style="background-color: #ffffe0"><b>Order Number</b><br /> #m.OrderId</td>
</tr>
foreach (var d in m.Details)
{
<tr>
<td colspan="3" style="text-align: left; background-color:#ADD8E6;"><b>Product Name</b> #d.Title <br /><b>Colour</b> #d.Colour</td>
<td style="background-color: #ADD8E6"><b>Price: </b> £#d.UnitPrice</td>
<td colspan="2" style="background-color: #ADD8E6"><b>Quantity Ordered: </b> #d.Quantity</td>
</tr>
}
<tr><td>#Html.ActionLink("Return Order", "ReturnsForm")</td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
}
</table>
</center>
My ReturnsCreate View
#model T_shirt_Company_v3.Models.returnDetails
#{
ViewBag.Title = "ReturnsForm";
}
<h2>ReturnsForm</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>returnDetails</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Reason, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Reason, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Reason, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Classes
namespace T_shirt_Company_v3.Models
{
//[Bind(Exclude = "OrderId")]
public partial class Order
{
[ScaffoldColumn(false)]
public int OrderId { get; set; }
[ScaffoldColumn(false)]
public System.DateTime OrderDate { get; set; }
[ScaffoldColumn(false)]
[Remote("CheckUserName", "Account")]
public string Username { get; set; }
[Required]
[StringLength(16, ErrorMessage = "Your name is too long")]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Your last name is required.")]
[StringLength(16, ErrorMessage = "Last name is too long.")]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required(ErrorMessage = "Address is required.")]
public string Address { get; set; }
[Required(ErrorMessage = "City is required.")]
public string City { get; set; }
[Required(ErrorMessage = "Postcode is required.")]
[Display(Name = "Post Code")]
public string PostalCode { get; set; }
[Required(ErrorMessage = "Country is required.")]
public string Country { get; set; }
[Required(ErrorMessage = "Phone number is required.")]
public string Phone { get; set; }
[RegularExpression(#"[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "Email doesn't look like a valid email address.")]
public string Email { get; set; }
[System.ComponentModel.DataAnnotations.Compare("Email")]
[Display(Name = "Confirm your email address")]
public string EmailConfirm { get; set; }
[ScaffoldColumn(false)]
public string PaymentTransactionId { get; set; }
[ScaffoldColumn(false)]
public bool HasBeenShipped { get; set; }
[ScaffoldColumn(false)]
//[ReadOnly(true)]
public decimal Total { get; set; }
[Required]
[Range(0, 2, ErrorMessage = "Select a delivery method")]
public Postage? PostageList { get; set; }
public CardDetails cardDetails { get; set; }
//public List<CardDetails> cardDetails { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
public int ReturnId { get; set; }
public virtual returnDetails returns { get; set; }
}
public enum Postage {[Display(Name = "Standard Delivery - Free")]StandardDelivery, [Display(Name = "First Class Delivery - £5")]FirstClass, [Display(Name = "24 Hour Delivery - £10")]TwentyFourHour }
public class returnDetails
{
[Key]
public int ReturnId { get; set; }
[ScaffoldColumn(false)]
public System.DateTime ReturnDate { get; set; }
[Required]
public string Reason { get; set; }
[ForeignKey("Order")]
public int OrderId { get; set; }
public virtual Order order { get; set; }
}
}
Keys
In the Return class
[ForeignKey("Order")]
public int OrderId { get; set; }
public virtual Order order { get; set; }
In the Order Class
public int ReturnId { get; set; }
public virtual returnDetails returns { get; set; }
In your MyOrders.cshtmlview, you need to generate a link to your ReturnsForm() method and pass the ID of the order
#foreach (var m in Model)
{
....
#Html.ActionLink("Return Order", "ReturnsForm", new { orderID = m.OrderId })
}
and modify the method to
public ActionResult ReturnsForm(int orderID)
{
returnDetails model = new returnDetails()
{
OrderId = orderID
};
return View(model );
}
and then in your ReturnsCreate.cshtml view, include a hidden input for the property
#Html.HiddenFor(m => m.OrderId )
so is value will be bound when you post back the model.
Side note: The code above uses your data model but that is poor practice and you should be using a view model for Returns
Related
My project was working but from tomorrow I am getting required field validation error on the ModelState.IsValid
My Model:
public class CategoryModel
{
public int CategoryId { get; set; }
public int UserId { get; set; }
public int CategoryParent { get; set; }
[Required]
[Display(Name = "Category Name")]
public string CategoryName { get; set; }
public bool Status { get; set; }
public DateTime CreatedOn { get; set; }
public string CreatedOnString { get; set; }
public DateTime? UpdatedOn { get; set; }
}
MVC Page:
#model LSB.Common.Model.CategoryModel
#{
ViewBag.Title = "Category";
Layout = "~/Areas/Restaurant/Views/Shared/_RestaurantLayout.cshtml";
}
#using (Html.BeginForm("Category", "menu", FormMethod.Post))
{
<div class="form-group row">
<div class="col-sm-6">
#Html.LabelFor(x => x.CategoryName)
#Html.TextBoxFor(x => x.CategoryName, new { #class = "form-control", #placeholder = "First Name", #maxlength = "20" })
#Html.ValidationMessageFor(x => x.CategoryName)
</div>
</div>
#Html.HiddenFor(x => x.CategoryId)
<input type="submit" value="test" />
}
Controller:
[Authorize(Roles = "Restaurant")]
[HttpPost]
public ActionResult Category(CategoryModel categoryModel)
{
//ModelState.Remove("CategoryId");
if (!(ModelState.IsValid))
{
return View(categoryModel);
}
}
Model State
Database Used: MySql Server
DotNet Core Version = 2.2
Platform: Windows 10 IIS
When I am trying to save an attendance of an existing employee, the attendance page is trying to create a new employee with null values in Name fields. Since name field is set to not null its failed and showing error message.
Employee Table
namespace payroll_razor_core.Models.repository
{
[Table("Employee")]
[Display(Name = "Employee",Description = "Stores Employee Basic Details.")]
public class Employee
{
[Column("Employee Id")]
[Key]
public string EmployeeId { get; set; }
public string EmployeeName =>
string.Concat(EmployeeFirstName,
string.IsNullOrEmpty(EmployeeMiddleName)?"":" "+EmployeeMiddleName,
string.IsNullOrEmpty(EmployeeLastName) ? "" : " " + EmployeeLastName
);
[Column("Employee First Name")]
[Display(Name = "First Name *")]
[MaxLength(200, ErrorMessage = "Exceeded Character Limit..!!")]
[RegularExpression(#"^[[A-Za-z+[\s]+[A-Za-z]+]*]*", ErrorMessage = "Can accept only characters..!!",
MatchTimeoutInMilliseconds = 1000)]
[Required(ErrorMessage = "Employee First Name is required..!!")]
public string EmployeeFirstName { get; set; }
[Column("Employee Middle Name")]
[Display(Name = "Middle Name *")]
[MaxLength(200, ErrorMessage = "Exceeded Character Limit..!!")]
[RegularExpression(#"^[[A-Za-z+[\s]+[A-Za-z]+]*]*", ErrorMessage = "Can accept only characters..!!",
MatchTimeoutInMilliseconds = 1000)]
public string EmployeeMiddleName { get; set; }
[Column("Employee Last Name")]
[Display(Name = "Last Name *")]
[MaxLength(200, ErrorMessage = "Exceeded Character Limit..!!")]
[RegularExpression(#"^[[A-Za-z+[\s]+[A-Za-z]+]*]*", ErrorMessage = "Can accept only characters..!!",
MatchTimeoutInMilliseconds = 1000)]
public string EmployeeLastName { get; set; }
public ICollection<AttendanceDailyRegister> AttendanceDailyRegisters { get; set; }
}
Attendance Table
[Table("Attendance")]
[Display(Name = "Attendance",Description = "Registers Employee Attendance")]
public class Attendance
{
[Key]
[Column("Attendance Id")]
[Display(Name = "Attendance Id")]
public int AttendanceId { get; set; }
[ForeignKey("EmployeeId")]
[Column("Employee")]
[Display(Name = "Employee")]
public string Employee { get; set; }
public bool Check{ get; set; }
[Column("AttendanceTime")]
[Display(Name = "Attendance Time",AutoGenerateField = true)]
[DisplayFormat(DataFormatString = "{0:dddd, dd/MM/yyyy, h:mm:ss tt}")]
[Timestamp]
public DateTime AttendanceTime { get; set; }
[ForeignKey("Employee")]
public virtual Employee Employees { get; set; }
}
Attendance Create Page
public class CreateModel : PageModel
{
private readonly Data.payroll_app_context _context;
public CreateModel(Data.payroll_app_context context)
{
_context = context;
}
public IActionResult OnGet()
{
ViewData["Employee"] = new SelectList(_context.Employee, "EmployeeId", "EmployeeName");
return Page();
}
[BindProperty]
public AttendanceDailyRegister AttendanceDailyRegister { get; set; }
public async Task<IActionResult> OnPostAsync()
{
//Commented for catching errors.
/*if (!ModelState.IsValid)
{
return Page();
}*/
_context.AttendanceDailyRegister.Add(AttendanceDailyRegister);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Attendance Razor CSHTML Page
#page
#model razor.Pages.attendance.CreateModel
#{
ViewData["Title"] = "Create";
Layout = "~/Pages/Shared/_Layout.cshtml";
}
<h1>Create</h1>
<h4>Attendance</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Attendance.Employee" class="control-label"></label>
<select asp-for="Attendance.Employee" class ="form-control" asp-items="ViewBag.Employee"></select>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="Attendance.Check" /> #Html.DisplayNameFor(model => model.Attendance.Check)
</label>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Here in this page while saving new attendance time of an existing employee, its creating a new employee. I Cannot fix it. Please help me.
The moment I changed the attendance table, the problem got solved. Though I don't clearly understand how it got solved.
[Table("Attendance")]
[Display(Name = "Attendance",Description = "Registers Employee Attendance")]
public class Attendance
{
private readonly Employee employee;
[Key]
[Column("Attendance Id")]
[Display(Name = "Attendance Id")]
public int AttendanceId { get; set; }
[ForeignKey("EmployeeId")]
[Column("Employee")]
[Display(Name = "Employee")]
public string Employee { get; set; }
public bool Check{ get; set; }
[Column("AttendanceTime")]
[Display(Name = "Attendance Time",AutoGenerateField = true)]
[DisplayFormat(DataFormatString = "{0:dddd, dd/MM/yyyy, h:mm:ss tt}")]
[Timestamp]
public DateTime AttendanceTime { get; set; }
[ForeignKey("Employee")]
public virtual Employee Employees => employee
}
I have a view model for a view AddAppointment. It has many properties of which 2 are Required (I wrote Required attribute over it).
Now I want to use the same model for another view but excluding the properties which are required but it doesn't work i.e. it's invalid.
What to do apart from writing another view model?
View Model:
public class AddBookingsViewModel
{
public string CustomerName { get; set; }
public string ContactNo { get; set; }
public string VehicleRegNo { get; set; }
public short fk_VehicleMakeID { get; set; }
public string VehicleModel { get; set; }
[Required(ErrorMessage = "Select appointment time ")]
public int fk_TimeSlotID { get; set; }
public byte fk_BookingModeID { get; set; }
public int EntryUserID { get; set; }
public int ReturnBookingID { get; set; }
[Required(ErrorMessage="Fill in the appointment date")]
[DataType(DataType.Date)]
public DateTime? AppointmentDate { get; set; }
}
View: (Where it is used)
#model ZahidCarWash.ViewModels.AddBookingsViewModel
#{
ViewBag.Title = "Add Appointment";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!-- page banner -->
<!-- end page banner -->
#using (Html.BeginForm())
{
<!-- appointments -->
<div id="appointments" class="appointment-main-block appointment-two-main-block">
<div class="container">
<div class="row">
<div class="section text-center">
<h3 class="section-heading text-center">Get an Appointment</h3>
</div>
<div class="col-md-8 col-sm-12">
<div class="appointment-block">
<h5 class="form-heading-title"><span class="form-heading-no">1.</span>Vehicle Information</h5>
<div class="row">
<div class="col-sm-4">
<div class="dropdown">
#Html.DropDownListFor(Model => Model.fk_VehicleMakeID, new SelectList(ZahidCarWash.DAL.VehicleMakesRepository.getVehicleMakes(), "VehicleMakeID", "MakeTitle"),
new { #class = "form-control" })
</div>
</div>
<div class="col-sm-4">
#Html.EditorFor(Model => Model.VehicleModel, new { htmlAttributes = new { #class = "form-control", placeholder = "Enter Vehicle Model" } })
</div>
<div class="col-sm-4">
#Html.EditorFor(Model => Model.VehicleRegNo, new { htmlAttributes = new { #class = "form-control", placeholder = "Enter Vehicle Reg No." } })
</div>
</div>
<h5 class="form-heading-title"><span class="form-heading-no">2.</span>Contact Details</h5>
<div class="row">
<div class="col-sm-4">
#Html.EditorFor(Model => Model.CustomerName, new { htmlAttributes = new { #class = "form-control", placeholder = "Customer Name" } })
#Html.ValidationMessageFor(Model => Model.CustomerName, "", new { #class = "ErrorMessages" })
</div>
<div class="col-sm-4">
#Html.EditorFor(Model => Model.ContactNo, new { htmlAttributes = new { #class = "form-control", placeholder = "Enter Contact Number." } })
#Html.ValidationMessageFor(Model => Model.ContactNo, "", new { #class = "ErrorMessages" })
</div>
</div>
<button type="submit" class="btn btn-default pull-right">Book Now</button>
</div>
</div>
</div>
</div>
</div>
}
Controller:
public JsonResult AddManualAppointment(AddBookingsViewModel AddBookingVM)
{
if (ModelState.IsValid)
{
AddBookingVM.fk_BookingModeID = 2;
int ReturnRowsCount = BookingRep.InsertCustomerAppointments(AddBookingVM, out ReturnStatus, out ReturnMessage, out ReturnBookingID);
}
else
{
}
return Json(new { ReturnMessageJSON = ReturnMessage, ReturnStatusJSON = ReturnStatus });
}
Data is passed through ajax:
<script type="text/javascript">
//to add an appointment
$('form').submit(function (e) {
e.preventDefault();
if (!$(this).valid()) {
return;
}
var url = '#Url.Action("AddManualAppointment")';
var data = $(this).serialize();
$.post(url, data, function (response) {
if (response.ReturnStatusJSON == true) {
swal("Booked !", response.ReturnMessageJSON, "success");
$("#VehicleRegNo").val("");
$("#VehicleModel").val("");
$("#CustomerName").val("");
$("#ContactNo").val("");
}
else {
swal("Sorry !", response.ReturnMessageJSON, "error");
}
});
});
</script>
<!--End Custom Scripts-->
}
I guess the quick and dirty way is to use #Html.Hiddenfor and fill the value with a new datetime from inside your controller
You can split your view model into a version with and without the required attributes using inheritance:
public class AddBookingsViewModel
{
public string CustomerName { get; set; }
public string ContactNo { get; set; }
public string VehicleRegNo { get; set; }
public short fk_VehicleMakeID { get; set; }
public string VehicleModel { get; set; }
public byte fk_BookingModeID { get; set; }
public int EntryUserID { get; set; }
public int ReturnBookingID { get; set; }
}
public class AddBookingsViewModelWithAppointment : AddBookingsViewModel
{
[Required(ErrorMessage = "Select appointment time ")]
public int fk_TimeSlotID { get; set; }
[Required(ErrorMessage="Fill in the appointment date")]
[DataType(DataType.Date)]
public DateTime? AppointmentDate { get; set; }
}
This allows you to use the appropriate view model in your situation and still maintain compatibilty through polymorphism.
If you need the optional properties in your base class, you can make your properties virtual and apply the attribute in the derived class:
public class AddBookingsViewModel
{
public string CustomerName { get; set; }
public string ContactNo { get; set; }
public string VehicleRegNo { get; set; }
public short fk_VehicleMakeID { get; set; }
public string VehicleModel { get; set; }
public byte fk_BookingModeID { get; set; }
public int EntryUserID { get; set; }
public int ReturnBookingID { get; set; }
public virtual int fk_TimeSlotID { get; set; }
public virtual DateTime? AppointmentDate { get; set; }
}
public class AddBookingsViewModelWithAppointment : AddBookingsViewModel
{
[Required(ErrorMessage = "Select appointment time ")]
public override int fk_TimeSlotID {
get => base.fk_TimeSlotID;
set => base.fk_TimeSlotID = value;
}
[Required(ErrorMessage="Fill in the appointment date")]
[DataType(DataType.Date)]
public override DateTime? AppointmentDate {
get => base.AppointmentDate;
set => base.AppointmentDate = value;
}
}
Use the veriant that works best in your business case.
I want to apply for each loop on two models at the same time.
My Controller Action Is:
public ActionResult MarkAttendance(int id)
{
var students = _context.Students.Where(c => c.ClassId == id).ToList();
var status = _context.Statuses.ToList();
var viewModel = new AttendanceViewModel
{
Student = students,
Status = status
};
return View(viewModel);
}
My Student Model is
public class Student
{
public int Id { get; set; }
[Required]
[StringLength(30)]
[RegularExpression(#"^[A-Za-z\s]{1,}[\.]{0,1}[A-Za-z\s]{0,}$", ErrorMessage = "Invalid name. Use letters only")]
public string Name { get; set; }
[Required]
[StringLength(30)]
[RegularExpression(#"^[A-Za-z\s]{1,}[\.]{0,1}[A-Za-z\s]{0,}$", ErrorMessage = "Invalid name. Use letters only")]
[Display(Name = "Father Name")]
public String FatherName { get; set; }
[Required]
[Range(0, 10000)]
public int Fee { get; set; }
[Required]
[RegularExpression(#"^((\+92)|(0092))-{0,1}\d{3}-{0,1}\d{7}$|^\d{11}$|^\d{4}-\d{7}$", ErrorMessage = "Please enter only mobile number, Landline not acceptable")]
[Display(Name = "Student Contact No.")]
public string StudentContact { get; set; }
[Required]
[RegularExpression(#"^[0-9]+$", ErrorMessage = "Please enter correct phone number")]
[Display(Name = "Guardian Contact No.")]
public string GuardianContact { get; set; }
[Required]
[RegularExpression(#"^[0-9]+$", ErrorMessage = "Enter only numbers")]
[Display(Name = "Roll Number")]
[IfRollNoExists]
public int RollNo { get; set; }
[Required]
[Display(Name = "Record Date")]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime DateTime { get; set; }
[Display(Name = "Student Picture")]
public String ImageURL { get; set; }
public Class Class { get; set; }
[Required]
[Display(Name = "Class Title")]
public int ClassId { get; set; }
[ForeignKey("Account")]
public int AccountId { get; set; }
public virtual Account Account { get; set; }
}
My Status Class is
public class Status
{
public int Id { get; set; }
public string StudentStatus { get; set; }
}
My ViewModel Is:
public class AttendanceViewModel
{
public IEnumerable<Student> Student { get; set; }
public IEnumerable<Status> Status { get; set; }
}
My Razor View is:
#model Pioneer.ViewModel.AttendanceViewModel
#foreach (var student in Model.Student)
{
<tr>
<td>#student.Name</td>
<td>#student.RollNo</td>
<td>
<div data-toggle="buttons">
<label class="btn btn-success active">
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Present", new { id = "1" })
</label>
<label class="btn btn-danger">
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Absent", new { id = "2" })
</label>
<label class="btn btn-primary">
#Html.RadioButtonFor(m => m.Status.StudentStatus, "On Leave", new { id = "3" })
</label>
<label class="btn btn-warning">
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Short Leave", new { id = "4" })
</label>
</div>
</td>
</tr>
}
Now when I am getting error for using
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Present", new { id = "1" })
Below I attached an image of error. Error Screen Shot
And please tell me can I iterate over my rows without using for-each if I use HTML helper here?
What you are trying to achieve is not possible. As per your view code, the Status model should be part of Student model class class.
So your view Model will look like this :
public class AttendanceViewModel
{
public IEnumerable<Student> Student { get; set; }
}
And Student model class will include status :
public class Student
{
public IEnumerable<Status> Status { get; set; }
}
Now you can access status in your view like this :
#model Pioneer.ViewModel.AttendanceViewModel
#foreach (var student in Model.Student)
{
<tr>
<td>#student.Name</td>
<td>#student.RollNo</td>
#foreach(var status in student)
{
<td>
<div data-toggle="buttons">
<label class="btn btn-success active">
#Html.RadioButtonFor(status.StudentStatus, "Present", new { id = "1" })
</label>
<label class="btn btn-danger">
#Html.RadioButtonFor(statusStudentStatus, "Absent", new { id = "2" })
</label>
<label class="btn btn-primary">
#Html.RadioButtonFor(status.StudentStatus, "On Leave", new { id = "3" })
</label>
<label class="btn btn-warning">
#Html.RadioButtonFor(status.StudentStatus, "Short Leave", new { id = "4" })
</label>
</div>
</td>
}
</tr>
}
EDIT :
Or if you're particular about using the same ViewModel as mentioned in the question, you can replace foreach with for. Check below sample code :
#model Pioneer.ViewModel.AttendanceViewModel
#for(var studentIndex = 0; studentIndex < Model.Student.Count(); studentIndex++)
{
<tr>
<td>#Model.Student[studentIndex].Name</td>
<td>#Model.Student[studentIndex].RollNo</td>
#for(var statusIndex = 0; statusIndex < Model.Status.Count; statusIndex++)
{
<td>
<div data-toggle="buttons">
<label class="btn btn-success active">
#Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "Present", new { id = "1" })
</label>
<label class="btn btn-danger">
#Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "Absent", new { id = "2" })
</label>
<label class="btn btn-primary">
#Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "On Leave", new { id = "3" })
</label>
<label class="btn btn-warning">
#Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "Short Leave", new { id = "4" })
</label>
</div>
</td>
}
</tr>
}
m.Status its IEnumerable<Status>, it's have not StudentStatus property.
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Absent", new { id = "2" })
I have a view model that has a of items that are equipment for a session and I want to create a new session but I am not sure how to use a HTML helper to achieve this, here is the view model:
public class SessionInsertViewModel
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Hour { get; set; }
public int Minute { get; set; }
public int Duration { get; set; }
public string Difficulty { get; set; }
public string Equipment { get; set; }
public virtual ICollection<Product> Products { get; set; }
public int ClassId { get; set; }
}
and here is the Form on my view:
#using (Html.BeginForm(MVC.Session.Insert(), FormMethod.Post, new { #class = "form label-inline", name = "iform", enctype = "multipart/form-data", id = "Insert" }))
{
#Html.HiddenFor(model => model.ClassId)
<div class="formSep">
<label class="req">Session Name</label>
<div style="color:red;display:none" id="reqTitle">This Field is required to create a Session</div>
#Html.EditorFor(model => model.Title, new { #class = "medium", id="Title"})
</div>
<div class="formSep">
<span style="color:red">#Html.ValidationMessageFor(model => model.Description)</span>
<label class="req">Description</label>
<div style="color:red;display:none" id="reqDesc">This Field is required to create a Session</div>
#Html.TextAreaFor(model => model.Description,new{style="width: 420px; height: 6em;"})
</div>
<div class="formSep">
<table>
<tr>
<th style="text-align:left"><span>Date</span></th>
<th style="text-align:left"><div>Time</div></th>
</tr>
<tr>
<th style="padding-right: 20px;"><input id="StartDate" type="text" style="width:120px" /></th>
<th><input id="Hour" value="12:00" type="text" style="width:67px" /></th>
</tr>
</table>
</div>
<div class="formSep">
<label class="req">Duration (In Minutes)</label>
#Html.EditorFor(model => model.Duration, new { #class = "medium", id = "Duration" })
</div>
<div class="formSep">
<label class="req">Difficulty</label>
#Html.DropDownListFor(model => model.Difficulty, new SelectList(new List<Object> { new { value = "Easy", text = "Easy" }, new { value = "Medium", text = "Medium" }, new { value = "Difficult", text = "Difficult" } }, "value", "text", #Model.Difficulty), new { id="Difficulty" })
</div>
</div>
}
So I need to be able to select a list of Equipment in the form and send it with the ViewModel to the controller but I am not sure how to do this.
Save the possible options for the dropdowns in the Model, not in the View.
Then you can pass them the other way (so from Controller > Model > View).
Sample:
Model:
public class SessionInsertViewModel
{
// existing code
public List<Difficulty> Difficulties { get; set; }
}
View:
#Html.DropDownListFor( model => model.Difficulty
, new SelectList( Model.Difficulties
, "Text"
, "Value"
)
)