How to search between two Dates - c#

I have View page rendered with two outside pages included (#{Html.RenderAction) in One.
All 3 pages have one controller. By default i take all data from MSSQL Database and i have result. Now i need to Filter results by Date, and to take results between some dates.
Here is HTML Code of Search form:
#using (Html.BeginForm("Reporti", "Reporti", null, FormMethod.Get))
{
<table border="0" cellspacing="5" cellpadding="5">
<tbody>
<tr>
<td>Od Datum:</td>
<td><input type="text" id="datumOD" name="datumOD" class="datumOD"></td>
</tr>
<tr>
<td>Do Datum:</td>
<td><input type="text" id="max" name="datumDO" class="datumDO"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Baraj" /></td>
</tr>
</tbody>
</table>
}
Url of page is:h**p://localhost:41777/Reporti/Reporti
After click Search Button i have this URL
h**p://localhost:41777/Reporti/Reporti?datumOD=01.03.2017&datumDO=02.03.2017
Here is code of controller
public ActionResult Reporti(string filter, DateTime? datumOD, DateTime? datumDO)
{
Session["invoiceFrom"] = datumOD;
Session["invoiceTo"] = datumDO;
return View();
}
public ActionResult reportIZ(DateTime? datumOD, DateTime? datumDO)
{
var smetkis = db.smetkis.Include(s => s.firmi);
return View(smetkis.ToList());
}
public ActionResult Report(DateTime? datumOD, DateTime? datumDO)
{
var ponudis = db.ponudis.Include(s => s.ponudaDets).Where(x => x.odobreno);
return View(ponudis.ToList());
}
My question is, how to implement code in public ActionResult Reporti to filter result between dates.

Just add another condition:
public ActionResult Reporti(DateTime? datumOD, DateTime? datumDO)
{
var ponudis = db.ponudis.Include(s => s.ponudaDets).AsQueryable();
if(datumOD.HasValue) //If we have date - add condition
ponudis = ponudis.Where(x => x.odobreno >= datumOD);
if(datumDO.HasValue) //If we have date - add condition
ponudis = ponudis.Where(x => x.odobreno <= datumDO);
return View(ponudis.ToList());
}
If you need to get data from 2 tables at once you should use Union. But if your tables have different structure you should create separate class like RowViewModel. like this:
public class RowViewModel
{
public int Id {get; set;}
public int DateTime? Odobreno {get; set;}
//your other properties
}
And then in your controller:
public ActionResult Reporti(DateTime? datumOD, DateTime? datumDO)
{
var ponudis = db.ponudis.Include(s => s.ponudaDets).AsQueryable();
var smetkis = db.smetkis.Include(s => s.firmi).AsQueryable();
if(datumOD.HasValue) //If we have date - add condition
{
smetkis = smetkis.Where(x => x.odobreno >= datumOD);
ponudis = ponudis.Where(x => x.odobreno >= datumOD);
}
if(datumDO.HasValue) //If we have date - add condition
{
smetkis = smetkis.Where(x => x.odobreno >= datumOD);
ponudis = ponudis.Where(x => x.odobreno <= datumDO);
}
var res = smetkis.Select(x => new RowViewModel
{
Id = x.ID,
Odobreno = x.odobreno
//other properties if you need
}).Union(ponudis.Select(x => new RowViewModel //note Union
{
Id = x.ID,
Odobreno = x.odobreno
//other properties if you need
}));
return View(res);
}

Related

Display both unavailable and available booking time slot and disable the booked time slots

I want to display all time slots for a selected date and room. I'm using IsBooked property in TimeSlot class to indicate that the time slot is booked.
From the result that I have, it only disables the check box for the last record from the query. I want to disable all the time slots that is in the bookings database so that it cannot be double booked.
In BookingsController:
[HttpGet]
public ActionResult TestTimeSlot(BookingsViewModel searchViewModel)
{
IEnumerable<Booking> _booking = _context.Bookings
.Where(b => b.RoomId == searchViewModel.RoomId)
.Where(b => b.BookDate == searchViewModel.BookDate)
.Include(b => b.Building)
.Include(b => b.Room)
.Include(b => b.TimeSlot)
.OrderBy(b => b.TimeSlotId)
.ToList();
IEnumerable<TimeSlot> _timeSlot = _context.TimeSlots.ToList();
foreach (var slot in _timeSlot)
{
foreach(var book in _booking)
{
if (slot.Id != book.TimeSlotId)
slot.IsBooked = false;
else
slot.IsBooked = true;
}
}
var viewModel = new BookingsViewModel
{
TimeSlots = _timeSlot,
ConfirmedBookings = _booking,
BuildingId = searchViewModel.BuildingId,
RoomId = searchViewModel.RoomId,
BookDate = searchViewModel.BookDate
};
return View(viewModel);
}
In TimeSlot.cs:
public class TimeSlot
{
public byte Id { get; set; }
[Display(Name = "Start Time")]
public TimeSpan StartTime { get; set; }
[Display(Name = "End Time")]
public TimeSpan EndTime { get; set; }
public bool IsBooked { get; set; }
}
In TestTimeSlot.cshtml:
#foreach (var item in Model.TimeSlots)
{
if (item.IsBooked == true)
{
<tr>
<td>
<input type="checkbox" disabled="">
</td>
<td>
#Html.DisplayFor(modelItem => item.StartTime)
</td>
<td>
#Html.DisplayFor(modelItem => item.EndTime)
</td>
</tr>
}
else
{
<tr>
<td>
<input type="checkbox">
</td>
<td>
#Html.DisplayFor(modelItem => item.StartTime)
</td>
<td>
#Html.DisplayFor(modelItem => item.EndTime)
</td>
</tr>
}
}
Result: It only disabled the time slot at 16:30:00 while there are a couple of other records for that selected room and date
I think the problem is that after you've found a booking which matches the timeslot, and have set IsBooked to true, you carry on looking through the list of bookings. Therefore when it comes to the next booking in the list, which doesn't match, the code will set IsBooked to false again! (And hopefully you can see why it works only for the last booking, because there are no other bookings left to reset the record.)
The fix should be simple - when you've found a match, just end the loop using break;. Control will then pass to the line after the end of the foreach, and no more bookings will be tested.
if (slot.Id != book.TimeSlotId)
slot.IsBooked = false;
else {
slot.IsBooked = true;
break;
}

Display data based on year and week number

I am developing an application where the administrator types a Datetime as searching terms to match stamp dates in the database.
I need to change it so the search criteria can be based on year and week number. The scenario is the user enter year and week number in the GetWeekStamp View, which after they post redirects to Stampings view where they display the data based on the entered year and week number.
Model 1:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Aviato.Models
{
public partial class Stamping
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public int UserId { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime Timestamp { get; set; }
[Required]
[StringLength(3)]
public string StampingType { get; set; }
public virtual User User { get; set; }
}
}
Model 2:
using System;
using System.Collections.Generic;
using Aviato.Models;
namespace Aviato.ViewModel
{
public class StampingModel
{
public List<Stamping> Stampings { get; set; }
public DateTime Timestamp { get; set; }
}
}
View (GetWeekStamp):
#model Aviato.Models.Stamping
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h1>Ange Datum</h1>
<p>(ÅÅÅÅ-MM--DD)</p>
#Html.EditorFor(model => model.Timestamp, new { htmlAttributes = new { #class = "form-control" } })
<br/>
<br />
<input type="submit" value="Välj" class="btn btn-default">
<br />
<br />
<div>
#Html.ActionLink("Tillbaka", "Index")
</div>
}
View(Stampings)
#model Aviato.ViewModel.StampingModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h2>Instämplingar</h2>
<p>Du har valt: #Model.Timestamp.Year-#Model.Timestamp.Month-#Model.Timestamp.Day</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Stampings[0].Timestamp)
</th>
<th>
#Html.DisplayNameFor(model => model.Stampings[0].StampingType)
</th>
</tr>
#foreach (var item in Model.Stampings)
{
<tr>
<td>
#Html.DisplayFor(model => item.Timestamp)
</td>
<td>
#Html.DisplayFor(model => item.StampingType)
</td>
</tr>
}
</table>
<p>
#Html.ActionLink("Tillbaka", "GetWeekStamp")
</p>
}
Controller:
public ActionResult GetWeekStamp()
{
return View();
}
[HttpPost]
public ActionResult GetWeekStamp(Stamping model)
{
return RedirectToAction("Stampings", new { model.Timestamp });
}
public ActionResult Stampings(Stamping model)
{
var startTime = model.Timestamp;
var endTime = model.Timestamp.AddDays(1);
var userId = (int)Session["userId"];
var stampings = _db.Stampings.Where(s => s.Timestamp >= startTime && s.Timestamp <= endTime)
.Where(s => s.UserId == userId).ToList();
var stampingModel = new StampingModel();
stampingModel.Stampings = stampings;
stampingModel.Timestamp = model.Timestamp;
return View(stampingModel);
}
I have found this Converter class here in Stack, but I am not sure what to do with it...
Class:
public class DateConverter
{
public static DateTime FirstDateOfWeek(int year, int weekOfYear)
{
var jan1 = new DateTime(year, 1, 1);
var daysOffset = DayOfWeek.Thursday - jan1.DayOfWeek;
var firstThursday = jan1.AddDays(daysOffset);
var cal = CultureInfo.CurrentCulture.Calendar;
var firstWeek = cal.GetWeekOfYear(firstThursday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
var weekNum = weekOfYear;
if (firstWeek <= 1)
{
weekNum -= 1;
}
var result = firstThursday.AddDays(weekNum * 7);
return result.AddDays(-3);
}
}
you can get week number using extension method like this:
public static int GetWeekNumber(this DateTime dateTime)
{
CultureInfo currentCulture = CultureInfo.CurrentCulture;
return currentCulture.Calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
to get a year from DateTime just use:
var datetime = DateTime.Now; //i'm using Now, but you can use the one from Timestamp ...
var year = datetime.Year;
You need to create a model for GetWeekStamp view
using System;
using System.Collections.Generic;
using Aviato.Models;
namespace Aviato.ViewModel
{
public class GetWeekStampModel
{
public int Year { get; set; }
public int WeekNo { get; set; }
}
}
then change GetWeekStamp view code to this so user can enter the year and week number
#model Aviato.ViewModel.GetWeekStampModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h1>Year</h1>
#Html.EditorFor(model => model.Year, new { htmlAttributes = new { #class = "form-control" } })
<br />
<br />
<h1>Week No</h1>
#Html.EditorFor(model => model.WeekNo, new { htmlAttributes = new { #class = "form-control" } })
<br />
<br />
<input type="submit" value="Välj" class="btn btn-default">
<br />
<br />
<div>
#Html.ActionLink("Tillbaka", "Index")
</div>
}
then in GetWeekStamp controller post action method, pass the entered year and week number to Stampings view
[HttpPost]
public ActionResult GetWeekStamp(GetWeekStampModel model)
{
return RedirectToAction("Stampings", new { year = model.Year, weekNo = model.WeekNo });
}
The Timestamp property in StampingModel class should be removed and two new properties Year and WeekNo should be added
using System;
using System.Collections.Generic;
using Aviato.Models;
namespace Aviato.ViewModel
{
public class StampingModel
{
public List<Stamping> Stampings { get; set; }
public int Year { get; set; }
public int WeekNo { get; set; }
}
}
in Stampings controller get action method you can calculate the first date of the week based on year and weekNo using your FirstDateOfWeek method above, then use the results as the startTime and set endTime to six days after startTime
public ActionResult Stampings(int year, int weekNo)
{
var startTime = DateConverter.FirstDateOfWeek(year, weekNo);
var endTime = startTime.AddDays(6);
var userId = (int)Session["userId"];
var stampings = _db.Stampings.Where(s => s.Timestamp >= startTime && s.Timestamp <= endTime)
.Where(s => s.UserId == userId).ToList();
var stampingModel = new StampingModel();
stampingModel.Stampings = stampings;
stampingModel.Year = year;
stampingModel.WeekNo = weekNo;
return View(stampingModel);
}
Finally change this part in Stampings view
<p>Du har valt: #Model.Timestamp.Year-#Model.Timestamp.Month-#Model.Timestamp.Day</p>
to this
<p>Du har valt: #Model.Year-#Model.WeekNo</p>

How to return a list to the controller based on checkbox checked?

I have a table of data in a razor view, to which I added a checkbox for each row in the table.
I'm trying to return the checked list to my post action in the controller.
However the model shows as null on post back.
Model in view..
#model IPagedList<TrackerModel>
Post actionResult in controller....
[HttpPost]
public ActionResult Index(IList<TrackerModel> model)
{
return View(model);
}
The form tag is applied in another as the table is in a partial..
<div id="all-calibrations-grid" class="pull-left tracker-container">
#using (Html.BeginForm(FormMethod.Post))
{
{Html.RenderAction("AllCalibrations");}
}
</div>
Tracker ViewModel..
public class TrackerModel
{
public int Id { get; set; }
public string EquipmentID { get; set; }
public string EquipmentDescription { get; set; }
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime? ExpectedReturnedToCustomer { get; set; }
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime? DateOfCalibration { get; set; }
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime? NextDueDate { get; set; }
public bool StatusChange { get; set; } //01/07/2014
public string Status { get; set; }
public string CustomerName { get; set; }
}
All calibrations ...
[RoleAuthorization(Roles = "Customer User Passive,LTS User Passive")]
public PartialViewResult AllCalibrations(int? page, IPrincipal user)
{
int totalRecords;
// the filter model is fully populated
var filter = (CalibrationFilter)Session["_Filter"];
filter.PageSize = ((CalibrationFilter)Session["_Filter"]).PageSize;
filter.Page = page.HasValue ? page.Value - 1 : 0;
IList<Calibration> calibrationList;
if (user.IsInRole("LTS User Passive"))
{
LtsUser ltsUser = _ltsUserRepo.GetUser(user.Identity.Name);
// access the required data from the calibration repository
calibrationList = _calRepo.GetAllCalibrations(ltsUser.Customers, out totalRecords, filter);
}
else
{
CustomerUser custUser = _custUserRepo.GetUser(user.Identity.Name);
var customer = new List<Customer> { _custRepo.GetCustomer(custUser.Customer.Name) };
// access the required data (for a specific customer) from the calibration repository
calibrationList = _calRepo.GetAllCalibrations(customer, out totalRecords, filter);
}
var customerViewList = Mapper.Map<IList<Calibration>, IList<TrackerModel>>(calibrationList);
IPagedList<TrackerModel> pagedList = customerViewList.ToPagedList(filter.Page, filter.PageSize, totalRecords);
return PartialView("AllCalibrations", pagedList);
}
All Calibrations View...
#using InstrumentTracker.ViewModels.TrackerModels
#using MvcPaging
#model IPagedList<TrackerModel>
#{
Layout = null;
AjaxOptions ajaxOpts = new AjaxOptions
{
UpdateTargetId = "all-calibrations-grid",
HttpMethod = "POST"
};
}
#RenderPage("StatusLegend.cshtml")
<span>Displaying #Model.ItemStart - #Model.ItemEnd of #Model.TotalItemCount Calibrations</span>
<table id="all-calibrations" class="grid tracker-grid">
<colgroup>
<col class="workno-data">
<col class="equipmentId-data">
<col class="equipmentDesc-data">
<col class="calDate-data">
<col class="nextDueDate-data">
<col class="status-data">
</colgroup>
<thead>
<tr>
#* ADDED 23/06/2014 *#
#if (this.User.IsInRole("LTS Admin"))
{
<th id="SelectHeader">
<input type="submit" class="styledbutton" value="Save" /></th>
}
<th>Work<br />No.</th>
<th>ID</th>
<th>Description</th>
<th>Calibrated<br />On</th>
<th>Next<br />Due</th>
<th id="status-header">Status<a id="status-help" href="#">?</a></th>
#*Add the following to <th> tag if ? does not display correctly - style="text-overflow:clip;"*#
#* the customer column is only shown for LTS users since customer only see 1 customers data *#
#if (this.User.IsInRole("LTS User Passive"))
{
<th>Customer</th>
}
</tr>
</thead>
<tbody>
#* iterate through each calibration shown on this page *#
#for (int index = 0; index < Model.Count(); index++)
{
#Html.HiddenFor(m => Model.ElementAt(index).Id)
#Html.HiddenFor(m => Model.ElementAt(index).EquipmentID)
#Html.HiddenFor(m => Model.ElementAt(index).EquipmentDescription)
#Html.HiddenFor(m => Model.ElementAt(index).DateOfCalibration)
#Html.HiddenFor(m => Model.ElementAt(index).NextDueDate)
#Html.HiddenFor(m => Model.ElementAt(index).CustomerName)
<tr>
#*<th name="SelectCells" style="display:none;"><input type="checkbox" name="selectedCals" value="<m => Model.ElementAt(index).Id>"/></th>*#
#* ADDED 23/06/2014 *#
#if (this.User.IsInRole("LTS Admin"))
{
<th>#Html.EditorFor(m => Model.ElementAt(index).StatusChange, new { name = "selectedCals" })</th>
}
#* The work number is a link to the calibration the work no. represents *#
<td>#Html.ActionLink("WN–" + #Html.DisplayFor(m => Model.ElementAt(index).Id), "Index", "CalibrationViewer", new { id = Model.ElementAt(index).Id }, null)</td>
<td>#Html.DisplayFor(m => Model.ElementAt(index).EquipmentID)</td>
<td>#Html.DisplayFor(m => Model.ElementAt(index).EquipmentDescription)</td>
<td>#Html.DisplayFor(m => Model.ElementAt(index).DateOfCalibration)</td>
<td>#Html.DisplayFor(m => Model.ElementAt(index).NextDueDate)</td>
<td>#Html.DisplayFor(m => Model.ElementAt(index).Status)</td>
#* once again only the lts user sees the customer column data *#
#if (this.User.IsInRole("LTS User Passive"))
{
<td>#Html.DisplayFor(m => Model.ElementAt(index).CustomerName)</td>
}
</tr>
}
</tbody>
}
</table>
#* The page navigation for the recently completed table *#
<div class="pager">
#Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount, ajaxOpts).Options(o => o.Action("AllCalibrations"))
</div>
If I remove the IList from the post actionResult, I just get the first selected model.
What am I doin wrong ??
What I do is have a hidden input in the view that holds a list of the selected records and then have that as a parameter on the controller action...
<input id="selectedRecords" name="selectedRecords" type="hidden" />
Populate the hidden input using javascript attached to the checkboxes, i.e. add an id to the hidden input when a checkbox is clicked, then on the controller action you can access it as a string; i think it even puts commas inbetween values automagically, using something like a selectrow function that will loop through the grid and put the selectedrow ids into the hidden input...
$.each(checkedIds, function (value) {
// stuff
});
EDIT:
Forget that each loop and have a read of this example on how to get the selected row data
Then get the ID, and store it in the hidden input, then on post on the controller action you simply get the hidden input value.

