Passing date value from view to controller - asp.net-mvc

In my model I have
[DataType(DataType.Date)]
public DateTime SaleDate { get; set; }
public virtual Customer Customers { get; set; }
in my controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include="SaleID,shippingBillNo,CustomerID,PlantID,Quantity,SaleDate")] Sale sale)
{
if (ModelState.IsValid)
{
var strddlValue = Convert.ToInt32(Request.Form["CustomerID"]);
var saledate = Convert.ToDateTime(Request.Form["mySaleDate"]);
In my View
#using (Html.BeginForm(null, null, FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Sale</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.CustomerID, "CustomerID", new {
#class = "control-label col-md-2" })
<div class="col-md-10">
#Html.Hidden("CustomerText")
#Html.DropDownList("CustomerID", String.Empty)
#Html.ValidationMessageFor(model => model.CustomerID)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SaleDate, new { #class = "control-
label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SaleDate, new { Name =
"mySaleDate"})
#Html.ValidationMessageFor(model => model.SaleDate)
</div>
</div>
and the JavaScript for the DateTimePicker is:
<script type="text/javascript">
$(function () {
$('#SaleDate').datetimepicker({
format: "DD/MM/YYYY"
}).on('dp.change', function (e) {
$(this).data('DateTimePicker').hide();
});
});
I succeed to pass the CustomerID to the controller. No Problem with that. Instead of passing the date I pick in the editofor with the DataTimePicker helper I get a meaningless value of '01/01/0001'. What am I doing wrong?

Related

One model for two submit buttons in ASP.NET MVC

I have a form on my view:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.DateFrom, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateFrom, new { htmlAttributes = new { #class = "form-control date-picker" } })
#Html.ValidationMessageFor(model => model.DateFrom, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DateTo, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateTo, new { htmlAttributes = new { #class = "form-control date-picker" } })
#Html.ValidationMessageFor(model => model.DateTo, "", 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" formAction=#Url.Action("CreateReport") />
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EMail, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EMail, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EMail, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Send to email" class="btn btn-default" formAction=#Url.Action("SendEmail") />
</div>
</div>
</div>
}
As you can see I have two butons, first button call CreateReport action and than Send button call SendEmail action. I want to create report and then send this report by e-mail.
Here is my controller actions:
public ActionResult Index()
{
Report
report=ReportRepository.GetReport(DateTime.Parse("02.08.1996"), DateTime.Parse("07.08.1996"));
return View(report);
}
public ActionResult CreateReport(Report report)
{
report = ReportRepository.GetReport(report);
return View("Index", report);
}
public ActionResult SendEmail(Report report)
{
return View("Index", report);
}
And my model class:
public class Report
{
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public List<OrderDetails> Orders { get; set; }
[Display(Name = "Email address")]
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string EMail { get; set; }
}
So I mean that I fill Orders list in CreateReport action and display it and after it I press "Send to email" button, that's call "SendEmail" action, where I save Orders list to file and send it.
The problem is that in "SendEmail" action List is null.
How can I fix it?
The simplest way that I could think of is to remove your submit action for create report and handle this with ajax call. So that you will have only one submit action.
Or else you can try with 2 forms in your View.
Personally, I prefer the 1st option.
I'v found a solution. The solution is not to pass model to controller but store my List in Session. Like this:
public ActionResult Index()
{
Report report=ReportRepository.GetReport(DateTime.Parse("02.08.1996"), DateTime.Parse("07.08.1996"));
Session["Orders"] = report.Orders;
return View(report);
}
public ActionResult CreateReport(Report report)
{
report = ReportRepository.GetReport(report);
Session["Orders"] = report.Orders;
return View("Index", report);
}
public ActionResult SendEmail(Report report)
{
List<OrderDetails> orders = (List<OrderDetails>)Session["Orders"];
report.Orders = orders;
return View("Index", report);
}

How do I create a new db entry and populate the foreign key based on autocomplete selection of that foreign key object?

I have a ASP.NET MVC application i am developing, and have a repair model that includes a foreign key to a serial number model. In my view i have a typeahead jquery doing a autocomplete search through database to allow the user to select a serial number already in the database. I then have fields to fill out new information that will populate the repair table. I cannot seem to get the selected SerialNumber.Id to populate in the Repair.SerialNumber_Id from the selected serial number.
my view:
#model EntityTestApp.Models.Repair
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Repair</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.RepairDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.RepairDate, new {htmlAttributes = new { #class = "form-control", #Value = DateTime.Now.ToShortDateString() } })
#Html.ValidationMessageFor(model => model.RepairDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SerialNumber, htmlAttributes: new { #class = "control-label col-md-2"})
<div class="col-md-10">
<input id="serialNumberTextBox" type="text" value="" class="form-control" />
#Html.ValidationMessageFor(model => model.SerialNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CustomerComplaint, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(model => model.CustomerComplaint, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CustomerComplaint, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.IssueFound, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(model => model.IssueFound, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.IssueFound, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.RepairActionTaken, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(model => model.RepairActionTaken, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.RepairActionTaken, "", 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>
#section scripts{
<script>
$(document).ready(function () {
var SerialNumbers = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('Number'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/api/serialnumbers?query=%QUERY',
wildcard: '%QUERY'
}
});
$('#serialNumberTextBox').typeahead({
highlight: true
}, {
name: 'SerialNumbers',
display: 'Number',
source: SerialNumbers
}).on("typeahead:select", function (e, SerialNumber) {
//alert(serialNumberTextBox.value)
});
});
</script>
}
my Controller action to create a new repair entry:
// GET: Repairs/Create
public ActionResult Create()
{
return View();
}
// POST: Repairs/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Repair repair)
{
if (ModelState.IsValid)
{
db.Repairs.Add(repair);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(repair);
}
And my repair model:
public class Repair
{
public int Id { get; set; }
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime RepairDate { get; set; }
public SerialNumber SerialNumber { get; set; }
public string CustomerComplaint { get; set; }
public string IssueFound { get; set; }
public string RepairActionTaken { get; set; }
}
Ok, several hair pulling nights later i figured it out. I had to add a hidden field to hold the value for the foreign key and assign that value based on the 'typeahead' javascript autocomplete selection with "document.getElementById('').
Works like a charm. Thanks for the help!
-Chris

Showing RDLC report inside asp.net mvc 5 application

I have created following view form to filter results ,
also I have created following aspx web-form to generate report
Now I want to once I click Generate Report button in view form(1st image) I should be able to pass parameters to text boxes
Type
Category
Subsidary
Country
Date
generate results in web-form and show Microsoft report wizard(RDLC) like 2nd image .
I have done these things separately, I want to link those together
1
Create a model with the filter properties but add a datatable for dataset in report.rdlc for example
public class paramsModel
{
public string typeRep {get; set;}
public DateTime dateRep {get; set;}
public DataTable dataReport {get; set;}
}
2
In your Controller create the ActionResult for the View
public ActionResult showReport()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult showReport(paramsModel paramsRep)
{
if (ModelState.IsValid)
{
paramsRep.dataReport = LocalData.GetDataFromDb(paramsRep.typeRep, paramsRep.dateRep);
}
return View(paramsRep);
}
3
In your View
#model yourproyect.models.paramsModel
#{
ViewBag.Title = "Report page";
var settings = new ControlSettings
{
UseCurrentAppDomainPermissionSet = true,
EnableHyperlinks=true
};
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Report filters</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.typeRep , new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.typeRep , ModelMetadata.FromLambdaExpression(model => model.typeRep , ViewData).EditFormatString, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.typeRep )
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.dateRep , new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.dateRep , ModelMetadata.FromLambdaExpression(model => model.dateRep , ViewData).EditFormatString, new { #class = "form-control datepicker" })
#Html.ValidationMessageFor(model => model.dateRep )
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#if (Model != null)
{
<div >
#Html.MvcReportViewer("Reports/YourReport.rdlc").ProcessingMode(ProcessingMode.Local).LocalDataSource("DataSet1", Model.dataReport).ControlSettings(settings).Attributes(new { Style = "width:100%; border:none; height: 87vh;" }).Method(FormMethod.Post)
</div>
}
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$('.datepicker').datepicker({
dateformat: "#System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.ToLower()",
language: "es",
autoclose: true,
showAnim: 'blind',
highlightWeek: true
}); //Initialise any date pickers
</script>
}

Bind Checkboxlist to model

I'm working on an app for a cycling team. I have to add riders to a ride. To do this I want the user te select the date of a ride, select a value for the point of this ride an then have a list of the members of the team where the user selects which member participated on the ride.
It works fine until I post the form. when I debug my model in the controler the list of Riders in de model counts 4 riders (which is correct as I have 4 riders in my Db for testing) but the riders are null when I check the list.
Can anyone help me, I dont know what I'm doing wrong.
this are the viewmodels I use:
public class RiderViewModel
{
public string Id { get; set; }
public string FulllName { get; set; }
public bool IsChecked { get; set; }
}
public class RideViewModel
{
public string RideId { get; set; }
[Display(Name = "Datum")]
[DataType(DataType.Date)]
[Required(ErrorMessage = "Datum is verplicht")]
public DateTime Date { get; set; }
[Display(Name = "Aantal punten")]
[Required(ErrorMessage = "Een waarde voor het puntenaantal is verplicht")]
public int Punten { get; set; }
[Display(Name = "Leden")]
public List<RiderViewModel> Riders { get; set; }
}
this is my controler:
//POST Rides/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(RideViewModel model)
{
if (ModelState.IsValid)
{
var db = new ApplicationDbContext();
var riders = new List<ApplicationUser>();
foreach(RiderViewModel r in model.Riders)
{
var user = db.Users.FirstOrDefault(u => u.Id == r.Id);
if(user == null)
{
ModelState.AddModelError(string.Empty, "Er is een Fout opgetreden bij het selecteren van de leden. contacteer de systeembeheerder indien het probleem blijft bestaan");
return View(model);
}
riders.Add(user);
}
var ride = new Ride
{
Date = model.Date,
Punten = model.Punten,
Riders = riders
};
db.Rides.Add(ride);
db.SaveChanges();
return RedirectToAction("Index", "AdminPanel");
}
return View(model);
}
and this is the view:
using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Ride</h4>
<hr />
<div class="form-group">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Punten, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Punten, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Punten, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Leden", htmlAttributes: new { #class = "control-label col-md-2"})
<div class="col-md-10">
#for (var i = 0; i < Model.Riders.Count(); i++)
{
<div class="col-md-10">
#Html.HiddenFor(model => model.Riders[i])
#Html.CheckBoxFor(model => model.Riders[i].IsChecked)
#Html.LabelFor(model => model.Riders[i].IsChecked, Model.Riders[i].FulllName)
</div>
}
</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>
}
Thanx a lot.
grtz Jeff
You can use a EditorTemplate for this, just add a new file in the EditorTemplates folder named RiderViewModel :
#model RiderViewModel
<div class="col-md-10">
#Html.HiddenFor(model => model.Id)
#Html.CheckBoxFor(model => model.IsChecked)
#Html.LabelFor(model => model.IsChecked, Model.FulllName)
</div>
Then in the view just call the EditorFor:
#Html.EditorFor(m => m.Riders)
Your usage of
#Html.HiddenFor(model => model.Riders[i])
is creating a hidden input for a complex property which is typeof RiderViewModel. If you inspect the html, it will be something like
<input type="hidden" id="Riders_0_" name="Riders[0]" value="someAssembly.RiderViewModel" />
When you submit, the DefaultModelBinder tries to set model.Riders[0] to the value someAssembly.RiderViewModel which fails and so model.Riders[0] is null
Assuming you want to generate a hidden input for the ID property, change it to
#Html.HiddenFor(model => model.Riders[i].ID)

