Display checkbox Data value from database using mvc - c#

I need to create a form to register.
the example of form will look like this
how do I display the value in the red circle in the form? (the value is from database)
My controller
namespace Insurance.Controllers
{
public class FlexiPAController : Controller
{
//
// GET: /FlexiPA/
public ActionResult RegisterFlexiPA()
{
return View();
}
public ActionResult RegisterFire()
{
return View();
}
public ActionResult RegisterMotor()
{
return View();
}
}
}
My ViewModel
namespace Insurance.ViewModels
{
public class RegisterInfoPA
{
public register reg { get; set; }
public infoPA infoFlexiPA { get; set; }
public personalInfo pinfo { get; set; }
public List<maritalInfo> minfo { get; set; }
public childInfo cInfo { get; set; }
}
}
My view
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<!--TITLE-->
<div class="editor-label">
Title
</div>
<div class="editor-field">
#Html.EditorFor(model => model.reg.title)
#Html.ValidationMessageFor(model => model.reg.title)
</div>
<!--NAME-->
<div class="editor-label">
Name
</div>
<div class="editor-field">
#Html.EditorFor(model => model.reg.registerNm)
#Html.ValidationMessageFor(model => model.reg.registerNm)
</div>
<!--IC NO-->
<div class="editor-label">
IC No
</div>
<div class="editor-field">
#Html.EditorFor(model => model.reg.identityNo)
#Html.ValidationMessageFor(model => model.reg.identityNo)
</div>
<!--GENDER-->
<div class="editor-label">
Gender
</div>
<div class="editor-field">
#Html.EditorFor(model => model.pinfo.gender)
#Html.ValidationMessageFor(model => model.pinfo.gender)
</div>
<!--Marital Status-->
<div class="editor-label">
**Marital Status**
</div>
<div class="editor-field">
</div>
Wanted to make the checkbox here for marital status eg :single,widowed,married
I am new to mvc, really appreciate your helps.