Understanding Enumerables and ViewModels

I am trying to learn ASP.NET MVC (C#), and am currently tackling ViewModels. I understand the purpose of ViewModels, and I can get data through to the screen using them, but am having difficulties with understanding their relationship with - another new element for me - interfaces.
I want to achieve the following View:
You can see I have a simple initial insert form for adding a new staff member, with a dropdown for salutations. Following this, there is a second form for editing where I iterate through available staff members, placing their values into relevant input fields, where the salutation dropdown defaults to their relative salutation.
I have two Domain Models / tables, Prm_Staff and Prm_Salutation, which I am accessing (wrong word, I think) via the ViewModel Staff_VM:
public class Staff_VM
{
public int StaffID { get; set; }
public int SalutationID { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public bool Active { get; set; }
public List<Prm_Salutation> AvailableSalutations { get; set; }
}
public class StaffMembers
{
public Staff_VM StaffVm;
public IEnumerable<Staff_VM> ListStaffVms;
}
In my controller:
var activeSalts = (from a in db.Prm_Salutations
where a.Active == true
orderby a.Desc ascending
select a).ToList();
var model = new StaffMembers
{
ListStaffVms = (from a in db.Prm_Staffs
where a.Active == true
orderby a.LName ascending
select new Staff_VM
{
StaffID = a.Prm_StaffID,
SalutationID = a.SalutationID,
FName = a.FName,
LName = a.LName,
Active = a.Active,
AvailableSalutations = activeSalts
}),
StaffVm = new Staff_VM()
{
AvailableSalutations = activeSalts
},
};
return View("StaffMembers", model);
In the View, I refer to that model #model November.ViewModels.StaffMembers:
#*Record New Staff Member*#
<tr>
<td>
#Html.DropDownListFor(
model => model.StaffVm.SalutationID,
Model.StaffVm.AvailableSalutations.Select(option => new SelectListItem
{
Text = option.Desc.ToString(),
Value = option.Prm_SalutationID.ToString()
}
),
"Choose...")
</td>
<td>#Html.EditorFor(model => model.StaffVm.FName)</td>
<td>#Html.EditorFor(model => model.StaffVm.LName)</td>
<td>#Html.EditorFor(model => model.StaffVm.Active)</td>
</tr>
#*Update Existing Staff Members*#
#foreach (var staff in Model.ListStaffVms)
{
<tr>
<td>#Html.HiddenFor(model => staff.StaffID)#Html.ValueFor(model => staff.StaffID) </td>
<td>
#Html.DropDownListFor(
model => staff.SalutationID, staff.AvailableSalutations.Select(option => new SelectListItem
{
Selected = (option.Prm_SalutationID == staff.SalutationID),
Text = option.Desc.ToString(),
Value = option.Prm_SalutationID.ToString()
}
),
"Choose...")
</td>
<td>#Html.EditorFor(model => staff.FName)</td>
<td>#Html.EditorFor(model => staff.LName)</td>
<td>#Html.EditorFor(model => staff.Active)</td>
<td>Delete</td>
</tr>
}
ActionResult:
public ActionResult UpdateStaff(StaffMembers list)
{
if (ModelState.IsValid)
{
foreach (var staffVm in list.ListStaffVms)
{
Prm_Staff staff = db.Prm_Staffs.Find(staffVm.StaffID);
staff.SalutationID = staffVm.SalutationID;
staff.FName = staffVm.FName;
staff.LName = staffVm.LName;
staff.Active = staffVm.Active;
}
db.SaveChanges();
ViewBag.rtrn = "Successfully Updated.";
return RedirectToAction("Parameters", new { param = "Staff Members", rtrn = ViewBag.rtrn });
}
else
{
ViewBag.rtrn = "Failed ! Please try again.";
return RedirectToAction("Parameters", new { param = "Staff Members", rtrn = ViewBag.rtrn });
}
}
EDIT: Updated to show most recent changes
I think you should consider change your ViewModel. Also do something like below:
ViewModel
public class Staff_VM
{
public int ID { get; set; }
public int SalutationID { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public bool Active { get; set; }
}
public class MyViewModel
{
public Staff_VM StaffVm { get; set; }
public List<Staff_VM> ListStaffVms { get; set; }
public List<Prm_Salutation> AvailableSalutations { get; set; }
}
Add_Update_Staff Action
[HttpGet]
public ActionResult Add_Update_Staff()
{
var model = new MyViewModel
{
ListStaffVms = (from a in db.Prm_Staffs
where a.Active == true
orderby a.LName ascending
select new Staff_VM
{
ID = a.Id,
SalutationID = a.SalutationID,
FName = a.FName,
LName = a.LName,
Active = a.Active
}),
AvailableSalutations = (from p in db.Prm_Salutations
where a.Active == true
orderby p.Desc ascending
select p).ToList()
};
return View(model);
}
Update Staff Post
[HttpPost]
public ActionResult Add_Update_Staff(MyViewModel model, string buttonType)
{
if (buttonType == "Insert")
{
if (ModelState.IsValid)
{
//save a new staff info
return RedirectToAction("Index", "Home");
}
}
if (buttonType == "Update")
{
foreach (var staffVm in model.ListStaffVms)
{
// update each record here
}
return RedirectToAction("Index", "Home");
}
model.AvailableSalutations = (from p in db.Prm_Salutations
orderby p.Desc ascending
select p).ToList();
return View(model);
}
View
You may need to add validation for insert and update staff info
#using (Html.BeginForm("Add_Update_Staff", "Staff"))
{
<tr>
<td>
#Html.DropDownListFor(
model => model.StaffVm.SalutationID, Model.AvailableSalutations.Select(option => new SelectListItem
{
Text = option.Desc.ToString(),
Value = option.Prm_SalutationID.ToString()
}
), "Choose...")
</td>
<td>#Html.EditorFor(model => model.StaffVm.FName)</td>
<td>#Html.EditorFor(model => model.StaffVm.LName)</td>
<td>#Html.EditorFor(model => model.StaffVm.Active)</td>
</tr>
<input type="submit" value="Insert" name="buttonType" />
for (int i = 0; i < Model.ListStaffVms.Count(); i++)
{
<tr>
<td>#Html.HiddenFor(m => m.ListStaffVms[i].ID)#Html.ValueFor(m => m.ListStaffVms[i].ID) </td>
<td>
#Html.DropDownListFor(
m => m.ListStaffVms[i].SalutationID, Model.AvailableSalutations.Select(option => new SelectListItem
{
Selected = (option.Prm_SalutationID == Model.ListStaffVms[i].SalutationID),
Text = option.Desc.ToString(),
Value = option.Prm_SalutationID.ToString()
}), "Choose...")
</td>
<td>#Html.EditorFor(model => model.ListStaffVms[i].FName)</td>
<td>#Html.EditorFor(model => model.ListStaffVms[i].LName)</td>
<td>#Html.EditorFor(model => model.ListStaffVms[i].Active)</td>
<td>Delete</td>
<hr />
</tr>
}
<input type="submit" value="Update" name="buttonType" />
}

