ASP.NET MVC form without helper - asp.net-mvc

I would like to create a form in my asp.net MVC website, without using HTML helpers like #Html.EditorFor()...
I also want to use Jquery Mobile.
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset data-role="controlgroup" data-iconpos="right">
<legend>Languages :</legend>
<input type="checkbox" name="checkbox-h-6a" id="checkbox-h-6a">
<label for="checkbox-h-6a"></label>
<input type="checkbox" name="checkbox-h-6b" id="checkbox-h-6b">
<label for="checkbox-h-6b">French</label>
<input type="checkbox" name="checkbox-h-6c" id="checkbox-h-6c">
<label for="checkbox-h-6c">German</label>
</fieldset>
}
I would like to use it with my model. (for ex. "bool UseEnglish", "bool UseFrench",..)
How can I do it simply ?

The only thing the helpers really do is abstract the name attributes of the form fields away. If you don't want to use the helpers, you will just have to make sure the name attributes are set to the right thing so that they will match up to your model after POST.
For simple properties, the name is just the property name, so given:
public string Foo { get; set; }
You'd have an input like:
<input type="text" name="Foo">
For things like complex types or reference navigation properties, you'll just chain the property names together until you're at the level you need, so given:
public Foo Foo { get; set; }
And:
public class Foo
{
public string Bar { get; set; }
}
You'll end up with:
<input type="text" name="Foo.Bar">
Finally, for list-style properties, you'll just add an index, so given:
public List<string> Foos { get; set; }
Then:
<input type="text" name="Foos[0]">
<input type="text" name="Foos[1]">
<input type="text" name="Foos[2]">
And of course, you can put all of these principles together to model any relationship:
public List<Foo> Foos { get; set; }
Then:
<input type="text" name="Foos[0].Bar">

Related

.net MVC posting nested model to controller, data set is empty

<form method="post">
<input type="text" name="ClientList[0].ItemList[0].ItemID">
<input type="text" name="ClientList[0].ItemList[0].Qty">
<input type="text" name="ClientList[0].ItemList[1].ItemID">
<input type="text" name="ClientList[0].ItemList[1].Qty">
<input type="text" name="ClientList[1].ItemList[0].ItemID">
<input type="text" name="ClientList[1].ItemList[0].Qty">
<input type="text" name="ClientList[1].ItemList[1].ItemID">
<input type="text" name="ClientList[1].ItemList[1].Qty">
<input type="submit" />
</form>
This is controller
[HttpPost]
public ActionResult Sale(List<ClientList> ClientList)
{
return View();
}
public class ClientList
{
public List<ItemList> ItemList = new List<ItemList>();
}
public class ItemList
{
public int ItemID { get; set; }
public string Qty { get; set; }
}
This is result
the second loop, items details are not submitting.
Your ItemList is a field, not a property, and the DefaultModelBinder cannot set its value.
Change it to
public class ClientList
{
public List<ItemList> ItemList { get; set; }
}
As a side note, the name attributes can be just
<input type="text" name="[0].ItemList[0].ItemID">
which allows you to name the parameter in the POST method to anything you want (except ItemList)
I used a bit different approach, with named list
[HttpPost]
public ActionResult Sale(List<ClientList> ClientList)
{
return View();
}

get information from form to controller and save it in database