How do I pass a ViewModel to an Edit Action in ASP.NET MVC 5

I'm learning about using ViewModels to pass information from the view to the controller and vice versa. I have my create action, view, and viewmodel working perfectly but I'm having trouble with the edit one. I get the error:
The model item passed into the dictionary is of type 'CatVM.Models.Cat', but this dictionary requires a model item of type 'CatVM.Models.EditCatViewModel'.
Here is my code:
Controller Method
// GET: /Cats/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Cat cat = unitOfWork.CatRepository.GetByID(id);
if (cat == null)
{
return HttpNotFound();
}
return View(cat);
}
View
#model CatVM.Models.EditCatViewModel
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Cat</h4>
<hr />
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Color, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Color)
#Html.ValidationMessageFor(model => model.Color)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FurLength, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FurLength)
#Html.ValidationMessageFor(model => model.FurLength)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Size, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Size)
#Html.ValidationMessageFor(model => model.Size)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
EditCatViewModel
public class EditCatViewModel
{
public int ID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[StringLength(50)]
public string Color { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Fur Type")]
public string FurLength { get; set; }
[StringLength(50)]
public string Size { get; set; }
}
}
That's because the item you receive from CatRepository.GetByID(id); is of type Cat, not EditCatViewModel.
You can bypass this by constructing a new viewmodel from this object:
Cat cat = unitOfWork.CatRepository.GetByID(id);
var viewModel = new EditCatViewModel {
Name = cat.Name,
Color = cat.Color,
FurLength = cat.FurLength,
Size = cat.Size
};
return View(viewModel);
Alternatively you could construct implicit or explicit casting methods or use a mapping tool like AutoMapper.
Your return view should be of type CatVM.Models.EditCatViewModel now your returning a Cat
return View(cat);
transform your model in a view model and pass this object back to the view

Resources