Count duplicates in C# MVC3 with View

I need a help of displaying the view of comodities, by excluding the duplicate, but adding quantity to the count
E.g.
Name ComodityModel count SellerName
Iphone 3gs 1 Neal
Iphone 4g 1 Jane
Iphone 3gs 1 Neal
Iphone 3gs 1 Jane
Output should be
Name ComodityModel count SellerName
Iphone 3gs 2 Neal
Iphone 4g 1 Jane
Iphone 3gs 1 Jane
I need to filter it by Comodity model and SellerName. I have database and model Comodity
public class Comodity
{
public int ID { get; set; }
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
[Required(ErrorMessage = "Date is required")]
//[DisplayFormat(DataFormatString = "{0:d}")]
[DataType(DataType.Date)]
public DateTime ? RegisterDate { get; set; }
[Required(ErrorMessage = "Comodity Model must be specified")]
public string ComodityModel { get; set; }
[Required(ErrorMessage = "Color must be specified")]
[StringLength(15)]
public string Color { get; set; }
[Required(ErrorMessage = "Price Required")]
[Range(1, 1000, ErrorMessage = "Price must be between $1 and $100")]
[DisplayFormat(DataFormatString = "{0:c}")]
public decimal Price { get; set; }
[Required(ErrorMessage = "Seller name must be specified")]
[StringLength(15)]
public string SellerName { get; set; }
public int CountCom { get; set; }
}
public class ComodityDBContext : DbContext
{
public DbSet<Comodity> Comodities { get; set; }
}
and Controller where I defined Actionresult MyView
public ActionResult MyView(DateTime? startDate, DateTime? endDate, string comModel, string searchString)
{
// if (string.IsNullOrEmpty(comModel))
// {
// return View(comodities);
// }
// else
// {
// return View(comodities.Where(x => x.ComodityModel == comModel));
// }
DateTime dtNow;
dtNow = DateTime.Today;
if (!startDate.HasValue)
{
startDate = new DateTime(dtNow.Year, dtNow.Month, 1);
endDate = startDate.Value.AddMonths(1).AddDays(-1);
}
if (startDate.HasValue && !endDate.HasValue)
{
endDate = (new DateTime(startDate.Value.Year, startDate.Value.Month, 1)).AddMonths(1).AddDays(-1);
}
ViewBag.startDate = startDate.Value.ToShortDateString();
ViewBag.endDate = endDate.Value.ToShortDateString();
var viewDate = from r in db.Comodities
where r.RegisterDate >= startDate.Value && r.RegisterDate <= endDate.Value == true
// orderby r.RegisterDate
select r.RegisterDate;
var SelectListName = new List<string>();
var SelectNameQry = from m in db.Comodities
select m.SellerName;
SelectListName.AddRange(SelectNameQry.Distinct());
ViewBag.searchString = new SelectList(SelectListName);
var comModelLst = new List<string>();
var comModelQry = from d in db.Comodities
orderby d.ComodityModel
select d.ComodityModel;
comModelLst.AddRange(comModelQry.Distinct());
ViewBag.comModel = new SelectList(comModelLst);
var comodities = from m in db.Comodities
select m;
IDictionary<string, IList<string>> dict = new Dictionary<string, IList<string>>();
var queryC = from c in db.Comodities
group c by c.ComodityModel into g
where g.Count() > 1
select new { ComodityModel = g.Key, CCount = g.Count() };
foreach (var item in queryC)
{ // comodities = comodities.Where(item => item.Name && item => item.CCount);
//View("", item.ComodityModel, item.CCount);
// ViewBag(item.ComodityModel, item.CCount);
String key = item.ComodityModel;
if (dict.ContainsKey(key))
{
// add the class name into an existing "string" collection
dict[key].Add(item.ComodityModel);
}
else
{
// instantiate a new "string" collection and add the class name.
dict[key] = new List<string> { item.ComodityModel };
}
int maxCourseCount = 0;
foreach (var k in dict.Keys)
{
int valueCount = dict[k].Count;
if (valueCount > maxCourseCount)
maxCourseCount = valueCount;
}
}
if (!String.IsNullOrEmpty(searchString))
{
comodities = comodities.Where(s => s.SellerName.Contains(searchString));
}
if (startDate.HasValue && endDate.HasValue)
{
comodities = comodities.Where(r => r.RegisterDate >= startDate.Value && r.RegisterDate <= endDate.Value);
}
if (string.IsNullOrEmpty(comModel))
{
return View(comodities);
}
else
{
return View(comodities.Where(x => x.ComodityModel == comModel));
}
}
I am new in MVC and have no idea how to count and make view. Please, help. Also, is there some suggestion about date picking. It is showing incorrectly. I assume that it only comparing the day, not whole day-month-year. Thanks in advance
Finally MyView
#model IEnumerable<SaleCenter.Models.Comodity>
#{
ViewBag.Title = "total";
}
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<h2>total</h2>
<p>
#using (Html.BeginForm()){
<p> startdate:#Html.TextBox("startDate", null, new { #class = "datePicker" })
enddate : #Html.TextBox("endDate", null, new { #class = "datePicker" }) </p>
<p> model: #Html.DropDownList("comModel", "All")
seller: #Html.DropDownList("SearchString", "All")
<input type="submit" value="Total" /></p>
}
</p>
<table>
<tr>
<th>
product name
</th>
<th>
Model
</th>
<th>
seller
</th>
<th>
quantity
</th>
<th>
graphic
</th>
</tr>
#foreach (var item in Model)
{
int w = (int)(2000 * item.CountCom / 100);
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.ComodityModel)
</td>
<td>
#Html.DisplayFor(modelItem => item.SellerName)
</td>
<td>
#Html.DisplayFor(modelItem => item.CountCom)
</td>
<td>
<img src="#Url.Content("~/Content/Images/graph.gif")" width="#w.ToString()px" height="6px" alt="" />
</td>
</tr>
}
</table>
<script type="text/javascript">
$(document).ready(function () {
$('.datePicker').datepicker({ firstDay: 1, dateFormat: 'dd.mm.yy', showOn: 'button',
buttonImage: '/Content/images/calendar.gif',
duration: 0
});
});
</script>
For showing the commodity and it's count in the view. Quick way it to create a anonymous object from your comodities by grouping with name and get it's count. Return this anonymous object as the model to the view.
Better approach is to create ViewModel specific to this purpose, so that you could create a tightly bound view.
Here is a method to plop into your ComodityController.cs file:
private int getComodityCount(string param_Name, string param_ComodityModel, string param_SellerName)
{
return db.Comodity.Where(x => x.Name == param_Name && x.ComodityModel == param_ComodityModel && x.SellerName == param_SellerName).Count();
}
Now, to get the number of duplicates within the Collection of Comodity you call:
int count = getComodityCount("iPhone","3gs","Neal");
What's more, if you change the privacy setting from private to public, you can even call the method from your view like this:
Here is the method changed to public:
public int getComodityCount(string param_Name, string param_ComodityModel, string param_SellerName)
{
return db.Comodity.Where(x => x.Name == param_Name && x.ComodityModel == param_ComodityModel && x.SellerName == param_SellerName).Count();
}
and here is the code for your View:
#{
int count = new ComodityController().getComodityCount("iPhone","3gs","Neal");
}
I hope this helps. The Where(linq) method is REALLY handy for database querying.

Categories

Resources