I have this code in my html.And i want to post this information from form to controler and save in data base.
<form method="POST" class="contactme form-group">
<input type="text" placeholder="Name" class="form-control inputcontact">
<input type="text" placeholder="Surename" class="form-control inputcontact">
<input type="email" placeholder="E-mail" class="form-control inputcontact">
<input type="tel" pattern="[0-9]{5,10}" class="form-control inputcontact" placeholder="tel. number"><br>
<input type="submit" class="btn btn-default buttonsend" value="Оставить заявку">
</form>
And i have this model:
public int Id { get; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Email { get; set; }
public string Phonenumber { get; set; }
The MVC concept is quite straight forward for achieving what you need. It's usual to have a model that contains properties for the data that you need to display a "View" and also for the content entered by the user so the data can be bound to the model when posted. If you've not got any controller code yet then I would recommend the below approach.
First, write a controller to handle the displaying of your view and the posting of the views form content.
public class YourController : Controller
{
[HttpGet]
public ActionResult YourViewName()
{
var myViewModel = new YourViewModel();
//Populate model data from services etc...
return View("YourViewName", myViewModel);
}
}
I find it easier to wrap my views data objects that it needs in a class.
public class YourViewModel
{
public string Property1 { get; set; }
public int Property2 { get; set; }
\\etc...
}
Then in your view, wrap your controls in a Form and use Html helper controls to display and bind to the data in the model.
#using (Html.BeginForm("ActionName", "YourController ", FormMethod.Post, new { id = "FormName"}))
{
#Html.TextBoxFor(x => x.YourModel.Property1, null, new { #class = "SomeCssClass"})
\\Repeat for all properties that need displaying or for user input.
}
You will also need a submit button on the form to post the form to your specified controller.
<button id="btnSubmitForm" type="Submit" class="SomeCssClass">Submit</button>
Then in your controller you create a method to receive the posted form (Model)
[HttpPost]
public ActionResult ActionName(YourViewModel postedContent)
{
//Handle saving etc.. here.
var x = postContent.Property1;
//Do something with data
//Re populate model and show updated view.
var myViewModel = new YourViewModel();
return View("YourViewName", myViewModel);
}
Thant should help you on your way. A lot of this is down to preference and opinions though.
You have to tell it which Controller and which Action in the controller to look for like below:
using (Html.BeginForm("YourActionMethodHere", "YourControllerHere", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<input type="text" placeholder="Name" class="form-control inputcontact">
<input type="text" placeholder="Surename" class="form-control inputcontact">
<input type="email" placeholder="E-mail" class="form-control inputcontact">
<input type="tel" pattern="[0-9]{5,10}" class="form-control inputcontact" placeholder="tel. number"><br>
<input type="submit" class="btn btn-default buttonsend" value="Оставить заявку">
}
This link should also help

Post viewmodel with List<T> to controller action method

I know there are a lot of posts out there regarding this, most of which I have read and tried all morning but still can't get it working.
I have a view model as such:
namespace GrantTracker.ViewModels
{
public class CoverPageViewModel
{
public List<Compliance> Compliances { get; set; }
}
}
I have a partial view that uses the view model:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<GrantTracker.ViewModels.CoverPageViewModel>" %>
<%
for (var i = 0; i < Model.Compliances.Count; i++)
{ %>
<%=Html.HiddenFor(x => x.Compliances[i].ComplianceId) %>
<%=Html.TextBoxFor(x => x.Compliances[i].ComplianceName) %>
<% } %>
This properly displays the text boxes and their values:
The generated source looks ok to me:
<input id="Compliances_0__ComplianceId" name="Compliances[0].ComplianceId" type="hidden" value="1" />
<input id="Compliances_0__ComplianceName" name="Compliances[0].ComplianceName" type="text" value="Human Subjects" />
<input id="Compliances_1__ComplianceId" name="Compliances[1].ComplianceId" type="hidden" value="2" />
<input id="Compliances_1__ComplianceName" name="Compliances[1].ComplianceName" type="text" value="Vertebrate Animals" />
<input id="Compliances_2__ComplianceId" name="Compliances[2].ComplianceId" type="hidden" value="3" />
<input id="Compliances_2__ComplianceName" name="Compliances[2].ComplianceName" type="text" value="Hazardous Substances" />
When I submit the page the textbox properties are as far as I can tell properly posted:
Compliances[0].ComplianceId:1
Compliances[0].ComplianceName:Human Subjects
Compliances[1].ComplianceId:2
Compliances[1].ComplianceName:Vertebrate Animals
Compliances[2].ComplianceId:3
Compliances[2].ComplianceName:Hazardous Substances
However, the values are all gone when accessed in the controller action
[HttpPost]
public ActionResult SaveCoverPage(CoverPageViewModel coverPageViewModel)
{
return Content(coverPageViewModel.Compliances[0].ComplianceId.ToString());
}
The debugger shows that it knows it should contain three Compliance objects.
However, when drilled down none of them have their values:
Any help with this would be greatly appreciated. I am really stuck on this.
Change your Compliance class as below.
public class Compliance
{
public int ComplianceId { get; set; }
public string ComplianceName { get; set; }
}
You should define properties correctly.

How to create an EditorFor a collection and avoid doing a loop

For example:
Model
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Editor Template for Person (PersonEditor.cshtml):
#model MvcApplication1.Models.Person
#Html.HiddenFor(x=>x.ID)
<label>First Name</label>
#Html.TextBoxFor(x=>x.FirstName)
<label>Last Name</label>
#Html.TextBoxFor(x=>x.LastName)
<br />
On my main page, I want to be able to do the following:
#model IList<MvcApplication1.Models.Person>
#using (Html.BeginForm())
{
#Html.EditorFor(x=>x,"PersonEditor")
}
And have all the elements in the form, generate the proper names automatically; instead of having to loop through the collection as I am doing now:
#using (Html.BeginForm())
{
for (int i = 0; i < Model.Count; i++)
{
#Html.EditorFor(x=>Model[i],"PersonEditor")
}
}
The form elements must contain the following format:
<input name="[0].ID" type="text" value="Some ID" />
<input name="[0].FirstName" type="text" value="Some value" />
<input name="[1].ID" type="text" value="Some x" />
<input name="[1].FirstName" type="text" value="Some y" />
And so on...
Because in my controller, I expect to receive an IList<Person> when the form posts pack.
Can I eliminate that for loop completely?
EDIT
Right now, when I simply do #Html.EditorFor(x=>x) (without the loop, in other words), I get this exception:
The model item passed into the dictionary is of type
'MvcApplication1.Models.Person[]', but this dictionary requires a
model item of type 'MvcApplication1.Models.Person'.
You should be able to use the same template for both IEnumerable<T> and T. The Templating is smart enough to enumerate the IEnumerable, but you will need to rename the editor template to match the type name. Then you should be able to use
#model IList<MvcApplication1.Models.Person>
#using (Html.BeginForm())
{
#Html.EditorForModel()
}
Unfortunately, it looks like a template named anything other than the type name will throw an exception
The model item passed into the dictionary is of type
'MvcApplication1.Models.Person[]', but this dictionary requires a
model item of type 'MvcApplication1.Models.Person'

Model binding two or more collections

Has anyone had any luck model binding two or more collections using the code posted by Phil Haack here: Model Binding To A List?
As an example, I have the below code.
public class Book {
public string Name { get; set; }
}
public class Author {
public string Name { get; set; }
}
public ActionResult Index(List<Book> books, List<Author> authors) {
// Will never model bind two collections.
}
The HTML that I have is:
<input type="hidden" name="books.index" value="1" />
<input type="text" name="books[1].Name" />
<input type="hidden" name="books.index" value="2" />
<input type="text" name="books[2].Name" />
<input type="hidden" name="authors.index" value="1" />
<input type="text" name="authors[1].Name" />
<input type="hidden" name="authors.index" value="1" />
<input type="text" name="authors[1].Name" />
The exception that I get is:
The parameters dictionary contains an invalid entry for parameter 'authors' for method 'System.Web.Mvc.ActionResult Index(System.Collections.Generic.List1[Book], System.Collections.Generic.List1[Author])' in 'HomeController'. The dictionary contains a value of type 'System.Collections.Generic.List1[Book]', but the parameter requires a value of type 'System.Collections.Generic.List1[Author]'. Parameter name: parameters
Am I doing something wrong or is this not supported by ASP.NET MVC?
Your problem is somewhere else, I was unable to reproduce. The following works fine for me:
Model:
public class Book
{
public string Name { get; set; }
}
public class Author
{
public string Name { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(List<Book> books, List<Author> authors)
{
return View();
}
}
View:
<% using (Html.BeginForm()) { %>
<input type="text" name="books[0].Name" value="book 1" />
<input type="text" name="books[1].Name" value="book 2" />
<input type="text" name="authors[0].Name" value="author 1" />
<input type="text" name="authors[1].Name" value="author 2" />
<input type="submit" value="OK" />
<% } %>
It successfully binds values back in the POST action.
UPDATE:
I confirm that this is a bug in ASP.NET MVC 3 RC2 which will be fixed in the RTM. As a workaround you could put the following in your Application_Start:
ModelMetadataProviders.Current = new DataAnnotationsModelMetadataProvider();

Resources