ASP.NET MVC 3 Model null on submit - asp.net

View
#model Survey.Models.TakeSurveyViewModel
#{
Layout = "~/Views/Shared/_SiteLayout.cshtml";
}
<h2>SURVEY : #Model.Title</h2>
<h3>#Model.Description</h3>
<hr />
#using (Html.BeginForm("SubmitSurvey", "HomePage", FormMethod.Post, new { id = "surveyForm" }))
{
for (int index = 0; index < Model.SurveyQuestions.Count; index++)
{
#* Editor Template - Null result *#
#*SurveyQuestionModel item = Model.SurveyQuestions[index];
#Html.EditorFor(x => item);*#
<p>#Model.SurveyQuestions[index].QuestionText</p>
#Html.DropDownListFor(item => Model.SurveyQuestions[index].OptionId, new SelectList(Model.SurveyQuestions[index].Options, "OptionId", "OptionText"), string.Empty)
}
<input type="submit" value="SubmitSurvey" />
}
ViewModel
public class TakeSurveyViewModel
{
public string Title { get; set; }
public string Description { get; set; }
public int SurveyId { get; set; }
public List<SurveyQuestionModel> SurveyQuestions { get; set; }
public TakeSurveyViewModel() { }
public TakeSurveyViewModel(int surveyId)
{
//Populate data - works ok.
}
}
DropDownList Model
public class SurveyQuestionModel
{
public int QuestionId { get; set; }
public string QuestionText { get; set; }
[Required(ErrorMessage = "Please select an option.")]
public int OptionId { get; set; }
public IEnumerable<QuestionOption> Options { get; set; }
}
The page is rendering fine, with all the drop-downs with correct options. The id and name of each select is also unique -
id="SurveyQuestions_3__OptionId" name="SurveyQuestions[3].OptionId"
Controller Action
[HttpPost]
public ActionResult SubmitSurvey(TakeSurveyViewModel model)
{
return !ModelState.IsValid ? TakeSurvey(model.SurveyId) : null;
}
But clicking on the submit button, controller action model is null.
Edit: Removed the 2x HTML.BeginForm
Edit 2: SurveyQuestions now has public setter. The issue seem to be still there. Please see this image:

Is the problem that you have SurveyQuestions being a private set?
-old answer-
You have 2 x
(Html.BeginForm(Html.BeginForm
I once forgot to have my form within a using statement which did the same sort of thing.

Related

View Modeling: List field

I have a Form class that has a List<FormField>.
public class Form
{
public int ID { get; set; }
public int templateID { get; set; }
public List<FormField> fields { get; set; }
public Form()
{
fields = new List<FormField>();
}
}
The FormField:
public class FormField
{
public object value { get; set; }
public TemplateField templateField {get;set;}
}
And the TemplateField:
public class TemplateField
{
public int ID { get; set; }
public string fieldDescription { get; set; }
public TemplateFieldType type { get; set; }
}
My controller class:
public class MedicalAppointment : Controller
{
public IActionResult Index()
{
Template template = new TemplateDataMapper().GetMedicalAppointmentTemplate();
Form form = new Form();
form.templateID = template.ID;
foreach(TemplateField field in template.fields)
{
FormField formField = new FormField();
formField.templateField = field;
form.fields.Add(formField);
}
return View(form);
}
public IActionResult TemplateManagement()
{
return View();
}
[HttpPost]
public void SaveForm(Form form)
{
......
}
My view looks like this:
#model Form
....
#using (Html.BeginForm("SaveForm", "MedicalAppointment", FormMethod.Post, new { id = "registerDonorForm" }))
{
<table class="personal-data">
#for(int i=0; i<Model.fields.Count; i++)
{
<tr>
<th>#Html.LabelFor(model => Model.fields[i].templateField.ID, Model.fields[i].templateField.fieldDescription)</th>
<th>#Html.TextBoxFor(model => Model.fields[i].value)</th>
</tr>
}
</table>
<div class="register-button">
<input type="submit" value="Registar" />
</div>
}
</div>
I want to create a dynamic form, where when I submit it, I could receive a Form with the field[i].value.
My problem is that, when I submit the form, in the controller, I don't receive any value submitted by the user. The Form is received with the FormField.Value null as well the Form.FormField.TemplateField.ID.
Any one can help me with that?
Note: Forget the class names on html and other wrong names.
Thank you in advance

Mvc4 how can i use 2 tables in a single view

This is an ASP.NET MVC4 project with Entity Framework.
I need to use 2 tables in single view
I have 2 tables in my database (Budgets and Products).
My Models
Budget.cs
public class Budget
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<Product> Products { get; set; }
}
Product.cs
public class Product
{
public int Id { get; set; }
public string Title { get; set; }
public decimal Value { get; set; }
public int BudgetId { get; set; }
}
BpDb
public class BpDb:DbContext
{
public DbSet<Budget> Budgets { get; set; }
public DbSet<Product> Products { get; set; }
}
MasterBP
public class MasterBP
{
public int Id { get; set; }
public string Title { get; set; }
public List<Product> ProdName { get; set; }
public int CountOfValues { get; set; }
}
I need something about Controller to get ProdName (Title from table products)
public class HomeController : Controller
{
BpDb _db = new BpDb();
public ActionResult Index()
{
var model=_db.Budgets
.Select(r=>new MasterBP
{
Id = r.Id,
Title = r.Title,
ProdName = r.Products.Where(s => s.BudgetId == r.Id).ToList(),
CountOfValues = r.Products.Count()
});
return View(model);
}
}
I need a way to get a list of products Title when the BudgetId = ID (1 Budget can have more than 1 Products)
And my Index is like:
#model IEnumerable<MvcGg.Models.MasterBP>
#foreach (var item in Model)
{
<div>
<h4>#item.Title</h4>
#foreach (var product in item.ProdName)
{
#(product.Title.ToString());
}
Values:#item.CountOfValues
</div>
}
It sounds like (correct me if I am wrong) you want to access two sets of entities in your view model?
Then something along these lines will do:
public class BudgetsViewModel
{
public IEnumerable<MasterBP> MasterBps { get;set; }
public IEnumerable<Product> Products { get;set;}
}
And then you just retrieve all the data and populate the viewmodel and pass it down.
...
var budgets =_db.Budgets
.Select(r=>new MasterBP
{
Id = r.Id,
Title = r.Title,
ProdName = r.Products.Where(s => s.BudgetId == r.Id).ToList(),
CountOfValues = r.Products.Count()
});
var model = new BudgetsViewModel()
{
MasterBps = budgets
//Products here
}
return View(model);
...
However it would be better if you made some form of service layer to handle the retrieving on entities and the mapping to view models instead of having all this logic in your controller.
finally this solve my problem,
Model:
MasterBP
public class MasterBP
{
public int Id { get; set; }
public string Title { get; set; }
public IEnumerable<Product> ProdName { get; set; }
public int CountOfValues { get; set; }
}
I replaced List<> with IEnumerable<>
Controller:
public ActionResult Index()
{
var model=_db.Budgets
.Select(r=>new MasterBP
{
Id = r.Id,
Title = r.Title,
ProdName = r.Products.Where(s => s.BudgetId == r.Id).AsEnumerable(),
CountOfValues = r.Products.Count()
});
return View(model);
}
In addition i have change ToList() in AsEnumerable() and now i can see my result using this
View:
Index
#foreach (var item in Model)
{
<div>
#item.Title
<ul>
#foreach (var prod in item.ProdName)
{
<li>#prod.Title</li>
}
</ul>
<hr />
</div>
}

Html.DropDownList razor

I'm new to MVC and C# and having hard time with a dropdown list.
What I'm trying to accomplish is to initialize my page with an object that keeps the settings.
(I read settings from XML file).
Here's what I have
public class StoreSettings
{
public String BackSrs2Path { get; set; }
public int NoLines { get; set; }
public String Requesturl { get; set; }
}
public class Store
{
public String StoreId { get; set; }
public String Address { get; set; }
public StoreSettings StoreSettings { get; set; }
}
and the Model for my view page is a list of Store
#model System.Collections.Generic.List<Control2.Models.Store>
#{
List<SelectListItem> selectList = new List<SelectListItem>();
foreach (var Store in Model)
{
SelectListItem i = new SelectListItem();
i.Text = Store.StoreId;
i.Value = Store.StoreId;
selectList.Add(i);
}
}
#using (Html.BeginForm())
{
SelectList list = new SelectList(selectList, "Value", "Text");
#Html.DropDownList("ddl", list, "select store", new { onchange = "this.form.submit();" });
}
}
By reading examples here managed to populate the dropdownlist from my model and postsback
but now i need to get only the selected object from the list and apply his seetings to the page to display it etc a message "you ve selected Store"+Storeid(the slected from dropdown)
Also this code is written in my cshtml page which isn't the best but couldn't figure how should I do it with ViewModel and dropdown list
Yes when I first started looking at the DropDownList Binding mechanisms of MVC I too had problems. What I'd like to do is suggest to you the following:
Create a Viewmodel and bind the entire view to the viewmodel... as follows:
public class VMStore
{
public VMStore()
{
ItemsInDropDown = new List<SelectListItem>(){
new SelectListItem{ Text="SomeValue", Selected=false, Value="SomeUniqueId"}
};
}
public String StoreId { get; set; }
public String Address { get; set; }
public StoreSettings StoreSettings { get; set; }
public string SelectedValue { get; set; }
public IEnumerable<SelectListItem> ItemsInDropDown { get; set; }
public void Post()
{
//This method will have the user selected value...
}
}
The view will bind fields like this:
#model WebApplication1.ViewModels.VMStore
#{
ViewBag.Title = "GetStore";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>GetStore</h2>
<div>
<h4>VMStore</h4>
<hr />
<dl class="dl-horizontal">
#Html.BeginForm(){
<dt>Select Store</dt>
<dd>#Html.DropDownListFor(p=>Model.SelectedValue, Model.ItemsInDropDown) </dd>
<dd><button type="submit">Submit</button></dd>
}
</dl>
</div>
The action methods will look like this:
public ActionResult GetStore()
{
return View();
}
[HttpPost]
public ActionResult GetStore(ViewModels.VMStore userdata) {
if (ModelState.IsValid)
{
userdata.Post();
}
return View(userdata);
}

