Post Model back to Server - asp.net-mvc

My aim is to export the clicked table, to excel (csv). This requires taking the Model on the page, and posting it to the server. But its providing difficult as its a list.
How do I post the Model in the View, to the controller.
Below is my code
View:
#model List<NameSpace.Property>
#using (Html.BeginForm("Export","Excel", FormMethod.Post))
{
<input type="submit" class="submit" value="Submit" />
}
<table .... />
Controller:
public void Export(List<Property> list)
{
}

As you did not state whether your table displays static data or dynamic data I have provided both solutions:
STATIC:
For example, if you request a url (lets say): /home/index/1. The table data is retrieved for that id (of 1) and then displayed in a table in the view.
If the information in the table does not change then you do not need to post any information back to the server. You should perform a GET request rather than a POST request to retrieve the CSV.
You would need to change the view to accept a model containing the original id that was requested and to use an action link rather than a form:
#model MyTableViewModel
#Html.ActionLink("Click here to export", "Export", "Excel", new { id = Model.Id });
<table .... />
Where the view model might be:
public class MyTableViewModel
{
public int Id { get; set; }
public List<Customer> Customers { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string Street { get; set; }
public string PostCode { get; set; }
}
Then your export controller action would be:
public FileContentResult Export(int id)
{
string csv = //Retrieve the information for the provided id and convert to csv format
return File(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv", "expostfilename.csv");
}
DYNAMIC:
The view model would no longer need the id so would become:
public class MyTableViewModel
{
public List<Customer> Customers { get; set; }
}
The view could be written:
#model MyTableViewModel
#using (Html.BeginForm("Export", "Home"))
{
<table>
<tbody>
#for (int i = 0; i < Model.Customers.Count; i++)
{
<tr>
<td>Name: #Html.TextBoxFor(m => m.Customers[i].Name)</td>
<td>Street: #Html.TextBoxFor(m => m.Customers[i].Street)</td>
<td>PostCode: #Html.TextBoxFor(m => m.Customers[i].PostCode)</td>
</tr>
}
</tbody>
</table>
<input type="submit" value="submit" />
}
And the controller export action:
public FileContentResult Export(MyTableViewModel vm)
{
string csv = //convert view model (vm) to csv
return File(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv", "expostfilename.csv");
}

Controller Action
public void Export(List<Property> list)
{
}
Property Class
public class Property
{
public string Name { get; set; }
public string Street { get; set; }
public string Postcode { get; set; }
}
Html Table
<table id="my-table">
<tbody>
<tr>
<td>Chris</td>
<td>Awesome Street</td>
<td>DH9 4LD</td>
</tr>
<tr>
<td>Sean</td>
<td>Lame Street</td>
<td>DH8 4SR</td>
</tr>
</tbody>
</table>
Jquery
<script type="text/javascript">
var aData = {};
$('#my-table tbody tr').each(function(index, value) {
aData['list[' + index + '].Name'] = $(value).children().eq(0).text();
aData['list[' + index + '].Street'] = $(value).children().eq(1).text();
aData['list[' + index + '].Postcode'] = $(value).children().eq(2).text();
});
$.post("#Url.Action("Export")", aData, function(data) {
});
</script>
This should be enough to get you started. Hope this helps
Update
Alternatively if you did not want a Jquery specific solution, you could output your data in hidden fields
<input type="hidden" name="[0].Name" value="Chris" />
<input type="hidden" name="[0].Street" value="..." />
<input type="hidden" name="[0].Postcode" value="...." />
<input type="hidden" name="[1].Name" value="Sean" />
<input type="hidden" name="[1].Street" value="..." />
<input type="hidden" name="[1].Postcode" value="...." />
and this would get submitted in your form

Related

SelectediAlertIndex from SelectTagHelper (apparently) not passed to Index.cshtml from LoadAlert(…) …RedirectToAction(“Index”,”Alerts”)

Struggling with getting the SelectedAlertIndex (int) from AspNetCore MVC view page:
#{
<h4>#Model.Alerts.Count Alerts</h4>
<form asp-controller="Alerts" asp-action="LoadAlert" method="post">
<select asp-for="SelectedAlertIndex" asp-items="#Model.Alert_Identifiers">
<option>Select one</option>
</select>
<br />
<input type="submit" name="LoadAlert" value="LoadAlert" />
</form>
}
thru AlertsController.cs:
[HttpPost]
public IActionResult LoadAlert(Alert obj, string LoadAlert)
{
if (!string.IsNullOrEmpty(LoadAlert))
{
ViewBag.Message = "Alert loaded successfully";
}
return RedirectToAction("Index", "Alerts")
}
to #foreach loop inside table in Views/Alerts/Index.cshtml:
#model IEnumerable<edxl_cap_v1_2.Models.ContentViewModels.Alert>
…
<table id="elementTable" class="smallText">
#foreach (var item in Model)
{
#*#while(item.AlertIndex == item.SelectedAlertIndex)
{*#
<tr>
Without the nested #while loop, the table of rows, one for each data element, displays all three records of 13 data elements each, but what I want is to display the set of 13 data elements for the one selected record using the int value of the AlertIndex selected from the Select Tag Helper dropdownlist. If I uncomment the #while loop only the border of the “elementTable” is displayed with no rows. This also happens when I try adding a “Where” clause to the #foreach loop:
#foreach (var item in Model.Where(item => item.AlertIndex == item.SelectedAlertIndex))
{
I’m trying to only show relevant code for the problem, but just in case it’s needed here’s the basic model:
public class AlertViewModel
{
public int SelectedAlertIndex { get; set; }
public List<SelectListItem> Alert_Identifiers { get; set; }
public List<AlertVm> Alerts { get; set; }
}
public class AlertVm
{
[Key]
public int AlertIndex { get; set; }
[MaxLength(150)]
public string Alert_Identifier { get; set; }
}
I decided it probably wasn’t needed to show the Alert class of 13 elements that I ended up adding to the view model, from the original Alert.cs class.
I needed to change value of asp-action in the form tag helper usage to Index:
#{
<h4>#Model.Alerts.Count Alerts</h4>
<form asp-controller="Alerts" asp-action="Index" method="post">
<select asp-for="SelectedAlertIndex" asp-items="#Model.Alert_Identifiers">
<option>Select one</option>
</select>
<br />
<input type="submit" name="Index" value="LoadAlert" />
</form>
}
Then I needed to make sure that SelectedAlertIndex was spelled the same in all instances; changed its type to Nullable int (int?); put a null check in the HttpPost Index() action; and add a Where condition:
[HttpPost]
public IActionResult Index(Alert obj, int? SelectedAlertIndex)
{
if (SelectedAlertIndex.HasValue)
{
ViewBag.Message = "Alert loaded successfully";
}
return View(_context.Alert.Where(x => x.AlertIndex == SelectedAlertIndex));
}
Many Thanks to #Shyju

Dynamically adding controls in MVC4

I am currently working on creating an MVC4 application where I want controls to be generated automatically from the database rows.
I have the table in my database containing the questions and the control type in which it should be answered by the user.
I am just thinking of a logic like
Where I can get the database rows in a dataset and then foreach it, then checking the type of control it belongs and then creating the control in my View.
This is my Controller action:
Public ActionResult Index()
{
// get the rows from the table
foreach(Iterate the rows)
{
if(controllerType1)
{
//stmnts
}
if(controllerType2)
{
//stmnts
}
}
return View();
}
This is just an idea of how can we build the solution. If I am going in the right way please guide me, else I am eager to know the possibilities where I can build my solution in different ways :).
You can create a editor template and pass the control list as model to the template and in the template you can iterate that list to generate the control. As i have shown below.
1->Create a class for Control Information.
public class ControlInfo
{
public string ControlType { get; set; }
public string ControlID { get; set; }
public string ControlName { get; set; }
public string ControlValue { get; set; }
public string ControlLabel { get; set; }
public bool IsChecked { get; set; }
}
2->Create an Editor Template (Partial view with control name say CustomControl.cshtml) in \Views\Shared\EditorTemplates path.
#model List<MvcApplication2.Models.ControlInfo>
<table>
#foreach (MvcApplication2.Models.ControlInfo ControlInfo in Model)
{
<tr>
<td>#ControlInfo.ControlLabel</td>
<td>
#switch (ControlInfo.ControlType.ToLower())
{
case "textbox":
<input type="text" name="#ControlInfo.ControlName" id="#ControlInfo.ControlID" value="#ControlInfo.ControlValue" />
break;
case "checkbox":
if (ControlInfo.IsChecked)
{
<input type="checkbox" name="#ControlInfo.ControlName" id="#ControlInfo.ControlID" value="#ControlInfo.ControlValue" checked="checked" />
}
else
{
<input type="checkbox" name="#ControlInfo.ControlName" id="#ControlInfo.ControlID" value="#ControlInfo.ControlValue" checked="checked" />
}
break;
default:
break;
}
</td>
</tr>
}
</table>
3->Create a model for main view (say HomeModel).
public class HomeModel
{
public List<ControlInfo> ControlList { get; set; }
public void PolulateControlList()
{
//You can fill this list from database.
// For example i have filled the list manually.
ControlList = new List<ControlInfo>();
ControlList.Add(new ControlInfo() {ControlType="TextBox",ControlName="tbox1", ControlID="tbox1", ControlLabel="Name", ControlValue="Martin" });
ControlList.Add(new ControlInfo() { ControlType = "CheckBox", ControlName = "cbox1", ControlID = "cbox1", ControlLabel="Is Correct", ControlValue = "Yes", IsChecked=true });
}
}
4->Consume the editor template in the main view as.
#model MvcApplication2.Models.HomeModel
#{
ViewBag.Title = "Home Page";
}
#Html.EditorFor(model=>model.ControlList,"CustomControl")
5-> Call the main view in the controller ( Index here).
public ActionResult Index()
{
HomeModel ModelObj = new HomeModel();
ModelObj.PolulateControlList();
return View(ModelObj);
}
Edit 1:
For getting the posted value you need to modify the Editor Templates as below. The model properties whose name is equal to the name of the control posted as name value collection , will get automatically binded by the model binder of the mvc frame work, so for each property in the control collection i have created hidden tags and one input tag for the input value.
#model List<MvcApplication2.Models.ControlInfo>
<table>
#{ var index = -1;}
#foreach (MvcApplication2.Models.ControlInfo ControlInfo in Model)
{
index++;
<tr>
<td>#ControlInfo.ControlLabel</td>
<td>
<input type="hidden" name="#("ControlList[" + index + "].ControlID")" value="#ControlInfo.ControlID" />
<input type="hidden" name="#("ControlList[" + index + "].ControlLabel")" value="#ControlInfo.ControlLabel" />
<input type="hidden" name="#("ControlList[" + index + "].ControlName")" value="#ControlInfo.ControlName" />
<input type="hidden" name="#("ControlList[" + index + "].ControlType")" value="#ControlInfo.ControlType" />
#switch (ControlInfo.ControlType.ToLower())
{
case "textbox":
<input type="text" name="#("ControlList["+index+"].ControlValue")" id="#ControlInfo.ControlID" value="#ControlInfo.ControlValue" />
break;
case "checkbox":
<input type="hidden" name="#("ControlList[" + index + "].ControlValue")" value="#ControlInfo.ControlValue" />
if (ControlInfo.IsChecked)
{
<input type="checkbox" name="#("ControlList[" + index + "].IsChecked")" id="#ControlInfo.ControlID" value="true" checked="checked" />
}
else
{
<input type="checkbox" name="#("ControlList[" + index + "].IsChecked")" id="#ControlInfo.ControlID" value="true" />
}
break;
default:
break;
}
</td>
</tr>
}
</table>
And in the main view you need to have form
#model MvcApplication2.Models.HomeModel
#{
ViewBag.Title = "Home Page";
}
#using(Html.BeginForm()){
#Html.EditorFor(model=>model.ControlList,"CustomControl")
<input type="submit" name="name" value="Submit" />
}
And in controller you need to have corresponding post method
[HttpPost]
public ActionResult Index(HomeModel ModelObj)
{
// Your logic..........
return View(ModelObj);
}
This ModelObj will have the posted values.

