ASP.NET MVC - Can't bind array to view model - asp.net-mvc

I have a view model with a from that includes a set of checkboxes. I need the check boxes to map to an array when binding in the post back method of my controller.
Here's the view model.
#model TMDM.Models.TestSeriesCreateViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create a Test Series</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<h3>Which Test Collections are in this Test Series?</h3>
<div class="editor-field">
#{
var i = 0;
foreach (var testCollection in Model.TestCollections)
{
<input type="checkbox" id="ChosenTestCollectionIds[#i]" name="ChosenTestCollectionIds[#i]" value="#testCollection.Id" />
<span>#testCollection.Title</span>
<br />
i++;
}
}
</div>
<p>
<input type="submit" value="Save" class="medium green awesome" />
#Html.ActionLink("Cancel", "Index", "TestSeries", null, new { #class = "medium black awesome" })
</p>
</fieldset>
The form is rendering fine, I've checked the source and each output check box has a different number for their id and name fields.
<input type="checkbox" id="ChosenTestCollectionIds[0]" name="ChosenTestCollectionIds[0]" value="5" />
<input type="checkbox" id="ChosenTestCollectionIds[1]" name="ChosenTestCollectionIds[1]" value="6" />
//etc...
Here is the view model.
public class TestSeriesModel
{
public int Id { get; set; }
public string Title { get; set; }
}
public class TestSeriesCreateViewModel : TestSeriesModel
{
public List<ITestCollectionDataObject> TestCollections { get; set; }
public int[] ChosenTestCollectionIds { get; set; }
}
Problem I'm having is that when the form posts back the ChosenTestCollectionIds array comes back null. What am I doing wrong here?
ANSWER
I've worked out how to do it:
<input type="checkbox" id="[#i]" name="ChosenTestCollectionIds" value="#testCollection.Id" />

<input type="checkbox" id="[#i]" name="ChosenTestCollectionIds" value="#testCollection.Id" />

I always come back to Phil Haack's post about model binding a list. In addition, I always define my own index because my user's will alter the list on the client side then post back the changes.
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Set the name of the input types to all be the same. You can also create a custom model binder if you are trying to bind a more complex model than just a list. Here is an excellent article on the different ways to bind to your models
Various Model Binding techniques

Related

How to configure Checkboxes Materialize Css in Web application Asp.Net MVC

How do I configure Checkboxes in Asp.Net MVC Razor.
Since in the documentation we have the following configuration Materialize for checkboxes :
<p>
   <label>
     <input type = "checkbox" />
     <span> Network </span>
   </label>
</p>
And in Razor I could not perform this configuration.
<div class = "input-field col s12">
        #Html.EditorFor (model => model.AnnualDestaque)
        #Html.LabelFor (model => model.AnnualDestaque)
        #Html.ValidationMessageFor (model => model.AnnualDestaque, "", new {#class = "text-danger"})
</div>
Please include model Name in your cshtml page
#model WebApplication3.Models.Test
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm("Save", "Home", FormMethod.Post))
{
<div class="row">
<div class="col-md-4">
#Html.TextBoxFor(m => m.EmployeeName)
#Html.CheckBoxFor(m=>m.IsSelected)
</div>
<input type="submit" value="Save" />
</div>
}
Model
public class Test
{
public string EmployeeName { get; set; }
public bool IsSelected { get; set; }
}
If you just want to have a checkbox binded with your model like that :
public class Network
{
public bool Selected { get; set; }
public string Name { get; set; }
}
Just use :
#Html.CheckBoxFor(m=>m.Selected)
#Html.LabelFor(m=>m.Name)
I was able to solve it, and I am passing the answer.
I used Html Helper Documentation Html Helper MVC
It worked perfectly without mistakes the way it's meant to be.
<div class="input-field col s12">
<label>
<input data-val="true"
data-val-required="The Advertisement field is required."
id="Advertisement"/**** m => m.Advertisement ****/
name="Advertisement"/**** m => m.Advertisement ****/
type="checkbox"
value="true" />
<span>Anuncio Destaque</span>
<input name="Advertisement" type="hidden" value="false" />
</label>
</div>
You can make it work doing this:
<label>
<input type="checkbox" name="FIELDNAME" id="FIELDNAME" value="true" class="filled-in" #(Model.FIELDNAME? "checked" : "") />
<span>#Html.DisplayNameFor(model => model.FIELDNAME)</span>
</label>
<input name="FIELDNAME" type="hidden" value="false" />

