Issue on retrieving value from DropDownListFor - asp.net-mvc

I have a situation where I would like administrators to re-order questions to however they like, however, I have an issue on retrieving the value selected from the "DropDownListFor" from my form to my controller.
Placing the breakpoint at "Debug.WriteLine(MV.Count), the variable "SetNewValue" returns null in my controller
So what is the proper way to retrieve the new value that is selected and my default selected value from my DropDownListFor, as well as the current question number to my controller upon "onchange = this.form.submit()"?
I know the [HttpPost] Controller part is not a proper method to swap the questions, it is there for me to see whether the variables I have set do return the values that are sent from the DropDownListFor upon "onchange" form submit.
Any form of help is appreciated, as I am a beginner in MVC.
My View
#model IList<AppXamApplication.Models.EditQuestionsAndAnswersViewModel>
#{
ViewBag.Title = "EditQuestionsPage2";
}
<h4>Edit Your Questions Here</h4>
#using (Html.BeginForm("EditQuestionsPage2", "ExamAdmin", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<table id="tblQuestions" border="0" style="border:none">
#for (int i = 0; i < Model.Count; i++)
{
if (Model[i].TypeOfQuestion == "Open Ended")
{
<tr>
<td>
#Html.DropDownListFor(m => m[i].SetNewValue, new SelectList(Model[i].TotalNoQuestions, "Value", "Text", Model[i].ToSetPreSelectValue), new { #Name = "CurrentQnAction", onchange = "this.form.submit();" })
#Html.HiddenFor(m => m[i].CurrentQuestionNumber, new { CurrentQnNoID = Model[i].CurrentQuestionNumber })
</td>
<td> </td>
<td> </td>
<td>
#Html.ActionLink("Delete Question", "EditQuestionsPage2", new { Question_ID = Model[i].QuestionID, #class = "form-control" })
</td>
</tr>
<tr>
<td>
<b>Question Type: #Html.DisplayFor(m => m[i].TypeOfQuestion, new { #class = "form-control" }) </b>
</td>
</tr>
<tr>
<td>
#Html.EditorFor(m => m[i].QuestionsAsked, new { #class = "form-control" })
</td>
</tr>
<tr>
<td>
<br />
<br />
</td>
</tr>
}
}
</table>
}
Edited: My Model
public class EditQuestionsAndAnswersViewModel
{
//Questions
public string QuestionID { get; set; }
public string TypeOfQuestion { get; set; }
public string ExamID { get; set; }
public string QuestionsAsked { get; set; }
public string UserID { get; set; }
public int? OrderingQuestions { get; set; }
public int? CurrentQuestionNumber { get; set; }
public string SetNewValue { get; set; }
public int? ToSetPreSelectValue{ get; set; }
public IList<SelectListItem> TotalNoQuestions { get; set; }
public IList<EditAnswers> PossibleAnswers { get; set; }
public string AnswerID { get; set; }
public string AnswerText { get; set; }
}
Edited: My Controllers
[HttpGet]
public ActionResult EditQuestionsPage2()
{
if (ModelState.IsValid)
{
using (var ctx = new AppXamApplicationEntities())
{
var CurrentExamID2 = (string)Session["CurrentExamID2"];
string CurrentExamID2_string = Convert.ToString(CurrentExamID2);
var query = ctx.Questions.Where(x => x.ExamID.Equals(CurrentExamID2_string))
.Select(x => new EditQuestionsAndAnswersViewModel()
{
QuestionID = x.QuestionID,
TypeOfQuestion = x.TypeOfQuestion,
ExamID = x.ExamID,
QuestionsAsked = x.QuestionsAsked,
UserID = x.UserID,
ToSetPreSelectValue= x.QuestionOrder,
// To Order the questions in ascending order
OrderingQuestions = x.QuestionOrder,
// To Display Current Question Number
CurrentQuestionNumber = x.QuestionOrder,
// To Display the dropdownlist as well as set the default selected value to be displayed for each question in the dropdownlist
TotalNoQuestions = ctx.Questions.Where (v=> v.ExamID.Equals(x.ExamID)).Select(v => new SelectListItem
{
Value = v.QuestionOrder.ToString(),
Text = v.QuestionOrder.ToString(),
}).ToList(),
PossibleAnswers = x.Answers.Where(y => y.QuestionID.Equals(x.QuestionID)).Select(y => new EditAnswers()
{
AnswerID = y.AnswerID,
AnswerText = y.AnswerText
}).ToList()
}).ToList().AsQueryable();
var queryOrdered = query.OrderBy(x=> x.CurrentQuestionNumber).ToList();
return View(queryOrdered);
}
}
return View();
}
[HttpPost]
public ActionResult EditQuestionsPage2(string action, string CurrentQnAction, int? CurrentQnNoID, IList<EditQuestionsAndAnswersCollectionModel> MV, string ToRetrieveSelectedValue, AddQuestions _model)
{
if (ModelState.IsValid)
{
if (CurrentQnNo!= null)
{
//Breakpoint placed over here
Debug.WriteLine(MV.Count);
}
}
return View();
}