MVC post a list of complex objects

I have a FeedbackViewModel that contains a list of questions:
public class FeedbackViewModel
{
public List<QuestionViewModel> Questions { get; set; }
}
This QuestionViewModel is an object that can be inherited by 5 different types of questions
public class QuestionViewModel
{
public string QuestionText { get; set; }
public string QuestionType { get; set; }
}
An example of one of the inheriting question types:
public class SingleQuestionViewModel : QuestionViewModel
{
public string AnswerText { get; set; }
}
In the HttpGet of the Index action in the controller I get the questions from the database and add the correct question type in list of question in the FeedbackViewModel Then I render this model in the view:
#using (Html.BeginForm())
{
//foreach (var item in Model.Questions)
for (int i = 0; i < Model.Questions.Count; i++)
{
<div class="form-group">
#Html.DisplayFor(modelItem => Model.Questions[i].QuestionText, new { #class = "control-label col-md-4" })
<div class="col-md-6">
#if (Model.Questions[i].QuestionType == "Single")
{
#Html.EditorFor(modelItem => (Model.Questions[i] as OpenDataPortal.ViewModels.SingleQuestionViewModel).AnswerText)
}
else if (Model.Questions[i].QuestionType == "Multiple")
{
#Html.TextAreaFor(modelItem => (Model.Questions[i] as OpenDataPortal.ViewModels.SingleQuestionViewModel).AnswerText)
}
else if (Model.Questions[i].QuestionType == "SingleSelection")
{
#Html.RadioButtonForSelectList(modelItem => (Model.Questions[i] as OpenDataPortal.ViewModels.SingleSelectionQuestionViewModel).SelectedAnswer,
(Model.Questions[i] as OpenDataPortal.ViewModels.SingleSelectionQuestionViewModel).SelectionAnswers)
}
else if (Model.Questions[i].QuestionType == "MultipleSelection")
{
#Html.CustomCheckBoxList((Model.Questions[i] as OpenDataPortal.ViewModels.MultipleSelectionQuestionViewModel).AvailableAnswers)
}
else if (Model.Questions[i].QuestionType == "UrlReferrer")
{
#Html.EditorFor(modelItem => (Model.Questions[i] as OpenDataPortal.ViewModels.SingleQuestionViewModel).AnswerText)
}
</div>
</div>
<br />
}
<br />
<button type="submit">Submit</button>
}
Now, I simply can't get it to post the list of questions in the model. Is it even possible to post a list of different object types?
Edit: Following is the list of data within the post that I discovered using Fiddler:
After much research I've found two solutions:
One is to write HTML that has hardcoded Id's and Names
Two is to convert your ICollection/IEnumerable to an Array or List (i.e IList something with an 'index'), and have an Array object in your BindingModel in your Controller POST Action.
Thanks to Phil Haack's (#haacked) 2008 blog post http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
Which is still relevant to how the default ModelBinder works today for MVC.
(NB: the links in Phil's article to sample porject and extension methods are broken)
HTML snippet that inspired me:
<form method="post" action="/Home/Create">
<input type="hidden" name="products.Index" value="cold" />
<input type="text" name="products[cold].Name" value="Beer" />
<input type="text" name="products[cold].Price" value="7.32" />
<input type="hidden" name="products.Index" value="123" />
<input type="text" name="products[123].Name" value="Chips" />
<input type="text" name="products[123].Price" value="2.23" />
<input type="submit" />
</form>
Post array looks a bit like:
products.Index=cold&products[cold].Name=Beer&products[cold].Price=7.32&products.Index=123&products[123].Name=Chips&products[123].Price=2.23
Model:
public class CreditorViewModel
{
public CreditorViewModel()
{
this.Claims = new HashSet<CreditorClaimViewModel>();
}
[Key]
public int CreditorId { get; set; }
public string Comments { get; set; }
public ICollection<CreditorClaimViewModel> Claims { get; set; }
public CreditorClaimViewModel[] ClaimsArray {
get { return Claims.ToArray(); }
}
}
public class CreditorClaimViewModel
{
[Key]
public int CreditorClaimId { get; set; }
public string CreditorClaimType { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:N2}")]
public Decimal ClaimedTotalAmount { get; set; }
}
Controller GET:
public async Task<ActionResult> Edit(int id)
{
var testmodel = new CreditorViewModel
{
CreditorId = 1,
Comments = "test",
Claims = new HashSet<CreditorClaimViewModel>{
new CreditorClaimViewModel{ CreditorClaimId=1, CreditorClaimType="1", ClaimedTotalAmount=0.00M},
new CreditorClaimViewModel{ CreditorClaimId=2, CreditorClaimType="2", ClaimedTotalAmount=0.00M},
}
};
return View(model);
}
Edit.cshtml:
#Html.DisplayNameFor(m => m.Comments)
#Html.EditorFor(m => m.Comments)
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(m => Model.Claims.FirstOrDefault().CreditorClaimType)
</th>
<th>
#Html.DisplayNameFor(m => Model.Claims.FirstOrDefault().ClaimedTotalAmount)
</th>
</tr>
<!--Option One-->
#foreach (var item in Model.Claims)
{
var fieldPrefix = string.Format("{0}[{1}].", "Claims", item.CreditorClaimId);
<tr>
<td>
#Html.DisplayFor(m => item.CreditorClaimType)
</td>
<td>
#Html.TextBox(fieldPrefix + "ClaimedTotalAmount", item.ClaimedTotalAmount.ToString("F"),
new
{
#class = "text-box single-line",
data_val = "true",
data_val_number = "The field ClaimedTotalAmount must be a number.",
data_val_required = "The ClaimedTotalAmount field is required."
})
#Html.Hidden(name: "Claims.index", value: item.CreditorClaimId, htmlAttributes: null)
#Html.Hidden(name: fieldPrefix + "CreditorClaimId", value: item.CreditorClaimId, htmlAttributes: null)
</td>
</tr>
}
</table>
<!--Option Two-->
#for (var itemCnt = 0; itemCnt < Model.ClaimsArray.Count(); itemCnt++)
{
<tr>
<td></td>
<td>
#Html.TextBoxFor(m => Model.ClaimsArray[itemCnt].ClaimedTotalAmount)
#Html.HiddenFor(m => Model.ClaimsArray[itemCnt].CreditorClaimId)
</td></tr>
}
Form is processed in the Controller:
Post Model:
public class CreditorPostViewModel
{
public int CreditorId { get; set; }
public string Comments { get; set; }
public ICollection<CreditorClaimPostViewModel> Claims { get; set; }
public CreditorClaimPostViewModel[] ClaimsArray { get; set; }
}
public class CreditorClaimPostViewModel
{
public int CreditorClaimId { get; set; }
public Decimal ClaimedTotalAmount { get; set; }
}
Controller:
[HttpPost]
public ActionResult Edit(int id, CreditorPostViewModel creditorVm)
{
//...
Make sure you are rendering your view in order so that Model.Questions[i] renders in order.
For example, Model.Questions[0], Model.Questions[1], Model.Questions[2].
I noticed that if the order is not correct mvc model binder will only bind the first element.
Thanks for pointing me in the right direction with this post. I was struggling to get the syntax right for binding a non-sequential IDictionary<string, bool> object. Not sure this is 100% correct, but this Razor code worked for me:
<input type="hidden" name="MyDictionary.Index" value="ABC" />
<input type="hidden" name="MyDictionary[ABC].Key" value="ABC" />
#Html.CheckBox(name: "MyDictionary[ABC].Value", isChecked: Model.MyDictionary["ABC"], htmlAttributes: null)
If you need a checkbox, be sure to use Html.CheckBox instead of a standard HTML checkbox. The model will blow up if a value is not provided, and Html.CheckBox generates a hidden field to ensure a value is present when the checkbox is not checked.
Using Razor you can implement the for loop using a dictionary as follows without making changes to your object:
#foreach (var x in Model.Questions.Select((value,i)=>new { i, value }))
{
if (Model.Questions[x.i].QuestionType == "Single")
{
#Html.EditorFor(modelItem => (modelItem.Questions[x.i] as OpenDataPortal.ViewModels.SingleQuestionViewModel).AnswerText)
}
...
}
The collection needs to be either a List or Array for this to work.
I use this code maybe its can help
<input type="hidden" name="OffersCampaignDale[#(item.ID)].ID" value="#(item.ID)" />
#Html.Raw(Html.EditorFor(modelItem => item.NameDale, new { htmlAttributes = new { #class = "form-control" } })
.ToString().Replace("item.NameDale", "OffersCampaignDale[" + item.ID+ "].NameDale").Replace("item_NameDale", "NameDale-" + item.ID))
#Html.ValidationMessageFor(modelItem => item.NameDale, "", new { #class = "text-danger" })