Strongly typed radiobutton list not posting back, shows empty when received from view

I'm trying to get a collection of radio buttons to postback. I'm able to display them on the form just fine, and when i submit i receive it on my controller but the list is empty, what am I doing wrong here?
VIEW-MODEL
public class ProfileViewModel
{
public class FederalClassificationViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public IList<FederalClassificationViewModel> federalClassificationsRadioViewModel { get; set; }
}
CONTROLLER
//Retrieve all available radio buttons for tax information form
var allTaxFederalClassList = _taxFederalRepo.GetAllTaxFederalClassesList();
foreach (var federalClass in allTaxFederalClassList)
{
ProfileViewModel.FederalClassificationViewModel federalClassVM = new ProfileViewModel.FederalClassificationViewModel();
federalClassVM.IsSelected = false;
federalClassVM.Name = federalClass.Name;
federalClassVM.Id = federalClass.id;
model.federalClassificationsRadioViewModel.Add(federalClassVM);
}
VIEW
#foreach(var radio in Model.federalClassificationsRadioViewModel)
{
#Html.RadioButtonFor(p=>p.federalClassificationsRadioViewModel, radio) #radio.Name
}
Updated with new Results
#for(int i=0; i<Model.federalClassificationsRadioViewModel.Count; i++)
{
#Html.RadioButtonFor(p=>p.federalClassificationsRadioViewModel[i].IsSelected, Model.federalClassificationsRadioViewModel[i].Id) #Model.federalClassificationsRadioViewModel[i].Name
}
RESULTS
EDIT :
Change your view model like:
public class ProfileViewModel
{
public class FederalClassificationViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public int SelectedClass {get;set;}
public IList<FederalClassificationViewModel> federalClassificationsRadioViewModel { get; set; }
}
Change your foreach to for loop:
#for(int i=0; i<Model.federalClassificationsRadioViewModel.Count; i++)
{
#Html.RadioButtonFor(p=>p.
SelectedClass,Model.federalClassificationsRadioViewModel[i].Id) #Model.federalClassificationsRadioViewModel[i].Name
}
You need to understand Model binding of List, Collection and Arrays, you can see details here

DropdownList selected value not saved in database

I need big help from here i am new to Asp.net MVC 4 Application development , actually i faced a problem when i save my dropdownlist selected value in a database ,after i click my submit button.
I use Debug pointer to check values in a HTTP post object but it doesn't contain dropdownlist select value it always display null value in a division raw I need some expert advice to solve that problem i go through the several examples and try several times but still i haven't proper solution for that.
Model class:
public partial class tblEmployee
{
public int EmployeeId { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Nullable<System.DateTime> DateOfBirth { get; set; }
public Nullable<System.DateTime> DateOfJoin { get; set; }
public string Position { get; set; }
public string Office { get; set; }
public string Division { get; set; }
public Nullable<decimal> Salary { get; set; }
public virtual tblDivision Divisions { get; set; }
}
public partial class tblDivision
{
public int value { get; set; }
public string Division { get; set; }
public Nullable<int> SelectId { get; set; }
}
Controller class:
namespace EmpiteHrSystem.Controllers
{
public class EmployeeController : Controller
{
private EmpiteContext db = new EmpiteContext();
public ActionResult Create()
{
ViewBag.DivisionOptions = new SelectList(db.tblDivisions, "value","Division");
return View();
}
//
// POST: /Employee/Create
[HttpPost]
public ActionResult Create(tblEmployee tblemployee)
{
if (ModelState.IsValid)
{
try
{
db.Entry(tblemployee).State = EntityState.Added;
db.tblEmployees.Add(tblemployee);
db.SaveChanges();
}
catch (ArgumentException ae)
{
ModelState.AddModelError("", ae.Message);
}
return RedirectToAction("Index");
}
}
}
}
View:
#model EmpiteHrSystem.Models.tblEmployee
#{ ViewBag.Title = "Create"; Layout = "~/Views/Shared/_Layout.cshtml";}
#Html.EditorFor(model => model.EmployeeId)
#Html.ValidationMessageFor(model => model.EmployeeId)
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
#*#Html.EditorFor(model => model.Office)*#
#Html.DropDownList("DivisionOptions")
#Html.ValidationMessageFor(model => model.Division)
#Html.ActionLink("Back to List", "Index")
Your DivisionOptions drop down list is not being bound back to the model properly because it is the wrong name. Your model is looking for a property with the name Division while your drop down list is being bound to DivisionOptions. You have a few options.
Use a strongly typed helper
#Html.DropDownListFor(x=>x.Division, (SelectList)ViewBag.DivisionOptions)
Rename your currrent code and pass in the SelectList
#Html.DropDownList("Division", (SelectList)ViewBag.DivisionOptions)

Resources