How to apply MVC validation attribute dynamically on <input type='Text'>

I have a ViewModel with [Required] and [MaxLength(4)] attribute
public class Student
{
[MaxLength(4)]
[Required]
public string Name { get; set; }
}
Inside my view I have
#model List<WebApplication2.Models.Student>
<div class="row">
<div class="col-md-4">
#{
foreach(var item in #Model)
{
#Html.TextBoxFor(model=>item.Name)
#Html.ValidationMessageFor(model => item.Name)
}
}
</div>
<div class="col-md-4">
#{
foreach (var item in #Model)
{
<input type="text" value="#item" />
}
}
</div>
When I use #Html helpers to render text boxes it applied data-validation rules to textbox. I couldn't figure out how I can apply that to normal Html <input type = 'text' /> Is there any way I can do that dynamically without using #Html helpers?

MVC3 - How to add dropdown to a form (Post) populated with different entity

Hi I am working in a MVC 3 application. I have a Create Form with following code.
#model Xrm.Student
#{
ViewBag.Title = "Create Student Record";
}
#using (Html.BeginForm("Create", "Student", FormMethod.Post))
{
<div class="editor-label">
#Html.LabelFor(model => #Model.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => #Model.FirstName)
#Html.ValidationMessageFor(model => #Model.FirstName)
</div>
<div>
<input id="Submit1" type="submit" value="Submit" />
</div>
}
I want to add a new drop down under Firsname field which should be populated with pubjects. Subject is different Entity. I could be very easy, but I am newbie with MVC so I just stuck here. Can anyone please suggest me the way to achieve it.
Thanks and Regards
I would define a view model:
public class MyViewModel
{
public Student Student { get; set; }
[DisplayName("Subject")]
[Required]
public string SubjectId { get; set; }
public IEnumerable<Subject> Subjects { get; set; }
}
and then have your controller populate and pass this view model to the view:
public ActionResult Create()
{
var model = new MyViewModel();
model.Student = new Student();
model.Subjects = db.Subjects;
return View(model);
}
and finally have your view strongly typed to the view model:
#model MyViewModel
#{
ViewBag.Title = "Create Student Record";
}
#using (Html.BeginForm())
{
<div class="editor-label">
#Html.LabelFor(x => x.Student.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(x => x.Student.FirstName)
#Html.ValidationMessageFor(x => x.Student.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(x => x.SubjectId)
</div>
<div class="editor-field">
#Html.DropDownListFor(
x => x.SubjectId,
new SelectList(Model.Subjects, "Id", "Name"),
"-- Subject --"
)
#Html.ValidationMessageFor(x => x.SubjectId)
</div>
<div>
<input type="submit" value="Submit" />
</div>
}
The "Id" and "Name" values I used for the SelectList must obviously be existing properties on your Subject class that you want to be used as respectively binding the id and the text of each option of the dropdown.

how can i get the text box for a view? in my controller