Passing values of checkboxes from View to Controller

I have a view with a number of checkboxes in it. I want to be able to pass the values of the checkboxes to the controller, then output a list of the OfficeNames that have been ticked. I am not sure how to pass the values of multiple checkboxes back to the controller, or how to output the OfficeNames based on which boxes have been ticked
View:
<p>
#using (Html.BeginForm())
{
<p>
Start Date: #Html.TextBox("StartDate") <br />
<br />
End Date: #Html.TextBox("EndDate") <br />
<br />
<input type="submit" value="Filter" />
</p>
}
<p>
#foreach (var item in Model.BettingOffices)
{
<label>#Html.DisplayFor(modelItem => item.OfficeName)</label>
<input type="checkbox" name="selectedShops" value="#item.OfficeName">
}
</p>
Controller:
public class DailyReportController : Controller
{
private RiskEntities _db = new RiskEntities();
// GET: /DailyReport/
public ActionResult Index(DateTime? startDate, DateTime? endDate)
{
if (startDate == null || endDate == null)
{
var dailyReportModelBlank = new DailyReportModel();
dailyReportModelBlank.BettingOffices = (from bo in _db.BettingOffices orderby bo.OfficeName select bo ).ToList();
//dailyReportModelBlank.DailyReports.Add(new DailyReport());
return View(dailyReportModelBlank);
}
var endDateToUse = (DateTime) endDate;
endDateToUse = endDateToUse.AddDays(+1);
var dailyReportModel = new DailyReportModel
{
DailyReports = (from dr in _db.DailyReports
where dr.DailyReportDate >= startDate
&& dr.DailyReportDate <= endDateToUse
select dr).ToList(),
BettingOffices = (from bo in _db.BettingOffices select bo).ToList()
};
return View(dailyReportModel);
}
Model:
public class DailyReportModel
{
private List<DailyReport> _dailyReports = new List<DailyReport>();
private List<BettingOffice> _bettingOffices = new List<BettingOffice>();
public List<DailyReport> DailyReports
{
get { return _dailyReports; }
set { _dailyReports = value; }
}
public List<BettingOffice> BettingOffices
{
get { return _bettingOffices; }
set { _bettingOffices = value; }
}
}
BettingOffice Class:
public partial class BettingOffice
{
public int BettingOfficeID { get; set; }
public string OfficeName { get; set; }
public string OfficeCode { get; set; }
public string IpAddress { get; set; }
public Nullable<bool> SupportOnly { get; set; }
public Nullable<int> SisSrNumer { get; set; }
public Nullable<bool> Local { get; set; }
public string Server { get; set; }
}
try this :
<p>
#using (Html.BeginForm())
{
<p>
Start Date: #Html.TextBox("StartDate")
<br />
<br />
End Date: #Html.TextBox("EndDate")
<br />
<br />
<input type="submit" value="Filter" />
</p>
}
</p>
<p>
#foreach (var item in Model.BettingOffices)
{
<label>#Html.DisplayFor(modelItem => item.OfficeName)</label>
<input type="checkbox" name="bettingOfficeIDs" value="#item.BettingOfficeID">
}
</p>
And in your Action you can get the selected office ids in bettingOfficeIDs variable:
public ActionResult YourActionName(int[] bettingOfficeIDs)
Few things that need to change here.
If you want values to be passed to action method they need to be within form not outside
For MVT to 'understand' checkbox values as array (or more complex object) you need to work with their html name attribute.
I will do demonstration application below that should help you understand how it works:
CsHtml: Notice that you need to add value attribute to checkboxes to be able to read their values, checkbox gets true only when checkbox is ticked and value is true, hence the javascript. You can add as many of complex object properties as hidden fields as long as you give them names that match to the object property names in viewModel. In this case I am only passing BettingOfficeID
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
$(document).on("click", "[type='checkbox']", function(e) {
if (this.checked) {
$(this).attr("value", "true");
} else {
$(this).attr("value","false");}
});
<p>
#using (Html.BeginForm())
{
<p>
Start Date: #Html.TextBox("StartDate") <br />
<br />
End Date: #Html.TextBox("EndDate") <br />
<br />
</p>
<p>
<input type="checkbox" name="BettingOffices[0].Selected" value="true">
<input type="hidden" name="BettingOffices[0].BettingOfficeID" value="1">
<input type="checkbox" name="BettingOffices[1].Selected" value="false">
<input type="hidden" name="BettingOffices[1].BettingOfficeID" value="2">
<input type="checkbox" name="BettingOffices[2].Selected" value="true">
<input type="hidden" name="BettingOffices[2].BettingOfficeID" value="3">
<input type="checkbox" name="BettingOffices[3].Selected" value="false">
<input type="hidden" name="BettingOffices[3].BettingOfficeID" value="4">
<input type="checkbox" name="BettingOffices[4].Selected" value="true">
<input type="hidden" name="BettingOffices[4].BettingOfficeID" value="5">
</p>
<input type="submit" value="submit"/>
}
Post Action method to add to controller
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(BettingViewModel viewModel)
{
return null;
}
BettingViewModel: I have added Selected property to BettingOffice class.
public class BettingViewModel
{
public string StartDate { get; set; }
public string EndDate { get; set; }
public List<BettingOffice> BettingOffices { get; set; }
}
public class BettingOffice
{
public bool Selected { get; set; }
public int BettingOfficeID { get; set; }
public string OfficeName { get; set; }
public string OfficeCode { get; set; }
public string IpAddress { get; set; }
public Nullable<bool> SupportOnly { get; set; }
public Nullable<int> SisSrNumer { get; set; }
public Nullable<bool> Local { get; set; }
public string Server { get; set; }
}
Hope this saves you some time.
View:
#using (Html.BeginForm("Createuser", "User", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Create a new account.</h4>
<div class="form-group">
#Html.LabelFor(m => m.city, new { #class = "col-md-2 control-label" })
</div>
<div class="col-md-10">
<table>
<tr>
<td><input type="checkbox" name="city" value="Pune" id="1" />Pune</td>
<td><input type="checkbox" name="city" value="Banglore" id="2" />Banglore</td>
<td><input type="checkbox" name="city" value="Mumbai" id="3" />Mumbai</td>
</tr>
</table>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Create" />
</div>
</div>
}
[HttpPost]
public ActionResult Createuser(user user, string [] city)
{
var UserInfo = new user
{ Email =user.Email,Password=user.Password,Firstname=user.Firstname };
return View();
}
1. First of all, you are generating checkboxes with same name. So how you will be able to retrieve them on server end separately?
So declare some counter that gets incremented and name checkboxes uniquely.
#foreach (var item in Model.BettingOffices)
{
int counter=1;
var checkboxName = "selectedShops" + counter;
<label>#Html.DisplayFor(modelItem => item.OfficeName)</label>
<input type="checkbox" name="#checkboxName" value="#item.OfficeName">
counter++;
}
2. Now on submission of Form in your controller, get checkboxes as -
//Loop through the request.forms
for (var i = 0; i <= Request.Form.Count; i++)
{
var checkboxValue = Request.Form["selectedShops[" + i + "]"];
// Do whatever you want to with this checkbox value
}
For ticked values, you will probably get True value. Debug the retrieved value to write further code accordingly.
Try the following
your View is:
#foreach (var item in Model.BettingOffices)
{
<label>#Html.DisplayFor(modelItem => item.OfficeName)</label>
<input type="checkbox" name="selectedShops" value="#item.OfficeName">
}
Controller
[HttpPost]
public ActionResult Index(FormCollection collection)
{
if(!string.IsNullOrEmpty(collection["selectedShops"]))
{
string strSelectedShops = collection["selectedShops"];
}
}
Hi you can get the selected checkbox value using the bellow code it seem working fine fore me,
<script>
$(document).ready(function()
{
$("input[type=checkbox]").click(function()
{
var categoryVals = [];
categoryVals.push('');
$('#Category_category :checked').each(function() {
categoryVals.push($(this).val());
});
$.ajax({
type:"POST",
url:"<?php echo $this->createUrl('ads/searchresult'); ?>", //url of the action page
data:{'category': categoryVals},
success : function(response){
//code to do somethng if its success
}
});
}
}
</script>

How to pass list from view to controller

I have problem when pass a list in an object from view to controller, the list is always null. How should I do this?
My model:
public class ImageModel
{
public int id { get; set; }
public string url { get; set; }
public bool delete { get; set; }
}
public class SchoolImages
{
public Nullable<int> schoolid { get; set; }
public IList<ImageModel> images;
}
The view:
#model SchoolAppManager.Models.SchoolImages
#using (Html.BeginForm("DeleteImages", "Images"))
{
#Html.HiddenFor(x => x.schoolid)
<table>
#for (int i = 0; i < Model.images.Count(); i += 4) {
<tr>
<td>
<img src="#Url.Content(Model.images[i].url)" width="50%" />
<br />
#Html.CheckBoxFor(x => x.images[i].delete)
#Html.HiddenFor(x => x.images[i].id)
</td>
<td>
#if (i + 1 < Model.images.Count())
{
<img src="#Url.Content(Model.images[i + 1].url)" width="50%" />
<br />
#Html.CheckBoxFor(x => x.images[i + 1].delete)
#Html.HiddenFor(x => x.images[i + 1].id)
}
</td>
<td>
#if (i + 2 < Model.images.Count())
{
<img src="#Url.Content(Model.images[i + 2].url)" width="50%" />
<br />
#Html.CheckBoxFor(x => x.images[i + 2].delete)
#Html.HiddenFor(x => x.images[i + 2].id)
}
</td>
<td>
#if (i + 3 < Model.images.Count())
{
<img src="#Url.Content(Model.images[i + 3].url)" width="50%" />
<br />
#Html.CheckBoxFor(x => x.images[i + 3].delete)
#Html.HiddenFor(x => x.images[i + 3].id)
}
</td>
</tr>
}
</table>
<input type="submit" value="delete" />
}
When I click delete, SchoolImages is passed to the controller, SchoolImages.schoolId has value in the controller, however, SchoolImages.images is null. How can I pass SchoolImages.images to controller?
Default model binder doesn't work with fields, so make images a property:
public IList<ImageModel> images { get; set; }
I guess you will have problem binding complex types to your model. In case you don't get that working. Here is the alternative way.
You have a bunch of checkboxes, possibly with the same name and different values. You could post them to a method that takes a FormCollection, ie.
public ActionResult Test(FormCollection collection)
{
string results = collection["Blanks"];
}
This would give you a comma-delimited list of values (or null, where no checkboxes are ticked).
Alternatively, if you have the possible values as an array on the server then you could give the checkboxes names according to their array values, which would mean you could do something like this:
#using (Html.BeginForm("Test","Home"))
{
#Html.CheckBox("Blanks[0]", false);
#Html.CheckBox("Blanks[1]", false);
#Html.CheckBox("Blanks[2]", false);
<input type="submit" value="Submit" />
}
giving you an array of booleans in your Test method:
public ActionResult Test(bool[] Blanks)
{ }
Try changing your model "SchoolImages"; use array instead of IList<>.
It's null because the default model binder doesn't know how to initialize it.
Change your field images to be a property and add a constructor like this:
public class SchoolImages
{
public SchoolImages()
{
images = new List<ImageModel>();
}
public Nullable<int> schoolid { get; set; }
public IList<ImageModel> images { get; set; }
}
It should work.

Resources