Try this
Let's try one controller first
Your Controller
namespace Insurance.Controllers
{
public class FlexiPAController : Controller
{
//
// GET: /FlexiPA/
DATABASENAME db = new DATABSENAME (); //ESTABLISHING CONNECTION TO DATABASE
public ActionResult RegisterFlexiPA()
{
using (var dataBase = new DATABASENAME ())
{
var model = new RegisterInfoPA()
{
minfo = dataBase.maritalInfoes.ToList(),
//IF YOU WISH TO ADD MORE
};
return View(model);
}
}
Your ViewModel
change you marital info to IEnurumerable instead of List
public IEnumerable<maritalInfo> minfo { get; set; }
Your View
I would like to suggest you to make radiobutton instead of checkbox, because surely you can only choose one,eg: either single or married. Thus, it is highly preferred to use radiobutton
<div>
Marital Status
#foreach (var item in Model.minfo)
{
#Html.RadioButtonFor(model => model.pinfo.maritalId, item.maritalId)#Html.Label(item.maritalStatNm)
}
</div>
This is how you display, then in the controller you just need to save it.

You can use :
#foreach(var item in Model.minfo)
{
#Html.EditorFor(o => item)
}
Create a partial view called maritalInfo.cshtml. Put this partial in Views/Shared/DisplayTemplates.
In the partial :
#model maritalInfo
<!--Marital Status Name and Value depend on your maritalInfo Model-->
<div class="editor-label">
#Html.LabelFor(o => Model.Name)
</div>
<div class="editor-field">
#Html.CheckBoxFor(o => Model.Value)
</div>

Related

MVC C# foreach Loop passing button selection

I have a listing view which shows the jobs extracted from the database. Each Job has a button next to it. When I move to the next page, i need to carry the specified job, display it and later save it to my database.
This is inside my Controller class.
I extracted the jobs in the index and after clicking the button i want to move to the "Apply" method
public ActionResult Index()
{
var jobs = (from Jobs in db.Jobs
orderby Jobs.Id descending
select Jobs);
List<CareersClasses.Jobs> job = jobs.ToList();
return View(job);
}
[HttpPost]
public ActionResult Apply(){
return View();
}
This is The Index View:
<table>
#using (Html.BeginForm("Apply", "Jobs", FormMethod.Post))
{
foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Desc)
</td>
<td>
<button id="Apply" name="Apply" value="#item.Title">Apply</button>
</td>
</tr>
}
}
</table>
This is the Apply View
#using (Html.BeginForm("Submit", "Jobs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<fieldset>
<legend>Applicants</legend>
<div class="editor-label">
#Html.LabelFor(model => model.JobId)
</div>
<div class="editor-field">
#Html.DisplayFor(model=> model.JobId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FName)
#Html.ValidationMessageFor(model => model.FName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LName)
#Html.ValidationMessageFor(model => model.LName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PhoneNb)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PhoneNb)
#Html.ValidationMessageFor(model => model.PhoneNb)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Country)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Country)
#Html.ValidationMessageFor(model => model.Country)
</div>
<div class="editor-label">
Curriculum Vitae
</div>
<div class="editor-field">
<input type="file" name="file"/>
</div>
<div class="editor-label">
#Html.EditorFor(model => model.JobId)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
I also want to add a document to my database:
I used this method in the "submit" method is it correct?
Submit Method:
[HttpPost]
public ActionResult Submit(FormCollection formCollection, HttpPostedFileBase file)
{
CareersClasses.Applicants Applicants = new CareersClasses.Applicants();
if (ModelState.IsValid)
{
Applicants.FName = formCollection["FName"];
Applicants.LName = formCollection["LName"];
Applicants.Email = formCollection["Email"];
Applicants.Country = formCollection["Country"];
Applicants.PhoneNb = int.Parse(formCollection["PhoneNb"]);
if (file != null && file.ContentLength > 0)
{
byte[] data = GetDocument(file);
Applicants.CV = data;
}
db.Applicants.Add(Applicants);
db.SaveChanges();
return RedirectToAction("ListApps");
}
return View();
}
[HttpPost]
public byte[] GetDocument(HttpPostedFileBase file)
{
//Get file info
var fileName = Path.GetFileName(file.FileName);
var contentLength = file.ContentLength;
var contentType = file.ContentType;
//Get file data
byte[] data = new byte[] { };
using (var binaryReader = new BinaryReader(file.InputStream))
{
data = binaryReader.ReadBytes(file.ContentLength);
}
return data;
}
The Classes Model:
public class CareersClasses
{
public class Applicants
{
[Key]
public int Id { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public int PhoneNb { get; set; }
public string Email { get; set; }
public string Country { get; set; }
public byte[] CV { get; set; }
public int JobId { get; set; }
[ForeignKey("JobId")]
public virtual Jobs Jobs { get; set; }
}
public class Jobs
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Desc { get; set; }
}
}
Note: I am still new to MVC and I did a lot of research before asking these questions but i'm still lost, so your help will be much appreciated
The Index view should have links (not forms) to an Apply() method for the Job. The link passes the Id of the Jobs to the method, which initializes a new instance of CareersClasses and sets its JobId property. The method then returns a view to edit the CareersClasses and the submit button posts back the model to the POST method.
Index.cshtml
<table>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.Title)</td>
<td>#Html.DisplayFor(modelItem => item.Desc)</td>
<td>#Html.ActionLink("Apply", "Apply", new { ID = item.Id})</td>
</tr>
}
</table>
Controller
public ActionResult Apply(int ID)
{
CareersClasses model = new CareersClasses();
model.JobID = ID;
return View(model);
}
[HttpPost]
public ActionResult Apply(CareersClasses model, HttpPostedFileBase file)
{
// save the model and redirect
}
Apply.cshtml
#model CareersClasses
....
#Html.BeginForm())
{
// controls for properties of CareersClasses
....
<input type="submit" value="Create" />
}

There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'PestType'