I follow this example to make n to n relations
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/updating-related-data-with-the-entity-framework-in-an-asp-net-mvc-application
it work fine but for the n to n relations with payload to the database i figure out and I can do the [HttpGet] and show the view what i want to show but now i want to know how can i get the textbox I have in my view, I can get the checkbox in my controller (see see below the action) and this is my view so my question will be how can get the textbox too? in my controller for every checkbox?
#using (Html.BeginForm("AgregarEmpresas", "Empleado"))
{
<fieldset>
<div class="editor-field">
<table>
<tr>
#{
int cnt = 0;
List<ITCOrganigrama.ViewModel.AsignarEmpresa> empresas = ViewBag.Empresas;
foreach (var empresa in empresas)
{
if (cnt++ % 5 == 0) {
#: </tr> <tr>
}
#: <td>
<input type="checkbox"
name="selectedEmpresa"
value="#empresa.EmpresaId"
#(Html.Raw(empresa.Assigned ? "checked=\"checked\"" : "")) />
#empresa.Nombre
<div>
#Html.LabelFor(model => empresa.cargo)
#Html.TextBoxFor(model => empresa.cargo, new { style = "width: 150px;" })
#Html.ValidationMessageFor(model => empresa.cargo)
</div>
#:</td>
}
#: </tr>
}
</table>
</div>
<p>
<input type="submit" value="Agregar" />
</p>
</fieldset>
}
the action where i get the chekbox
[HttpPost]
public ActionResult AgregarEmpresas(int? id, FormCollection formCollection, string[] selectedEmpresa)
{
}
my final view:
http://s3.subirimagenes.com:81/otros/previo/thump_7406511add1.jpg
http://www.subirimagenes.com/otros-add1-7406511.html
Edited:
ViewModel Class
public class AsignarEmpresa
{
public int EmpresaId { get; set; }
public string Nombre { get; set; }
public string cargo { get; set; }
public bool Assigned { get; set; }
}
Look at your post action and it's parameters. Names of those are really important.
Your checkboxes
<input type="checkbox"
name="selectedEmpresa"
value="#empresa.EmpresaId"
are working fine beacuse look at the name of the input its "selectedEmpresa" it's the same name as in Controller Action definition. Model binder looks for this name in posted data and if he finds it, he creates object from it. In your case he will try to parse data into string[] object.
So ... first of all you have to change action definition to something like.
[HttpPost]
public ActionResult AgregarEmpresas(int? id, FormCollection formCollection, string[] selectedEmpresa,string [] empresaTextBox)
{
}
Then you have to change generated html.
#Html.TextBoxFor(model => empresa.cargo, new { style = "width: 150px;", name="empresaTextBox" })
With those changes you should get some data inside Action. However you will get something weird beacuse you have multiple checkboxes and textboxes in order to tell model binder that there are multiple elements of those you have to prepare special name of inputs that contains index number.
Look at this example
<input name="childs[0]"></input>
<input name="childs[1]"></input>
In this case Model Binder will create array of objects that contains 2 of them.
So finally your code would have to look like this.
#using (Html.BeginForm("AgregarEmpresas", "Empleado"))
{
<fieldset>
<div class="editor-field">
<table>
<tr>
#{
int cnt = 0;
int i=0;
List<ITCOrganigrama.ViewModel.AsignarEmpresa> empresas = ViewBag.Empresas;
foreach (var empresa in empresas)
{
if (cnt++ % 5 == 0) {
#: </tr> <tr>
}
#: <td>
<input type="checkbox"
name="selectedEmpresa[#i]"
value="#empresa.EmpresaId"
#(Html.Raw(empresa.Assigned ? "checked=\"checked\"" : "")) />
#empresa.Nombre
<div>
#Html.LabelFor(model => empresa.cargo)
#Html.TextBoxFor(model => empresa.cargo, new { style = "width: 150px;" ,name=String.Format("empresaTextBox\[{0}\]",i) })
#Html.ValidationMessageFor(model => empresa.cargo)
</div>
#:</td>
i++;
}
#: </tr>
}
</table>
</div>
<p>
<input type="submit" value="Agregar" />
</p>
</fieldset>
}
If you will get this to work. Then i would try to create a class with one boolean and one string value. With this change you would operate on the array of classes instead of two arrays with strings.

MVC Model validation on "HttpPostedFileWrapper"

Can someone help me with model validation on a HttpPostedFileWrapper object?
Model:
[Required(AllowEmptyStrings = false)]
public HttpPostedFileWrapper BlahFile { get; set; }
Controller:
[HttpPost]
public ActionResult LoadBlahData(BlahModel blahModel)
{
if (!ModelState.IsValid)
return RedirectToAction("Index");
}
cshtml:
#using (Html.BeginForm("LoadBlahData", "Admin", FormMethod.Post, new { #class = "blahhForm", enctype = "multipart/form-data", id = "uploadBlah" }))
{
<fieldset>
<legend>Upload Blah Information</legend>
#Html.LabelFor(x=>x.BlahFile, "Upload Blah file:")
<input size="26" class="uploader" type="file" name="BlahFile" />
<p><input class="ttButton" type="submit" value="Load Stuff" /></p>
</fieldset>
}
Problem:
Cannot see the "data-val*" attributes being added to the html.
Does not set the unobtrusive validation off (red border on input box)
Notes:
Other items in the Model are working fine with validation, its only the <input type="file"/> that seems to be having problems.
Comes into the action method fine - (i.e - i can access the InputStream if i want).
All scripts are referenced correctly (its working on normal text input's)
Thanks in advance,
Just for anyone else coming across this question you can also do this -
<%: Html.TextBoxFor(x => x.BlahFile, new { type = "file" }) %>
you have not added any data attributes to your element. Add it like,
<input data-pk="1" size="26" class="uploader" type="file" name="BlahFile" />
and there is no support of validation of <input type="file"

Resources