Related

Insert Checkbox Selected Value into Database

I am trying to insert selected checkbox values to database. But I get an error
Unable to cast object of type 'System.Collections.Generic.List` to type 'System.String'
Please help. Thanks.
Model:
public class CheckboxModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool Checked { get; set; }
}
public class MainModel
{
public List<CheckboxModel> CheckBoxes { get; set; }
}
HomeController:
// Get
public ActionResult Index()
{
MainModel model = new MainModel();
var list = new List<CheckboxModel>
{
new CheckboxModel{Id = 1, Name = "Male", Checked = false},
new CheckboxModel{Id = 2, Name = "Female", Checked = false},
};
model.CheckBoxes = list;
return View(model);
}
[HttpPost]
public ActionResult Create([Bind(Include = "Checkboxes")] MainModel model)
{
if (ModelState.IsValid)
{
db.MainModel.Add(model);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(MainModel);
}
View:
#using (Html.BeginForm("Create", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#for (var i = 0; i < Model.Checkboxes.Count; i++)
{
<table>
<tr>
<td>
#Html.HiddenFor(m => Model.Checkboxes[i].Id)
#Html.HiddenFor(m => Model.Checkboxes[i].Name)
#Html.CheckBoxFor(m => Model.Checkboxes[i].Checked)
</td>
<td>
#Html.DisplayFor(m => Model.Checkboxes[i].Name)
</td>
</tr>
</table>
}

ViewModel, View and PartialView Post to Controller

I am trying to do the following: I have two models, header and List(details), sent to a view by a view model. When loading the main view, a dropdown is displayed from a list in the ViewModel.header model previously loaded. When you click on that dropdown, a partial view is loaded with some values, filtered by the value of the ddl, of the ViewModel.List(details) for the user to complete the information. So far everything works fine, but when doing the Post, controller it receives the ViewModel.List(details) in null.
what am I doing wrong?
Header
public class StockTransactionsHeader
{
[Key]
public int TransactionHeaderID { get; set; }
public DateTime TransactionDate { get; set; }
public string TransactionDocument { get; set; }
public int CategoryID { get; set; }
[NotMapped]
public List<SelectList> CategoryCollection { get; set; }
public virtual List<StockTransactionsDetails> StockTransactionsDetails { get; set; }
}
Details
public class StockTransactionsDetails
{
[Key]
public int TransactionDetailID { get; set; }
public int TransactionHeaderID { get; set; }
public int ProductID { get; set; }
public decimal Qty { get; set; }
public decimal Amount { get; set; }
public decimal TransactionAmount { get; set; }
[NotMapped]
public string ProductDescription { get; set; }
public virtual StockTransactionsHeader StockTransactionsHeader { get; set; }
}
ViewModel
public class StockTransactionsViewModel
{
public StockTransactionsHeader StockTransactionsHeader { get; set; }
public List<StockTransactionsDetails> StockTransactionsDetails { get; set; }
}
Controller Create
public ActionResult Create()
{
var stockTransactions = new StockTransactionsViewModel();
stockTransactions.StockTransactionsHeader = GetHeaderCategories();
return View(stockTransactions);
}
GetHeaderCategories()
private StockTransactionsHeader GetHeaderCategories()
{
var header = new StockTransactionsHeader();
header.CategoryCollection = CommonServices.GetSelecList((int)DeliveryCommonHelper.ConfigurationType.Categoria);
return header;
}
MainView
#model DeliverySolutionCommon.ViewModels.StockTransactionsViewModel
#using (Html.BeginForm())
{
<div class="form-row">
<div id="partialView" class="table-responsive">
</div>
</div>
<div class="form-group">
<div class="col-md-2">
<input type="submit" value=" Procesar " class="btn btn-warning" />
</div>
</div>
}
Script to load partial view
<script>
$(document).ready(function () {
$("#Category").on("change", function () {
autoFiltro();
})
})
function autoFiltro() {
var url = "#Url.Action("GetProductsListByCategory", "StockTransactions")";
var id = $("#Category").val();
var data = { idCategory: id };
$.post(url, data).done(function (data) {
$("#partialView").html(data);
})
}
</script>
GetProductsListByCategory
[HttpPost]
public PartialViewResult GetProductsListByCategory(int idCategory)
{
var products = ProductsServices.GetProductsListByCategory(idCategory);
var stockTransactions = new StockTransactionsViewModel();
stockTransactions.StockTransactionsDetails = GetTransactionsDetails(products);
return PartialView("_createStockTransactions", stockTransactions);
}
GetTransactionsDetails
private List<StockTransactionsDetails> GetTransactionsDetails (List<Products> products)
{
var details = new List<StockTransactionsDetails>();
foreach (var item in products)
{
StockTransactionsDetails detail = new StockTransactionsDetails();
detail.ProductID = item.ProductID;
detail.ProductDescription = item.Description;
details.Add(detail);
}
return details;
}
PartialView
#model DeliverySolutionCommon.ViewModels.StockTransactionsViewModel
<table class="table table-sm table-bordered table-striped">
#foreach (var item in Model.StockTransactionsDetails)
{
<tr class="d-flex">
<td class="col-7">
#Html.DisplayFor(modelItem => item.ProductDescription)
</td>
<td class="col-1">
#Html.EditorFor(modelItem => item.Qty, new { htmlAttributes
= new { #class = "form-control" } })
</td>
<td class="col-2">
#Html.EditorFor(modelItem => item.Amount, new {
htmlAttributes = new { #class = "form-control" } })
</td>
<td class="col-2">
#Html.EditorFor(modelItem => item.TransactionAmount, new {
htmlAttributes = new { #class = "form-control" } })
</td>
</tr>
}
</table>
Aaaaand finally Create Post
[HttpPost]
public ActionResult Create(StockTransactionsViewModel stockTransactionsView)
{
// StockStransactionsView.StockTransactionsDetails = null
}
The problem is you are posting back a list and there is no indexing information in your HTML... MVC model binder does not know how to put the items in a list without the index info...
you can try something like this:
#for (int i = 0; i < Model.StockTransactionsDetails.Count, i++)
{
<tr class="d-flex">
<td class="col-7">
#Html.EditorFor(modelItem => Model[i].Amount, new {
htmlAttributes = new { #class = "form-control" } })
</td>
// more code...
This would add the indexing information to your HTML...
Alternatively you can use EditorTemplate... something like this:
// Note that EditorFor template would iterate the list item for you
#Html.EditorFor(m => m.Model.StockTransactionsDetails)
This tutorial might help

How to bind Linq Multiple models data in a View using ViewBag MVC?

I am using LINQ to join multiple model classes and pass the Linq object to View using ViewBag.
I am facing problem while repeating data or binding data
Model Properties:
public class SalesModel
{
public string CustomerName { get; set; }
public int SSN { get; set; }
public int LicenseId { get; set; }
public int Age { get; set; }
public string City { get; set; }
//Vehicle Sales
public DateTime? SaleDate { get; set; }
public int CustomerId { get; set; }
public int SelecteModle { get; set; }
}
public ActionResult CreateVehicleSalesView()
{
var make = objVehicleContext.VehicleMakes;
SalesModel objSalesModle = new SalesModel()
{
MakesList = new SelectList(make, "MakeId", "Make")
};
VehicleDataContext objDataContext = new VehicleDataContext();
var vehcileSalesDetails = from VS in objDataContext.Vehiclesales
join VModel in objDataContext.VehicleModels on VS.ModelId equals VModel.ModelId
join Cus in objDataContext.Customers on VS.customerId equals Cus.customerId
join VMake in objDataContext.VehicleMakes on VModel.MakeId equals VMake.MakeId
select new
{
Name = Cus.customerName,
age = Cus.Age,
city = Cus.City,
licenseId = Cus.LicesnseId,
make = VMake.Make,
model = VModel.Model,
year = VModel.Year,
saleDate = VS.SaleDate
};
ViewBag.vehicleSalesDetails = vehcileSalesDetails;
return View(objSalesModle);
}
View:
I have problem while binding data, How to call Linq column names in a view?
<table>
<tr>
<td>Name</td>
<td>Age</td>
<td>City</td>
<td>Make</td>
<td>Model</td>
<td>Year</td>
<td>Sale Date</td>
</tr>
#foreach (var v in ()ViewBag.vehicleSalesDetails)
{
<tr>#v.Name</tr>
<tr>#v.Age</tr>
<tr>#v.City</tr>
<tr>#v.Model</tr>
<tr>#v.Year</tr>
<tr>#v.SaleDate</tr>
}
</table>
Viewbag has a dynamic construction and I don't recommend to return your object in viewbag. Maintanence is diffucult with dynamics.
You can either add other properties to your SalesModel or create new model to return view like VehicleSalesDetailModel. I recommend to create a new model like:
public class SalesModel
{
public string Name { get; set; }
//Change XXX with Make's type
public XXX Make {get;set;}
public int LicenseId { get; set; }
public int Age { get; set; }
public string City { get; set; }
//Vehicle Sales
public DateTime? SaleDate { get; set; }
public int Year{ get; set; }
}
And in your action:
public ActionResult CreateVehicleSalesView()
{
var make = objVehicleContext.VehicleMakes;
SalesModel objSalesModle = new SalesModel()
{
MakesList = new SelectList(make, "MakeId", "Make")
};
VehicleDataContext objDataContext = new VehicleDataContext();
VehicleSalesDetailModel vehcileSalesDetails = from VS in objDataContext.Vehiclesales
join VModel in objDataContext.VehicleModels on VS.ModelId equals VModel.ModelId
join Cus in objDataContext.Customers on VS.customerId equals Cus.customerId
join VMake in objDataContext.VehicleMakes on VModel.MakeId equals VMake.MakeId
select new VehicleSalesDetailModel
{
Name = Cus.customerName,
Age = Cus.Age,
City = Cus.City,
LicenseId = Cus.LicesnseId,
Make = VMake.Make,
Model = VModel.Model,
Year = VModel.Year,
SaleDate = VS.SaleDate
};
return View(vehcileSalesDetails);
}
I solved my problem.
public class VehiclesSaveAndDetails
{
public SalesModel _salesModle { get; set; }
public IEnumerable< SalesDetailsTable> _SalesDetailsTable { get; set; }
}
public ActionResult VehicleSaveAndDetails()
{
var make = objVehicleContext.VehicleMakes;
SalesModel objSalesModle = new SalesModel()
{
MakesList = new SelectList(make, "MakeId", "Make")
};
VehicleDataContext objDataContext = new VehicleDataContext();
IEnumerable<SalesDetailsTable> vehcileSalesDetails = from VS in objDataContext.Vehiclesales
join VModel in objDataContext.VehicleModels on VS.ModelId equals VModel.ModelId
join Cus in objDataContext.Customers on VS.customerId equals Cus.customerId
join VMake in objDataContext.VehicleMakes on VModel.MakeId equals VMake.MakeId
select new SalesDetailsTable
{
CustomerName = Cus.customerName,
Age = Cus.Age,
City = Cus.City,
LicenseId = Cus.LicesnseId,
MakeName = VMake.Make,
ModelName = VModel.Model,
// = VModel.Year,
SaleDate = VS.SaleDate
};
VehiclesSaveAndDetails obj = new VehiclesSaveAndDetails();
obj._salesModle = objSalesModle;
obj._SalesDetailsTable = vehcileSalesDetails;
return View(obj);
}
MyView.
#model MvcApplication1.Models.VehiclesSaveAndDetails
#{
ViewBag.Title = "VehicleSaveAndDeatils";
}
<h2>VehicleSaveAndDeatils</h2>
<script src="#Url.Content("~/Scripts/jquery-1.12.4.js")" type="text/javascript"></script>
<script src="~/Scripts/jquery-1.12.4.js"></script>
<script type="text/javascript"
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
//Dropdownlist Selectedchange event
$('#ddlMake').change(function () {
// $("#ddlModel").empty();
$.ajax({
type: "POST",
url: "/iRateBook/FillModel",
dataType: "json",
traditional: true,
data: { makeId: $(this).val() },
success: function (data) {
//alert("hello"+data.Model[0]);
$("#ddlModel").empty();
$.each(data, function (i, data) { // bind the dropdown list using json result
$('<option>',
{
value: data.ModelId,
text: data.Model
}).html(data.CityName).appendTo("#ddlModel");
});
},
error: function (ex) {
alert('Failed to retrieve states.' + ex);
}
});
return false;
})
});
</script>
#{
ViewBag.Title = "CreateVehicleSalesView";
}
<h2>CreateVehicleSalesView</h2>
#using (Html.BeginForm("SaveVehcileSales", "iRateBook"))
{
<table>
<tr>
<td>Customer Name: </td>
<td>#Html.TextBoxFor(m => m._salesModle.CustomerName) </td>
</tr>
<tr>
<td>SSN</td>
<td>#Html.TextBoxFor(m => m._salesModle.SSN)</td>
</tr>
<tr>
<td>License Number</td>
<td>#Html.TextBoxFor(m => m._salesModle.LicenseId)</td>
</tr>
<tr>
<td>Age:</td>
<td>#Html.TextBoxFor(m => m._salesModle.Age)</td>
</tr>
<tr>
<td>City :</td>
<td>#Html.TextBoxFor(m => m._salesModle.City)</td>
</tr>
<tr>
<td>Select Make:</td>
<td>
#Html.DropDownListFor(m => m._salesModle.SelectedMake, Model._salesModle.MakesList, new
{
#id = "ddlMake"
})
</td>
</tr>
<tr>
<td>Select Model</td>
<td>#Html.DropDownListFor(m => m._salesModle.SelecteModle, new List<SelectListItem>(), new { #id = "ddlModel" })</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Save" /> </td>
</tr>
</table>
<br />
<br />
<table>
<tr>
<td>Name</td>
<td>Age</td>
<td>City</td>
<td>Make</td>
<td>Model</td>
<td>Sale Date</td>
</tr>
#foreach (var v in Model._SalesDetailsTable)
{
<tr>
<td>#v.CustomerName</td>
<td>#v.Age</td>
<td>#v.City</td>
<td>#v.MakeName</td>
<td>#v.ModelName</td>
<td>#v.SaleDate</td>
</tr>
}
</table>
}

For each loop with submitting form

Model Room:
public class Room
{
public int Id { get; set; }
public string NumberRoom { get; set; }
public double CostPerNight { get; set; }
public virtual Category Category { get; set; }
}
My view model code
public class RoomModel
{
public IList<Room> Rooms { get; set; }
}
My Razor code:
#model hotel.Models.RoomModel
#using (Html.BeginForm("ComfortLevelView", "Category"))
{
for (int i = 0; i < Model.Rooms.Count(); i++)
{
<table class="simple-little-table" cellspacing='0'>
<tr>
<td>#Html.DisplayFor(m => Model.Rooms[i].NumberRoom) </td>
<td>#Html.DisplayFor(m => Model.Rooms[i].Categoryid)</td>
<td>#Html.DisplayFor(m => Model.Rooms[i].NumberOfSeats) </td>
<td>
#{ var result = Model.Rooms[i].CostPerNight * numberNights; }
<p>#ViewBag.NumberNights ночей</p>:#result
</td>
<td>
<input type="submit" id="submit" value="Booking" />
</td>
</tr>
</table>
</div>
}
}
Controller:
public ActionResult ComfortLevelView(int NumberNights, int CategoryId, int NumberPeoples ,DateTime SelectedDate)
{
IRoomService roomService = new RoomService();;
return View(roomService.GetRoomsByCategory(CategoryId, SelectedDate, NumberNights, NumberPeoples));
}
[HttpPost]
public ActionResult ComfortLevelView(RoomModel model)
{
//
}
The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery`1[Hotel.BusinessObject.Room]', but this dictionary requires a model item of type 'hotel.Models.RoomModel'.
The error message is self explanatory. You have this in your view
#model hotel.Models.RoomModel
but you pass an instance of System.Data.Entity.Infrastructure.DbQuery<Hotel.BusinessObject.Room> to your view because of this line of code in your controller
return View(roomService.GetRoomsByCategory(CategoryId, SelectedDate, NumberNights, NumberPeoples));
You need to pass an instance of RoomModel instead of System.Data.Entity.Infrastructure.DbQuery<Hotel.BusinessObject.Room>. I would suggest changing your controller code to below
public ActionResult ComfortLevelView(int NumberNights, int CategoryId, int NumberPeoples, DateTime SelectedDate)
{
IRoomService roomService = new RoomService();
var rooms = roomService.GetRoomsByCategory(CategoryId, SelectedDate, NumberNights, NumberPeoples);
RoomModel model = new RoomModel();
model.Rooms = rooms.ToList();
return View(model);
}

ASP.net MVC 3 handling multiple checkboxes in each row of my table

I'm building an admin interface for a word guessing game so admin users are allowed to setup the game by selecting the words that will appear in the game and then select which letters in the words will be encoded.
MainGameTable Edit page.....
#model GameServer.ViewModels.GameTableModel
#section Javascript
{
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
}
#{
ViewBag.Title = "GameTableEdit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>GameTableEdit</h2>
#using (Html.BeginForm("GameTableEdit", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>GameTable</legend>
#Html.HiddenFor(model => model.GameTableId)
#Html.HiddenFor(model => model.GameTableNumber)
<div class="editor-label">
Table #: #Html.DisplayFor(model => model.GameTableNumber)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SubjectId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.SubjectId, new SelectList(Model.Subjects, "Key", "Value"))
#Html.ValidationMessageFor(model => model.SubjectId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ComplexityId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.ComplexityId, new SelectList(Model.Complexities, "Key", "Value"))
#Html.ValidationMessageFor(model => model.ComplexityId)
</div>
<button type="submit" name="button" value="GetWords">Get Words</button>
#Html.Partial("GameMatrix/_LineWordsTable", Model)
<p>
<button type="submit" name="button" value="Save">Save</button>
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Partial Page_for each of the words in the table
#model GameServer.ViewModels.GameTableModel
#if (Model.SelectedLinewords.Count != null && Model.SelectedLinewords.Count > 0)
{
<table>
<tr>
<th>
Select Word
</th>
<th>
LineWord
</th>
<th>
Characters to Display
</th>
</tr>
#Html.EditorFor(x => x.SelectedLinewords)
</table>
}
The Editor Template for each row:
#model GameServer.ViewModels.SelectedLineWord
<tr>
<td>
#Html.CheckBoxFor(x => x.isSelected)
</td>
<td>
#Html.DisplayFor(x => x.LineWord)
</td>
<td>
#Html.HiddenFor(x=>x.LineWordId)
#Html.HiddenFor(x=>x.LineWord)
#{ char[] lineword = Model.LineWord.ToCharArray(); }
#for (int i = 0; i < Model.LineWord.Length; i++)
{
<input type="checkbox" name="DisplayCharPosition" value="#i" /> #lineword[i]
}
</td>
</tr>
Here is my ViewModel
public class SelectedLineWord
{
[Required]
public Guid LineWordId { get; set; }
[Required]
public String LineWord { get; set; }
public int[] DisplayCharPosition { get; set; }
[Required]
public bool isSelected { get; set; }
public SelectedLineWord()
{
}
public SelectedLineWord(Guid linewordid, String word, String displaycharposition)
{
LineWordId = linewordid;
LineWord = word;
String[] pos = displaycharposition.Split(',');
DisplayCharPosition = new int[word.Length];
for (int i = 0; i < word.Length; i++)
{
DisplayCharPosition[i] = 0;
}
for (int i = 0; i < pos.Length; i++)
{
DisplayCharPosition[Int32.Parse(pos[i])] = 1;
}
}
public SelectedLineWord(Guid linewordid, String word, bool issel)
{
LineWordId = linewordid;
LineWord = word;
isSelected = issel;
}
}
public class GameTableModel
{
[Required]
public Guid GameTableId { get; set; }
[Required]
public Guid GameMatrixId { get; set; }
[Required]
[Display(Name = "Table Subject")]
public int SubjectId { get; set; }
[Required]
[Display(Name = "Minimum Complexity")]
public int ComplexityId { get; set; }
[Required]
public int GameTableNumber { get; set; }
[Required]
[Display(Name = "Include a Bonus table")]
public bool IsBonus { get; set; }
[Display(Name = "Table Subject")]
public Dictionary<int, string> Subjects;
[Display(Name = "Minimum Complexity")]
public Dictionary<int, int> Complexities;
public List<GameTableLine> GameTableLines { get; set; }
public List<SelectedLineWord> SelectedLinewords { get; set; }
public GameTableModel ()
{
try
{
//get a connection to the database
var data = new GameServerDataModelDataContext();
//Fetch the subjects reference data
var subjects = from c in data.Subjects orderby c.Subject1 select new { c.SubjectId, c.Subject1};
Subjects = new Dictionary<int, string>();
foreach (var subject in subjects)
{
Subjects.Add(subject.SubjectId, subject.Subject1);
}
//Fetch the complexities questions
Table<Complexity> dComplexities = data.GetTable<Complexity>();
Complexities = new Dictionary<int, int> { { 0, 0 } };
foreach (var complexity in dComplexities)
{
if (complexity.Complexity1 != null)
Complexities.Add(complexity.ComplexityId, (int)complexity.Complexity1);
}
}
catch (Exception ex)
{
//[TODO: Complete the exception handeling code.]
}
}
}
My problem is when I hit the save button the model passed to the controller has everything populated correctly but returns null for the check boxes that where selected for the DisplayCharPosition. What i was expecting was an int[] populated with the index of the character selected for display.
Could someone please help me understand what I'm doing wrong?
I've manage to solve this (but i'm still open to suggestions for a better way to do it).
What I did was I changed the following line <input type="checkbox" name="DisplayCharPosition" value="#i" /> #lineword[i] to #Html.CheckBoxFor(x => x.DisplayCharPosition[i]) #lineword[i] and my model type to public bool[] DisplayCharPosition { get; set; } so that i store an array of bools. Now the bool array has a true/false value for each char that the user wants to display in the game table. I then store this in the database as a comma delimited string (e.g. 1,4,6 - which i later split so i know that char in pos 1, 4 and 6 must be displayed and the rest encoded).
I also changed my model as follows:
public class SelectedLineWord
{
[Required]
public Guid LineWordId { get; set; }
[Required]
public String LineWord { get; set; }
public bool[] DisplayCharPosition { get; set; }
[Required]
public bool isSelected { get; set; }
public SelectedLineWord()
{
}
public SelectedLineWord(Guid linewordid, String word, String displaycharposition)
{
LineWordId = linewordid;
LineWord = word;
String[] pos = displaycharposition.Split(',');
DisplayCharPosition = new bool[word.Length];
//set all to false
for (int i = 0; i < word.Length; i++)
{
DisplayCharPosition[i] = false;
}
//now only set the ones that were already in the db.
for (int i = 0; i < pos.Length; i++)
{
DisplayCharPosition[Int32.Parse(pos[i])] = true;
}
}

Resources