I am learning MVC and Entity Framework, so pleas bear my questions... I am trying to create a drop down menu for a property (Enum type) for my model class SinglePest
Here is the model:
public class SinglePest
{
public int SinglePestId { get; set; }
public PestType PestType { get; set; } // here is my problem
public string Alias { get; set; }
public string TechName { get; set; }
public string Markings { get; set; }
public string SerialNumber { get; set; }
public SourceType SourceType { get; set; }
//virtual property
public Source Source { get; set; }
}
Here is PestType:
public enum PestType
{
Dog,
Cat,
Fox,
Rabbit,
Rat
}
This is the controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create (//(SinglePest singlepest)
[Bind(Include= "Alias, TechName, SerialNumber, PestType, Markings")] SinglePest singlepest)
{
try
{
if (ModelState.IsValid)
{
db.SinglePests.Add(singlepest);
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException /* dex */)
{
ModelState.AddModelError("", "Unable to save changes, try again, if problem persits contact your administrator");
}
//ViewBag.SerialNumber = new SelectList(db.Sources, "SerialNumber", "SerialNumber", singlepest.SerialNumber);
return View(singlepest);
}
And here is the View where I get the error (There is no ViewData item of type 'IEnumerable' that has the key 'PestType'.) :
<div class="editor-label">
#Html.LabelFor(model => model.PestType, "Pest Type")
</div>
<div class="editor-field">
#Html.DropDownList("PestType", String.Empty) // here is the error
#Html.ValidationMessageFor(model => model.PestType.ToString())
</div>
Now I have seen some posts about displaying enum, but I can't figure out a solution for my problem. Could please someone give me some piece of advice on how to fix it?
Thank you for your time!
You have #Html.DropDownList("PestType", String.Empty), but the second param needs to be an IEnumerable<T>. You will need the list of your pest in the model, and then use model.Pests for example where Pets is an IEnumerable.
EDIT: Based on comment...
But I want to display just the various types of pest (Dog, Cat, etc)
not all the pests that are in my database
OK, are these categorised, could you write something like (hand written so check syntax)..
var pests = (from _context.Pests.Where(p => p.CategoryId == 1) select p.PestName).ToList();
If you need to get a IEnumerable for the enum (since I'm not sure what the DB looks like), you can use...
Enum.GetValues(typeof(PestType))
.OfType<PestType>()
.Where(p => p == ??);
Currently your model only contains a place to store the value and not a Array/IEnumerable to populate the drop down from.
First add an IEnumerable to your model:
public class SinglePest
{
public int SinglePestId { get; set; }
public IEnumerable<PestType> Pests { get; set; }
public PestType PestType { get; set; }
public string Alias { get; set; }
public string TechName { get; set; }
public string Markings { get; set; }
public string SerialNumber { get; set; }
public SourceType SourceType { get; set; }
//virtual property
public Source Source { get; set; }
}
And in your controller:
public ActionResult Create()
{
var model = new SinglePest();
model.Pests = Enum.GetValues(typeof(PestType)).Cast<PestType>()
return View(model);
}
And your view:
#Html.DropDownListFor(m => m.PestType, Model.Pests);
Sorry if theres any errors I've written this from memory...
I found this post on DropDownListFor enums
It seems it is solving my problem.
so I have just changed the view with this new piece of code:
<div class="editor-label">
#Html.LabelFor(model => model.PestType, "Pest Type")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.PestType, new SelectList(Enum.GetValues(typeof( MvcTrackingSystem.Enums.PestType))))
#Html.ValidationMessageFor(model => model.PestType)
</div>
Now it looks like it is working
On the difference between DropDownList and DropDownListFor I have found useful infromation on this post
You can fix the original problem quite simply with this in your GET Create method:
ViewBag.PestType = new SelectList(Enum.GetValues(typeof(PestType)).OfType<PestType>());
and this in your POST Create method (where validation fails and it returns the view):
ViewBag.PestType = new SelectList(Enum.GetValues(typeof(PestType)).OfType<PestType>(),
singlepest.PestType);
if you want to keep it strongly typed in the view use:
#Html.DropDownListFor(model => model.PestType, ViewBag.PestType as SelectList)
If you don't mind the weak typed version use the simpler:
#Html.DropDownList("PestType")
In either case I suggest you create all lists in the controller and not in the view.
Explanation:
Basically DropDownlist will search the ViewData (i.e. your ViewBag settings) for a list of options for the member of the same name (if a list is not explicitly provided).
I mocked up the whole project (MVC5/VS2013) and more of the code is below for your reference.
Controller:
using PestTypeTest.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace PestTypeTest.Controllers
{
public class PestTypeController : Controller
{
//
// GET: /PestType/
public ActionResult Index()
{
return RedirectToAction("Create");
}
public ActionResult Create()
{
ViewBag.PestType = new SelectList(Enum.GetValues(typeof(PestType)).OfType<PestType>());
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(//(SinglePest singlepest)
[Bind(Include = "Alias, TechName, SerialNumber, PestType, Markings")] SinglePest singlepest)
{
try
{
if (ModelState.IsValid)
{
//db.SinglePests.Add(singlepest);
//db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException /* dex */)
{
ModelState.AddModelError("", "Unable to save changes, try again, if problem persits contact your administrator");
}
//ViewBag.SerialNumber = new SelectList(db.Sources, "SerialNumber", "SerialNumber", singlepest.SerialNumber);
ViewBag.PestType = new SelectList(Enum.GetValues(typeof(PestType)).OfType<PestType>(), singlepest.PestType);
return View(singlepest);
}
}
}
Views\PestType\Create.cshtml
#model PestTypeTest.Models.SinglePest
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>SinglePest</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.PestType, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("PestType")
#Html.ValidationMessageFor(model => model.PestType)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Alias, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Alias)
#Html.ValidationMessageFor(model => model.Alias)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TechName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TechName)
#Html.ValidationMessageFor(model => model.TechName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Markings, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Markings)
#Html.ValidationMessageFor(model => model.Markings)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SerialNumber, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SerialNumber)
#Html.ValidationMessageFor(model => model.SerialNumber)
</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 {
#Scripts.Render("~/bundles/jqueryval")
}

What is the proper way to submit data from Parent form with partial view MVC 4?

The Main Controller
public class TestPartialController : Controller
{
//
// GET: /TestPartial/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Main model)
{
HttpContext.Items.Add("MainModel", model);
return View();
}
public ActionResult PartialA()
{
return PartialView();
}
[HttpPost]
public ActionResult PartialA(PartialA a)
{
if (HttpContext.Items["MainModel"] != null)
{
Main model =(Main) HttpContext.Items["MainModel"];
model.PA = a;
}
return PartialView();
}
public ActionResult PartialB()
{
return PartialView();
}
[HttpPost]
public ActionResult PartialB(PartialB b)
{
if (HttpContext.Items["MainModel"] != null)
{
Main model = (Main)HttpContext.Items["MainModel"];
model.PB = b;
}
SubmitDatatoDB();
return PartialView();
}
public void SubmitDatatoDB()
{
if (HttpContext.Items["MainModel"] != null)
{
Main model = (Main)HttpContext.Items["MainModel"];
//SubmitDatatoDB
}
}
}
Models:-
namespace TestingMVC4.Models
{
public class Main
{
public string Main1 { get; set; }
public string Main2 { get; set; }
public virtual PartialA PA { get; set; }
public virtual PartialB PB { get; set; }
}
public class PartialA
{
public string UserName { get; set; }
public string UserID { get; set; }
}
public class PartialB
{
public string UserNameB { get; set; }
public string UserIDB { get; set; }
}
}
View :-
#model TestingMVC4.Models.Main
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Main</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Main1)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Main1)
#Html.ValidationMessageFor(model => model.Main1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Main2)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Main2)
#Html.ValidationMessageFor(model => model.Main2)
</div>
<div>
#Html.Action("PartialA","TestPartial")
</div>
<div>
#Html.Action("PartialB","TestPartial")
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
#model TestingMVC4.Models.PartialA
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>PartialA</legend>
<div class="editor-label">
#Html.LabelFor(model => model.UserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.UserID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserID)
#Html.ValidationMessageFor(model => model.UserID)
</div>
</fieldset>
}
Mine Question is if doing like this, the Index of HTTPPOST of main view will fire first. than follow by Partial view A and Partial View B. In this case I need to store the data in HttpContext.Items and call the submit to Database in the last Partial view B.
What I want is fire the Partial view A and B first, and store the data into Main View's model and call the SubmitDatatoDB function in Main View's POST Action.
Figure out 2 method to achieve mine goal
1) Passing the main model to each partial view, sample of partial view :-
#model TestingMVC4.Models.Main
//#model TestingMVC4.Models.PartialA
<fieldset>
<legend>PartialA</legend>
<div class="editor-label">
#Html.LabelFor(model => model.PA.UserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PA.UserName)
#Html.ValidationMessageFor(model => model.PA.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PA.UserID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PA.UserID)
#Html.ValidationMessageFor(model => model.PA.UserID)
</div>
</fieldset>
disadvantages of this method is the partial view is tight to other view.
2) convert all partial view to become templates helpers :- reference from http://lostechies.com/jimmybogard/2011/09/07/building-forms-for-deep-view-model-graphs-in-asp-net-mvc/
this second method is reuse able because it used it own model binding rather than model from parent, for example :-
#model TestingMVC4.Models.ProductEditModel
#{
ViewBag.Title = "Index";
}
<p>
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name)
</p>
#Html.EditorFor(m => m.Price)
#model TestingMVC4.Models.PriceEditModel
<p>
#Html.LabelFor(m => m.Currency)
#Html.TextBoxFor(m => m.Currency)
</p>
<p>
#Html.LabelFor(m => m.Value)
#Html.TextBoxFor(m => m.Value)
</p>
You need to change your binds to get PartialModelA to populate MainModel and ensure that Partial View A is posting back to and action on the Main Controller
Something like this:
#using (Html.BeginForm("MainAction", "MainController")) {
<fieldset>
<legend>PartialA</legend>
<div class="editor-label">
#Html.Label("UserName", model.UserName)
</div>
<input type="submit" />
</fieldset>
}
Notice the Action and Controller added to the form and the change of LabelFor to use just Label.

