I'm trying to format a price label so the price is always in the 0.00 format and I saw a similar question that used similar code as mine below. I'm getting an object reference not set to an instance of an object error and I know that it is because I am calling Model.Price but I'm very new to MVC and I don't understand how I set Model.Price before the page is loaded.
#Html.LabelFor(model => model.Price, "0.00", new { id = "priceLabel", Value = String.Format("{0:C}", Model.Price) })
Here is the Controller code:
[HttpGet]
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
// set the paper style list
List<SelectListItem> styles = new List<SelectListItem>();
ViewBag.paperStyle = new SelectList(styles, "Value", "Text");
// set the subject list
List<SelectListItem> subjects = new List<SelectListItem>();
ViewBag.subject = new SelectList(subjects, "Value", "Text");
// set the number of pages list
List<SelectListItem> numberOfPages = new List<SelectListItem>();
ViewBag.Urgency = new SelectList(urgency, "Value", "Text");
// set the document type list
List<SelectListItem> documentTypes = new List<SelectListItem>();
ViewBag.documentType = new SelectList(documentTypes, "Value", "Text");
// set the academic level list
List<SelectListItem> academicLevel = new List<SelectListItem>();
ViewBag.academicLevel = new SelectList(academicLevel, "Value", "Text");
// set the number of sources list
List<SelectListItem> numberOfSources = new List<SelectListItem>();
ViewBag.numberOfSources = new SelectList(numberOfSources, "Value", "Text");
// set the currency list
List<SelectListItem> currencies = new List<SelectListItem>();
currencies.Add(new SelectListItem() { Text = "$", Value = "USD", Selected = true });
currencies.Add(new SelectListItem() { Text = "£", Value = "GBP", Selected = false });
currencies.Add(new SelectListItem() { Text = "€", Value = "EUR", Selected = false });
ViewBag.currency = new SelectList(currencies, "Value", "Text");
return View();
}
[HttpPost]
public ActionResult Contact(WritingAppModel c)
{
if (ModelState.IsValid)
{
// send the email and process the payment
// if payment is ready then send email
if (isPaymentReady())
{
// send email
}
}
return View();
}
public class modelData
{
public string documentType { get; set; }
public string numberOfPages { get; set; }
public string urgency { get; set; }
}
public JsonResult getNewPrice(modelData dropdownValues)
{
// check for urgency first since that is the base price
if (dropdownValues.urgency != null)
{
currentPrice = Convert.ToDecimal(dropdownValues.urgency);
if (dropdownValues.documentType != null)
{
currentPrice = currentPrice + Convert.ToDecimal(dropdownValues.documentType);
if (dropdownValues.numberOfPages != null)
{
currentPrice = currentPrice * Convert.ToInt16(dropdownValues.numberOfPages);
}
}
}
// do something with value and return a decimal
return Json(new { currentPrice = currentPrice }, JsonRequestBehavior.AllowGet);
}
Here is the View code:
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<div class="row">
#Html.LabelFor(model => model.Name, "Name:")
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="row">
#Html.LabelFor(model => model.Email, "Email:")
#Html.TextAreaFor(model => model.Email, new { id = "email" })
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="row">
#Html.LabelFor(model => model.Topic, "Topic:")
#Html.EditorFor(model => model.Topic)
#Html.ValidationMessageFor(model => model.Topic)
</div>
<div class="row">
#Html.LabelFor(model => model.Subject, "Subject:")
#Html.DropDownListFor(model => model.Subject, (SelectList)ViewBag.subject, "--Select--", new { id = "subjectList" })
</div>
<div class="row">
#Html.LabelFor(model => model.Style, "Style:")
#Html.DropDownListFor(model => model.Style, (SelectList)ViewBag.paperStyle, "--Select--", new { id = "paperStyleList" })
</div>
<div class="row">
#Html.LabelFor(model => model.DocumentType, "Document Type:")
#Html.DropDownListFor(model => model.DocumentType, (SelectList)ViewBag.documentType, "--Select--", new { id = "documentTypeList" })
</div>
<div class="row">
#Html.LabelFor(model => model.AcademicLevel, "Academic Level:")
#Html.DropDownListFor(model => model.AcademicLevel, (SelectList)ViewBag.academicLevel, "--Select--", new { id = "academicLevelList" })
</div>
<div class="row">
#Html.LabelFor(model => model.NumberOfPages, "Number of Pages/Words:")
#Html.DropDownListFor(model => model.NumberOfPages, (SelectList)ViewBag.numberOfPages, "--Select--", new { id = "numberOfPagesList" })
</div>
<div class="row">
#Html.LabelFor(model => model.NumberOfSources, "Number of Sources:")
#Html.DropDownListFor(model => model.NumberOfSources, (SelectList)ViewBag.numberOfSources, "--Select--", new { id = "numberOfSourcesList" })
</div>
<div class="row">
#Html.LabelFor(model => model.Urgency, "Urgency:")
#Html.DropDownListFor(model => model.Urgency, (SelectList)ViewBag.urgency, "--Select--", new { id = "urgencyList" })
</div>
<div class="row">
#Html.LabelFor(model => model.Spacing, "Spacing:")
#Html.RadioButtonFor(model => model.Spacing, "Single") Single
#Html.RadioButtonFor(model => model.Spacing, "Double") Double
</div>
<div class="row">
#Html.LabelFor(model => model.Requirements, "Requirements:")
#Html.TextAreaFor(model => model.Requirements)
</div>
<div class="row">
#Html.DropDownListFor(model => model.Currency, (SelectList)ViewBag.currency, null, new { id = "currencyList" })
<h2>
#Html.LabelFor(model => model.Price, "{0:C}", new { id = "priceLabel" })
</h2>
<input type="submit" value="Submit" />
<input type="reset" value="Reset" />
</div>
}
I'm not sure what the controller looks like, but take this test version...
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new Product {Price = 9.99m};
return View(model);
}
}
I've created a Product class as an example..
public class Product
{
public decimal Price { get; set; }
}
Your view will then need to reference the model.
#model WebApplication2.Controllers.Product
#Html.LabelFor(model => model.Price, new { id = "priceLabel" })
#Html.TextBoxFor(model => model.Price, new { id = "priceLabel",
Value = String.Format("{0:C}", Model.Price) })
You can see from the controller where the model is built and passed to the view.
var model = new Product {Price = 9.99m};
return View(model);
The LabelFor will generate a label for the actual property, not the value for it.
EDIT: Based on comment.
If you only want to display the property...
#String.Format("{0:C}", Model.Price)
or. as Steve suggested...
Model:
[DisplayFormat(DataFormatString = "{0:C}")]
public decimal Price { get; set; }
View
#Html.DisplayFor(model => model.Price)
Related
I want to send my EmailFormModel, which contains the Ressurs-list, to the controller where i want to do stuff with it. However I'm never able to access the values in my EmailFormModel in my controller. I tried to overcome this problem by using Sessions, but still it doesnt work.
The list Ressurs contains several Ressursbehov, but there is never more than one EmailFormModel.
My controller
namespace WebApplication6.Controllers
{
public class AppController : Controller
{
const string SESSION_SAVED_MODEL = "savedModel";
[HttpGet]
public ActionResult Index()
{
Session[SESSION_SAVED_MODEL] = new EmailFormModel();
return View(Session[SESSION_SAVED_MODEL]);
}
public ActionResult Sent()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Index(EmailFormModel model)
{
//other irrelevant code
if (Request.Params["Ekstra_Ressurs"] != null)
{
model.Ressurs.Add(new RessursBehov());
Session[SESSION_SAVED_MODEL] = model;
}
}
return View(model);
}
}
My model
namespace WebApplication6.Models
{
public class EmailFormModel
{
[Required, Display(Name = "Prosjektnummer")]
public string Prosjektnummer { get; set; }
[Required, Display(Name = "Prosjektnavn")]
public string Prosjektnavn { get; set; }
[Required, Display(Name = "Prosjekttype")]
public string Prosjekttype { get; set; }
[Required, Display(Name = "Prosjektleder")]
public string Prosjektleder { get; set; }
public List<RessursBehov> Ressurs = new List<RessursBehov>()
{
new RessursBehov() };
}
public class RessursBehov
{
[Required, Display(Name = "Ressurstype")]
public string Ressurstype { get; set; }
[Required, Display(Name = "Navn på ressurs")]
public string Navn_På_Ressurs { get; set; }
[Required, Display(Name = "Ukenummer")]
public int? Ukenummer { get; set; }
[Required, Display(Name = "Antall timer")]
public int? Antall_Timer { get; set; }
[Required, Display(Name = "Antall uker")]
public int? Antall_Uker { get; set; }
}
}
}
My View
#model WebApplication6.Models.EmailFormModel
#{
ViewBag.Title = "Registrer nytt prosjekt";
List<SelectListItem> prosjektTypeListe = new List<SelectListItem>()
{
new SelectListItem { Text = "Prosjekt", Value = "Prosjekt" },
new SelectListItem { Text = "Forvaltning", Value = "Forvaltning" }
};
List<SelectListItem> ressurstypeliste = new List<SelectListItem>()
{
new SelectListItem { Text = "utvikler", Value = "utvikler" },
new SelectListItem { Text = "frontendutvikler", Value = "frontendutvikler" },
new SelectListItem { Text = "epi-utvikler", Value = "epi-utvikler" },
new SelectListItem { Text = "webnodesutvikler", Value = "webnodesutvikler" },
new SelectListItem { Text = "designer", Value = "designer" },
new SelectListItem { Text = "rådgiver", Value = "rådgiver" },
new SelectListItem { Text = "prosjektleder", Value = "prosjektleder" }
};
}
<div class="title">
<div class="text-center">
<h2>#ViewBag.Title</h2>
</div>
</div>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="rows">
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjektnummer, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => m.Prosjektnummer, new { #class = "html_label" })
#Html.ValidationMessageFor(m => m.Prosjektnummer)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjektnavn, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => m.Prosjektnavn, new { #class = "html_label" })
#Html.ValidationMessageFor(m => m.Prosjektnavn)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjekttype, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.DropDownListFor(m => m.Prosjekttype, prosjektTypeListe, "-- Velg Prosjekttype --", new { #class = "dropdown" })
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjektleder, new { #class = "col-md-1 text-center" }) <!--tar inn m som parameter og returnerer m.prosjektleder-->
<div class="col-md-7">
#Html.TextBoxFor(m => m.Prosjektleder, new { #class = "html_label" })
#Html.ValidationMessageFor(m => m.Prosjektleder)
</div>
</div>
#for (var i = 0; i < Model.Ressurs.Count; i++)
{
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Ressurstype, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.DropDownListFor(m => Model.Ressurs[i].Ressurstype, ressurstypeliste, "-- Velg ressurstype --", new { #class = "dropdown" })
</div>
</div>
<div class="row">
<div class="col-md-3"></div>
#Html.LabelFor(m => Model.Ressurs[i].Navn_På_Ressurs, new { #class = "col-md-2 text-right" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Navn_På_Ressurs, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Navn_På_Ressurs)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Ukenummer, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Ukenummer, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Ukenummer)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Antall_Timer, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Antall_Timer, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Antall_Timer)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Antall_Uker, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Antall_Uker, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Antall_Uker)
</div>
</div>
}
<br />
<div class="row">
<div class="col-md-5"></div>
<div class="col-md-2">
<input type="submit" class="btn btn-default" value="Legg til ressurser" name="Ekstra_Ressurs" />
</div>
<div class="col-md-2">
<input type="submit" class="btn btn-primary" value="Send inn mail" name="Sendknapp" />
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
In order to reach model in HttpPost Index action
1) You should pass EmailFormModel type model to View in the GET Index action method.
EmailFormModel model = new EmailFormModel();
Session[SESSION_SAVED_MODEL]=model;
return View(model);
2) You should use Model at the lambda expressions
#Html.TextBoxFor(m => Model.Prosjektleder, new { #class = "html_label" })
change all ms with Model.
All you have to do is add #Name in html attribute then you wont need to use session also .
#Html.DropDownListFor(m => m.Prosjekttype, prosjektTypeListe , "-- Velg Prosjekttype --", new { #class = "dropdown" , #Name = "Prosjekttype" })
I have the following error staring me in the face.
The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies.game_04BC2EA428E3397C72CED2755A5A78B93F676BBC970F6B9A8635AD53B08FEBCB', but this dictionary requires a model item of type 'TeamBuildingCompetition.ViewModels.EditGameVM'
I have an ASP.NET NVC 5 intranet application. I created an edit view from a view model to update contents of my database. Content of the database in question is an html content which was posted in by a rich text editor. When I load the edit view, it shows the above error.
Below is my edit view:
#model TeamBuildingCompetition.ViewModels.EditGameVM
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout_new.cshtml";
}
<script>
tinymce.init({ selector: '#description' });
tinymce.init({ selector: '#gameRule' });
</script>
#using (Html.BeginForm("Update", "Game", FormMethod.Post))
{
#Html.AntiForgeryToken()
<section id="middle">
<div class="container">
<div class="form-horizontal">
<div class="center"><h1>Edit Games </h1></div>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.gameID)
<div class="form-group">
#Html.LabelFor(model => model.gameName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-8">
#Html.EditorFor(model => model.gameName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.gameName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.description, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-8">
#Html.EditorFor(model => model.description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.description, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.gameRule, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-8">
#Html.EditorFor(model => model.gameRule, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.gameRule, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.gamePicture, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-8">
#Html.TextBoxFor(model => model.gamePicture, new { #type = "file", #name = "gamePicture" })
</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>
</section>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Below is the View Model for the Edit View:
namespace TeamBuildingCompetition.ViewModels
{
public class EditGameVM
{
public int gameID { get; set; }
[Required]
[Display(Name = "Game Name")]
public string gameName { get; set; }
[Required][AllowHtml]
[Display(Name = "Description")]
public string description { get; set; }
[Required]
[AllowHtml]
[Display(Name = "Game Rules")]
public string gameRule { get; set; }
[Display(Name = "Game Picture")]
public string gamePicture { get; set; }
}
}
And finally, here's the controller to do the update:
public ActionResult Update(EditGameVM model)
{
try {
game objGame = new game
{
gameID = model.gameID,
gameName = model.gameName,
description = model.description,
gameRule = model.gameRule,
gamePicture = model.gamePicture.ToString()
};
objBs.gameBs.Update(objGame);
TempData["Msg"] = "Created Successfully!";
return RedirectToAction("Edit");
}
catch (DbEntityValidationException dbEx)
{
var sb = new StringBuilder();
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
sb.AppendLine(string.Format("Entity:'{0}' Property: '{1}' Error: '{2}'",
validationErrors.Entry.Entity.GetType().FullName,
validationError.PropertyName,
validationError.ErrorMessage));
}
}
//throw new Exception(string.Format("Failed saving data: '{0}'", sb.ToString()), dbEx);
TempData["Msg"] = sb.ToString();
return RedirectToAction("Edit");
}
}
Here's my Get Method:
public ActionResult Edit(int id = 0)
{
if (id == 0)
{
id = 1;
}
var gameList = objBs.gameBs.GetByID(id);
return View(gameList);
}
I will appreciate all effort to resolving this.
You do not send your model to view, so you caught an error. It is possible to do by this way:
As you use some temporary storage mechanisom like TempData
TempData["Msg"] = objGame;
return RedirectToAction("Edit");
Then just read it in your GET Action method again of your View.
public ActionResult Edit()
{
//Here you should cast your TempData to EditGameVM:
EditGameVM receivedModel=TempData["Msg"] as EditGameVM;
//To take data from TempData["Msg"], you should use receivedModel object:
string gameID=receivedModel.gameID;
string gameName=receivedModel.gameName;
return View(receivedModel);
}
TempData uses Session object behind the scene to store the data. But once the data is read the data is terminated.
I failed to pass the model to my view hence, the above error. After careful examination of my code, I did the following according to https://stackoverflow.com/users/3559349/stephen-muecke advice. All credit goes to this great guy.
public ActionResult Edit(int id = 0)
{
if (id == 0)
{
id = 1;
}
var gameList = objBs.gameBs.GetByID(id);
EditGameVM model = new EditGameVM
{
gameID = id,
gameName = gameList.gameName,
gamePicture = gameList.gamePicture,
gameRule = gameList.gameRule,
description = gameList.description
};
return View(model);
}
I have an asp.net mvc 5 webapp, I want to get a DropDownListFor and add a condition to it.
In the next view I want to display in the DropDownList only Cars where Cars.ClientId==model.ClientId . So what can I add to the SelectListItem to get that?
I need something like this (which is not working):
Cars = db.Cars.Select(c => new SelectListItem() { Text = c.Licence, Value = c.Id.ToString() }).ToList().Where(item=>item.ClientId== id)
Here is the wiew:
#model BRMSWebApp.Models.CreateContractModel
#{
ViewBag.Title = "Ajouter"; }
<h2>Ajouter</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.ClientId)
<div class="form-horizontal">
<h4>Contrat</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.StartDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StartDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.StartDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AnnualPrice, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.AnnualPrice, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.AnnualPrice, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Car, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(c => c.CarId, Model.Cars)
#Html.ValidationMessageFor(model => model.CarId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ContractType, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(c => c.ContractTypeId, Model.ContractTypes)
#Html.ValidationMessageFor(model => model.ContractTypeId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Ajouter" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Retour à la liste", "Index")
</div>
<script type="text/javascript">
$(document).ready(function () {
//$("#StartDate").datepicker($.datepicker.regional["fr"]);
$("#StartDate").datepicker({
changeMonth: true,
changeYear: true
});
});
This is the model CreateContractModel:
namespace BRMSWebApp.Models
{
public class CreateContractModel
{
public int Id { get; set; }
public DateTime? StartDate { get; set; }
public float? AnnualPrice { get; set; }
public Car Car { get; set; }
public Client Client { get; set; }
public ContractType ContractType { get; set; }
public int? CarId { get; set; }
public int? ContractTypeId { get; set; }
public int? ClientId { get; set; }
public List<SelectListItem> Cars { get;set; }
public List<SelectListItem> ContractTypes { get; set; }
public CreateContractModel()
{
this.Cars = new List<SelectListItem>();
this.ContractTypes = new List<SelectListItem>();
}
}
}
And here is the controller:
// GET: Contracts/Create
public ActionResult Create(int id)
{
db.Cars.Select(c => new SelectListItem() { Text = c.Licence, Value = c.Id.ToString() }).ToList();
var contractModel = new CreateContractModel()
{
ClientId = id,
Cars = db.Cars.Select(c => new SelectListItem() { Text = c.Licence, Value = c.Id.ToString() }).ToList(),
ContractTypes = db.ContractTypes.Select(c => new SelectListItem() { Text = c.Name, Value = c.Id.ToString() }).ToList()
};
return View(contractModel);
}
This is the wrong part
Cars = db.Cars
.Select(c => new SelectListItem()
{
Text = c.Licence,
Value = c.Id.ToString()
}).ToList()
.Where(item=>item.ClientId== id)
First get the filtered records from database then use it.
Cars = db.Cars
.Where(item=>item.ClientId== id)
.Select(c => new SelectListItem()
{
Text = c.Licence,
Value = c.Id.ToString()
});
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
I'm still learning MVC and am confused. I am converting a windows application for CRUD with a database to an MVC website. I got an entire ViewModel's CRUD working that uses dropdownlist's already and the code is identical but throwing object reference not set errors with it in another page.
Controller
public ActionResult Create()
{
var shiftsEmployees = new ShiftsEmployeesViewModel();
var oEmployees = new CEmployees();
oEmployees.GetActiveEmployees();
shiftsEmployees.Employees = oEmployees;
return View(shiftsEmployees);
}
// POST: Shifts/Create
[HttpPost]
public ActionResult Create(ShiftsEmployeesViewModel shiftsEmployees)
{
try
{
shiftsEmployees.InsertShift();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
View
#model StatTracker.ASPMVC.ViewModels.ShiftsEmployeesViewModel
#{
ViewBag.Title = "Add Shift";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal text-center">
#Html.ValidationSummary(true, "", new {#class = "text-danger"})
<div class="form-group">
<div class="input-group date col-md-12">
#Html.LabelFor(model => model.Shift.Date, new {#class = "control-label"})
#Html.EditorFor(model => model.Shift.Date, new {#class = "form-control datepicker", placeholder = "Pick a date"})
#Html.ValidationMessageFor(model => model.Shift.Date, "", new {#class = "text-danger"})
#Html.LabelFor(model => model.Employee.FullName, new {#class = "control-label"})
#Html.DropDownListFor(model => model.Employee.Id, new SelectList(Model.Employees.Employees, "Id", "FullName", Model.Employee), null, null)
#Html.ValidationMessageFor(model => model.Employee.Id, "", new {#class = "text-danger"})
#Html.LabelFor(model => model.Shift.Hours, new {#class = "control-label"})
#Html.EditorFor(model => model.Shift.Hours, new {#class = "form-control", placeholder = "Hours worked"})
#Html.ValidationMessageFor(model => model.Shift.Hours, "", new {#class = "text-danger"})
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<input type="submit" value="Add Shift" class="btn btn-default"/>
</div>
</div>
</div>
}
<div class="text-center col-md-12">
#Html.ActionLink("Back to List", "Index")
</div>
ViewModel:
namespace StatTracker.ASPMVC.ViewModels
{
public class ShiftsEmployeesViewModel
{
public CShift Shift { get; set; }
public CEmployee Employee { get; set; }
public CEmployees Employees { get; set; }
public void InsertShift()
{
CShift.InsertShift(hours: Shift.Hours, employeeid: Employee.Id, date: Shift.Date);
}
public void UpdateShift()
{
CShift.UpdateShift(hours: Shift.Hours, employeeid: Employee.Id, date: Shift.Date, shiftid: Shift.Id);
}
}
}
working code with same idea
controller
public ActionResult Create()
{
var oSalesEmployeeService = new SalesEmployeeServiceViewModel();
var oServices = new CServices();
oServices.GetServices();
var oEmployees = new CEmployees();
oEmployees.GetActiveEmployees();
oSalesEmployeeService.Employees = oEmployees;
oSalesEmployeeService.Services = oServices;
return View(oSalesEmployeeService);
}
// POST: Sales/Create
[HttpPost]
public ActionResult Create(SalesEmployeeServiceViewModel oSalesEmployeeService)
{
try
{
oSalesEmployeeService.InsertSale();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
viewmodel
using StatTracker.BL;
namespace StatTracker.ASPMVC.ViewModels
{
public class SalesEmployeeServiceViewModel
{
public CSale Sale { get; set; }
public CEmployees Employees { get; set; }
public CServices Services { get; set; }
public CEmployee Employee { get; set; }
public CService Service { get; set; }
public void InsertSale()
{
CSale.InsertSale(service: Service.Id, date: Sale.Date, employee: Employee.Id);
}
public void UpdateSale()
{
CSale.UpdateSale(service: Service.Id, date: Sale.Date, employee: Employee.Id, salesid: Sale.Id);
}
}
}
view
#model StatTracker.ASPMVC.ViewModels.SalesEmployeeServiceViewModel
#{
ViewBag.Title = "Add Sale";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal text-center">
#Html.ValidationSummary(true, "", new {#class = "text-danger"})
<div class="form-group">
<div class="input-group date col-md-12">
#Html.LabelFor(model => model.Sale.Date, new {#class = "control-label"})
#Html.EditorFor(model => model.Sale.Date, new {#class = "form-control datepicker", placeholder = "Pick a date"})
#Html.ValidationMessageFor(model => model.Sale.Date, "", new {#class = "text-danger"})
#Html.LabelFor(model => model.Employee.FullName, new {#class = "control-label"})
#Html.DropDownListFor(model => model.Employee.Id, new SelectList(Model.Employees.Employees, "Id", "FullName", Model.Employee), null, null)
#Html.ValidationMessageFor(model => model.Employee.Id, "", new {#class = "text-danger"})
#Html.LabelFor(model => model.Service.Description, new {#class = "control-label"})
#Html.DropDownListFor(model => model.Service.Id, new SelectList(Model.Services.Services, "Id", "Description", Model.Service), null, null)
#Html.ValidationMessageFor(model => model.Service.Id, "", new {#class = "text-danger"})
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<input type="submit" value="Add Sale" class="btn btn-default"/>
</div>
</div>
</div>
}
<div class="text-center col-md-12">
#Html.ActionLink("Back to List", "Index")
</div>
You have not indicated exactly where the error is being thrown but there will be numerous reasons
Firstly, a view model is not just a holder for a series of data models. It should contain only those properties which you need to display/edit in the view. Currently if any properties of CShift or CEmployee have validation attributes (other that the Date and Hours properties), your model will be invalid.
Secondly, when you return the view, you need to return the model to the view and also assign the value of Employees which currently will be null (hence the exception when you access Model.Employees.Employees in the DropDownList() method).
Based on the view you have shown, your view model should be just (add validation attributes as required)
public class ShiftsEmployeesViewModel
{
public DateTime Date { get; set; }
public int Employee { get; set; }
public float Hours { get; set; }
public SelectList EmployeeList { get; set; }
}
Controller
public ActionResult Create()
{
ShiftsEmployeesViewModel model = new ShiftsEmployeesViewModel();
model.Employee = ? // set default selection
ConfigureCreateModel(model);
return View(model);
}
[HttpPost]
public ActionResult Create(ShiftsEmployeesViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureCreateModel(model);
return View(model);
}
.... // map the view model properties to a new instance of the data model, save and redirect
}
private void ConfigureCreateModel(ShiftsEmployeesViewModel model)
{
var oEmployees = (new CEmployees()).GetActiveEmployees();
model.EmployeeList = new SelectList(oEmployees, "Id", "FullName");
}
View
#Html.LabelFor(m => m.Date)
#Html.TextBoxFor(m => m.Date)
#Html.ValidationMessageFor(m => m.Date)
#Html.LabelFor(m => m.Employee)
#Html.DropDownListFor(m => m.Employee, Model.EmployeeList, "-please select-")
#Html.ValidationMessageFor(m => m.Employee)
#Html.LabelFor(m => m.Hours)
#Html.EditorFor(m => m.Hours)
#Html.ValidationMessageFor(m => m.Shift.Hours)
Side note: Your current usage of SelectList(Model.Employees.Employees, "Id", "FullName", Model.Employee) where you use the 4th parameter is pointless. Your binding to a property, so attempting to set the value of the Selected is ignored (the selected option is based on the value of the property your binding to)
Yes, because model.Employee has not been initialized and therefore, model.Employee.Id will throw a null reference exception. After that You still need to initialize the shift object as it will also throw a null reference exception when model.Shift.Hours is accessed. Please see my suggestions below
You will have to initialize the remaining properties
public ActionResult Create()
{
var oEmployees = new CEmployees();
oEmployees.GetActiveEmployees();
var shiftsEmployees = new ShiftsEmployeesViewModel
{
Employee = new CEmployee(),
Shift = new CShift(),
Employees = oEmployees;
};
return View(shiftsEmployees);
}
Another option is to just always initialize them in the constructor of the view model (you just have to make sure that somewhere GetActiveEmployees is getting called)
public class ShiftsEmployeesViewModel
{
public ShiftsEmployeesViewModel()
{
this.oEmployees = new CEmployees();
this.Employee = new CEmployee();
this.Shift = new CShift();
}
}
Also change the implementation in your view for the dropdownlist
#Html.DropDownListFor(model => model.Employee.Id,
new SelectList(Model.Employees.Employees ?? new List<CEmployee>(),
"Id",
"FullName"))
I have created a View in my MVC4 application for Creating Users. In this View, a User can have a property set for either Organization or for Sponsor, but not both. My current code is correctly displaying all of the Organizations/Sponsors depending upon what is being shown based upon a Switch selection, but when I make a selection in either DropDownList and save the new user, all the DropDownLists return is a Null value for the User.
Users Model (Partial):
[GridColumn(Title = "Org.", SortEnabled = true, Width = "100")]
public int? MemberOrgId { get; set; }
[NotMappedColumn]
public int? SponsorOrgId { get; set; }
[ForeignKey("MemberOrgId")]
[NotMappedColumn]
public virtual MemberOrganizations Organization { get; set; }
[ForeignKey("SponsorOrgId")]
[NotMappedColumn]
public virtual SponsorOrganizations Sponsor { get; set; }
Create (VIEW):
#model PROJECT.Models.Users
#{
ViewBag.Title = "Create";
Layout = "~/Areas/Admin/.../.../.../_AdminLayout.cshtml";
string cancelEditUrl = "/Admin/UserController/";
}
#using (Html.BeginForm("Create", "UserController", FormMethod.Post, new { enctype = "multipart/form-data" })) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.RegisteredDate)
<div class="container">
<div class="row">
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field" style="margin-bottom: 15px">
#Html.TextBoxFor(model => model.Email, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Email)
</div>
</div>
<input type="checkbox" value="12345" name="Sponsor-Organization" checked class="userCreate-BSSwitch"/>
<div style="margin-bottom: 15px">
<div class="row switchOn">
<div class="editor-label">
#Html.LabelFor(model => model.MemberOrgId, "Organization")
</div>
<div class="editor-field">
#Html.DropDownList("OrganizationId", null, String.Empty, new { #class = "form-control", #id = "OrgIdDropDown" })
#Html.ValidationMessageFor(model => model.MemberOrgId)
</div>
</div>
<div class="row switchOff">
<dliv class="editor-label">
#Html.LabelFor(model => model.SponsorOrgId, "Sponsor")
</dliv>
<div class="editor-field" >
#Html.DropDownList("SponsorId", null, String.Empty, new { #class = "form-control", #id = "SponsorIdDropDown" })
#Html.ValidationMessageFor(model => model.SponsorOrgId)
</div>
</div>
</div>
<div class="row" id="submitRow">
<div class="btn-group ">
<button type="submit" value="Save" class="btn btn-success">Create User</button>
</div>
Cancel
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
<script type="text/javascript">
jQuery(document).ready(function () {
setTimeout(function () { $("#alert").alert('close'); }, 5000);
$('.switchOff').addClass('hide');
});
$.fn.bootstrapSwitch.defaults.onText = 'Member';
$.fn.bootstrapSwitch.defaults.offText = 'Sponsor';
$.fn.bootstrapSwitch.defaults.offColor = 'info';
$.fn.bootstrapSwitch.defaults.animate = false;
//$.fn.bootstrapSwitch.defaults.size = 'large';
$(document).ready(function () {
$('input:checkbox[name="Sponsor-Organization"]').bootstrapSwitch();
});
$('input:checkbox[name="Sponsor-Organization"]').on('switchChange.bootstrapSwitch', function (event, state) {
var checked = state;
if (checked) {
$('.switchOn').removeClass('hide');
$('.switchOff').addClass('hide');
$('#SponsorIdDropDown').val("");
}
else {
$('.switchOff').removeClass('hide');
$('.switchOn').addClass('hide');
$('#OrgIdDropDown').val("");
}
});
$(document).ready(function () {
$(".btn-danger").click(function () {
var cancel = confirm("Are you sure? Entered data will be lost.")
if (cancel != true) {
event.preventDefault(); // cancel the event
}
});
});
//$('input:checkbox[name="Sponsor-Organization"]').on('switchChange.bootstrapSwitch', function(event, state) {
</script>
Controller (Create GET):
//
// GET: /Admin/
public ActionResult Create()
{
ViewBag.headerTitle = "Create a User";
ViewBag.OrganizationId = new SelectList(db.MemberOrganizations, "Id", "Name");
ViewBag.SponsorId = new SelectList(db.SponsorOrganizations, "Id", "Name");
Users newUser = new Users();
newUser.RegisteredDate = DateTime.Now;
newUser.LastVisitDate = DateTime.Now;
newUser.ProfilePictureSrc = null;
return View(newUser);
}
Controller (Create HTTP-Post):
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Users users)
{
ViewBag.headerTitle = "Create a User";
if (ModelState.IsValid)
{
WebSecurity.CreateUserAndAccount(users.Email, "defaultPassword");
Users user2 = db.Users.Where(u => u.Email == users.Email).FirstOrDefault();
user2.Enabled = true;
user2.Password = Membership.GeneratePassword(15, 7);
user2.ForumUsername = users.Name;
user2.RegisteredDate = DateTime.Now;
user2.ReceiveSystemEmails = true;
db.Entry(user2).State = EntityState.Modified;
db.SaveChanges();
string[] roleNames = new string[] { "role1", "role2", "role3" };
System.Web.Security.Roles.AddUserToRoles(users.Email, roleNames);
return RedirectToAction("Index");
}
}
Anyone have some thoughts on the matter? I've tried a few different suggestions I found in other questions, but nothing has worked as of yet. This is my first MVC application, so I feel as if I may be overlooking something very basic.
for a field to be tied to the model it has to be in a "for" helper (except display). try changing your drop downs like this
#Html.DropDownListFor(x => x.OrganizationId, null, String.Empty, new { #class = "form-control"})
#Html.DropDownListFor(x => x.SponsorId, null, String.Empty, new { #class = "form-control" })
assuming your users model has fields OrganizationId and SponsorId those fields will be tied to the drop down (set them on the get and the drop down will be set and the drop down value will be passed back to the controller through the post)
Edit
I would suggest passing your drop down list through your model. to your model add
public SelectList OrganizationList { get; set; }
public SelectList SponsorList { get; set; }
then on your controller (in the get)
newUser.OranizationList = new SelectList(db.MemberOrganizations, "Id", "Name");
newUser.SponsorList = new SelectList(db.SponsorOrganizations, "Id", "Name");
then on your view
#Html.DropDownListFor(x => x.MemberOrgId, Model.OrganizationList, new { #class = "form-control" })
public class MyModel
{
public MyModel()
{
this.myDDLList = new List<SelectListItem>();
}
public List<SelectListItem> myDDLList { get; set; }
public int ddlID { get; set; }
}
public ActionResult Index()
{
MyModel model = new MyModel();
using (YourEntities context = new YourEntities())
{
var list = context.YourTable.ToList();
foreach (var item in list)
{
model.myDDLList.Add(new SelectListItem() { Text = item.NameField, Value = item.ValueField.ToString() });
}
}
return View(model);
}
#Html.DropDownListFor(x => x.ddlID, Model.myDDLList)
I resolved the issue by using ViewData[] to pass a pre-filled select list from my controller to my view:
// GET: /Admin/
public ActionResult Create()
{
ViewBag.headerTitle = "Create a User";
ViewData["Organization"] = new SelectList(db.MemberOrganizations, "Id", "Name");
ViewData["Sponsor"] = new SelectList(db.SponsorOrganizations, "Id", "Name");
Users newUser = new Users();
newUser.RegisteredDate = DateTime.Now;
newUser.LastVisitDate = DateTime.Now;
newUser.ProfilePictureSrc = null;
return View(newUser);
}
and then in my view simply read in the ViewData[] values into my Html.DropDownList's as separate SelectList's:
#Html.DropDownList("MemberOrgId", ViewData["Organization"] as SelectList, String.Empty, new { #class = "form-control", #id = "MemberOrgId" })
#Html.DropDownList("SponsorOrgId", ViewData["Sponsor"] as SelectList, String.Empty, new { #class = "form-control", #id = "SponsorOrgId" })