How to POST a form containing Editor Templates for an ICollection?

I'm working with ASP.NET MVC 4 and I have the following models:
public class MultiLanguageText
{
[Key] public int Id { get; set; }
[Required] public string Name { get; set; }
public virtual ICollection<LocalizedText> LocalizedTexts { get; set; }
}
public class LocalizedText
{
[Key] public int Id { get; set; }
[ForeignKey("Language")] public int LanguageId { get; set; }
public virtual Language Language { get; set; }
[ForeignKey("MultiLanguageText")] public int MultiLanguageTextId { get; set; }
public virtual MultiLanguageText MultiLanguageText { get; set; }
public string Text { get; set; }
}
I'm trying to create an Edit view for MultiLanguageText which will also contain an editor for every item in the LocalizedTexts property. The form goes like this:
#using (Html.BeginForm("Edit", "MultiLanguageText", FormMethod.Post)) {
#Html.ValidationSummary(true)
<fieldset>
<legend>MultiLanguageText</legend>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
#Html.EditorFor(model => model.LocalizedTexts)
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
The editor template I've created (in the file ~/Views/Shared/EditorTemplates/LocalizedText.cshtml) is the following:
<fieldset>
<legend>LocalizedText</legend>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.LabelFor(model => model.LanguageId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LanguageId)
#Html.ValidationMessageFor(model => model.LanguageId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.MultiLanguageTextId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.MultiLanguageTextId)
#Html.ValidationMessageFor(model => model.MultiLanguageTextId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Text)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Text)
#Html.ValidationMessageFor(model => model.Text)
</div>
</fieldset>
I'm testing with some pre-existing values and all the data is shown properly in the parent and in the child editors, when the page is shown. However, when I submit the form, all changes done inside any of the child editors are ignored.
My HttpPost method is this:
[HttpPost]
public ActionResult Edit(MultiLanguageText multilanguagetext)
{
if (ModelState.IsValid)
{
db.Entry(multilanguagetext).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(multilanguagetext);
}
My question is: How do I make it so that all values are posted, from both the parent model and its children model editors? (I've seen that other similar questions exist, but I've tried their solutions and they didn't seem to fix my problem.)
I'm testing your question. I think it's done and all values posted. But I think you need provide more information to fix your problem
After some trying, this is the solution that I found to work:
[HttpPost]
public ActionResult Edit(MultiLanguageText multilanguagetext)
{
if (ModelState.IsValid)
{
db.Entry(multilanguagetext).State = EntityState.Modified;
foreach (var local in multilanguagetext.LocalizedTexts) db.Entry(local).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(multilanguagetext);
}

No parameterless constructor defined for this object- Unable to Solve

I am new to C# and MVC so please forgive any naiveness/stupidity. I have seen multiple posts dealing with the error I have and I have tried all the solutions but they dont seem to work in my case. Please guide me to the right way to solve this problem.
Background:
I have 2 models tblPrograms and tblReports.
I am trying to build a simple form where the user can create a new tblReport. Part of the process of creating a new tblReport is to select one tblProgram from a list.
Code Overview:
Controller:
// GET: /Reports/
public ViewResult New()
{
ProgramListModel progList = new ProgramListModel();
tblReports2 report = new tblReports2();
ExistingReportViewModel ervm = new ExistingReportViewModel(report,progList);
return View(ervm);
}
[HttpPost]
public ActionResult GenerateSQL(ExistingReportViewModel evrm)
{
evrm.Report.ProgramName = evrm.progList.selectedProgram;
return View(evrm);
}
View Model:
public class ExistingReportViewModel
{
public tblReports2 Report { get; set; }
public ProgramListModel progList { get; set; }
//public ExistingReportViewModel() { }
public ExistingReportViewModel(tblReports2 report, ProgramListModel progList)
{
this.Report = report;
this.progList = progList;
}
}
Models:
public class tblReports2
{
[Key]
public string ProgramName { get; set; }
public string ReportDesc { get; set; }
....
}
public class ProgramListModel
{
public SelectList progList;
public string selectedProgram;
public ProgramListModel() {
ReportHelper helper = new ReportHelper();
this.progList = helper.getProgramList();
}
}
Helper Method:
public SelectList getProgramList()
{
var programs = from p in this.DB.tblProgramsSet
select p;
programs = programs.Where(s => s.ProgramType.Equals("RPT"));
SelectList list = new SelectList(programs, "ProgramName", "ProgramDescription");
return list;
}
View:
#model ReportsSetup.Models.ExistingReportViewModel
#{
ViewBag.Title = "New";
}
New
#using (Html.BeginForm("GenerateSQL", "Reports"))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>ExistingReportViewModel</legend>
#Html.DropDownListFor(model=>model.progList.selectedProgram, Model.progList.progList)
<div class="editor-label">
#Html.LabelFor(model => model.Report.ReportDesc)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Report.ReportDesc)
#Html.ValidationMessageFor(model => model.Report.ReportDesc)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Report.Formerly)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Report.Formerly)
#Html.ValidationMessageFor(model => model.Report.Formerly)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Report.ExtendedDesc)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Report.ExtendedDesc)
#Html.ValidationMessageFor(model => model.Report.ExtendedDesc)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Report.ReportCode)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Report.ReportCode)
#Html.ValidationMessageFor(model => model.Report.ReportCode)
</div>
...
<input type="submit" value="Create" />
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Error:
![Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.][1]
http://i.stack.imgur.com/GHJpG.jpg
Attempted Solutions:
Refactored the code to use IEnumerable <tblPrograms> instead of
SelectList in ProgramListModel and converting to
IEnumerable in View using a function similar to
sample below:
public static IEnumerable<SelectListItem> ToSelectListItems(
this IEnumerable<Album> albums, int selectedId)
{
return
albums.OrderBy(album => album.Name)
.Select(album =>
new SelectListItem
{
Selected = (album.ID == selectedId),
Text = album.Name,
Value = album.ID.ToString()
});
}
Refactored the code to use IEnumerable<SelectListItem> instead of
SelectList in ProgramListModel
Many Thanks in Advance!!
No, you can't do that:
public ActionResult GenerateSQL(ExistingReportViewModel evrm)
if your ExistingReportViewModel doesn't have a parameterless constructor. The default model binder doesn't know how to instantiate this class if it doesn't have a default constructor.
So you have 2 possibilities:
Define a parametrless constructor to this class:
public class ExistingReportViewModel
{
public ExistingReportViewModel()
{ }
... some other stuff of course
}
Write a custom model binder
Definitely go for 1. unless you need something very special. If you need something very special then please define it precisely, so that we can help you with 2.

Categories

Resources