I'm trying to use Ajax.BeginForm but without any success. I cannot get my form to work properly. My Controller Action "UpdateTest" is never called I don't know why. I followed many tutorial but still get the same problem. Thank you for your help !
My Model:
public class TestModel
{
public ObjectId _id { get; set; }
public int orange { get; set; }
public int blue { get; set; }
public int red { get; set; }
public int yellow { get; set; }
public int white { get; set; }
public float green { get; set; }
public float pink { get; set; }
}
My Action in ColorController
[HttpPost]
public void UpdateTest(TestModel tmp)
{
...
...
}
My View
#model Project.Models.TestModel
#using (Ajax.BeginForm(new AjaxOptions()
{
HttpMethod = "POST",
Url = Url.Action("UpdateTest", "Color")
}))
{
#Html.TextBoxFor(model => model._id)
#Html.TextBoxFor(model => model.orange)
#Html.TextBoxFor(model => model.blue)
#Html.TextBoxFor(model => model.red)
#Html.TextBoxFor(model => model.yellow)
#Html.TextBoxFor(model => model.white)
#Html.TextBoxFor(model => model.green)
#Html.TextBoxFor(model => model.pink)
<input type="submit" value="Submit" />
}
Javascript
<script type="text/javascript" src="/Scripts/jquery.unobtrusive-ajax.min.js">
</script>
Try it this way....
#using (Ajax.BeginForm("UpdateTest", "Color", new AjaxOptions() { HttpMethod = "POST" }))
{
#Html.TextBoxFor(model => model._id)
#Html.TextBoxFor(model => model.orange)
#Html.TextBoxFor(model => model.blue)
#Html.TextBoxFor(model => model.red)
#Html.TextBoxFor(model => model.yellow)
#Html.TextBoxFor(model => model.white)
#Html.TextBoxFor(model => model.green)
#Html.TextBoxFor(model => model.pink)
<input type="submit" value="Submit" />
}
Related
I've got a model:
public class PersonViewModel
{
public int Id { get; set; }
[MaxLength(25)]
public string Firstname { get; set; }
[MaxLength(50)]
public string Surname { get; set; }
}
And a ViewModel to contain one instance and a list of the above:
public class PeopleSearchViewModel
{
public PersonViewModel Person { get; set; }
public List<PersonViewModel> People { get; set; }
}
Then my View:
#model PeopleSearchViewModel
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
#Html.LabelFor(m => m.Person.Firstname)
#Html.HiddenFor(m => m.Person.Firstname)
#Html.TextBoxFor(m => m.Person.Firstname)
#Html.ValidationMessageFor(m => m.Person.Firstname)
<input type="submit" value="Search" id="Whatever"/>
}
And finally the controller:
[HttpPost]
public ActionResult Search(PeopleSearchViewModel theModelIsntPassing)
{
}
The model is not being passed to the controller on form submission?
Or maybe it is, but the individual properties aren't populated.
The ActionResult Search method is definitely being called, just theModelIsntPassing has no values in its nested property
Not sure why you are having both HiddenFor and TextBoxFor for FirstName.
Please try comment/remove #Html.HiddenFor(m => m.Person.Firstname) statement in your view
#model PeopleSearchViewModel
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
#Html.LabelFor(m => m.Person.Firstname)
#*#Html.HiddenFor(m => m.Person.Firstname)*#
#Html.TextBoxFor(m => m.Person.Firstname)
#Html.ValidationMessageFor(m => m.Person.Firstname)
<input type="submit" value="Search" id="Whatever"/>
}
I've been around this for a couple of time and I would love if possible for a couple of "fresh" pair of eyes to look at this.
In my app I have a form where I use a model with some primitive types and two lists. Also I'm using a Kendo grid.
My problem is that when the user does Submit, the model arrives ok but one of the two lists returns with 0 elements...! (never null)
The list that arrives ok is the one I'm creating in the Kendo Grid.
The list that returns empty is List ProductItemlist, that is generated in the partial view (also tried not using the partial view).
The thing is, on the controller if I do:
string test = Request.Form["ProductItemlist[0].ProductItemId"],
I get the values I want, so the problem I think must be in the mapping.
Nevertheless I'm failing in discovering it....
What's happenning...? Thanks in advance for any help!
My Model:
public class PurchaseRegistrationProductEditVM
{
public int ClientId { get; set; }
public int ProductId { get; set; }
public int EnterpriseId { get; set; }
public int HeadquarterId { get; set; }
public string Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public int StatusId { get; set; }
public int? RUC { get; set; }
public string RUCName { get; set; }
public string RUCAddress { get; set; }
public List<PurchaseRegistrationProductItemEditVM> ProductItemlist { get; set; }
public List<ClientProductPurchaseRegistryComissionEditVM> ComissionList { get; set; }
}
Model PurchaseRegistrationProductItemEditVM:
public class PurchaseRegistrationProductItemEditVM{
public int ProductItemId { get; set; }
public string ProductItemName { get; set; }
public int ProductItemTypeId { get; set; }
public string ProductItemTypeName { get; set; }
public DateTime? StartCourseDate { get; set; }
public DateTime? EndCourseDate { get; set; }
public decimal Amount { get; set; }
public int ExpiryDays { get; set; }
public string Size { get; set; }
public int DiscountTypeId { get; set; }
public string DiscountTypeName { get; set; }
public decimal? Discount { get; set; }
public int? MonthlyPaymentDueDay { get; set; }
public decimal? MonthlyPaymentDuePenalty { get; set; }
public DateTime MatriculationStartDate { get; set; }
public string MatriculationObservation { get; set; }
}
Model: ClientProductPurchaseRegistryComissionEditVM
public class ClientProductPurchaseRegistryComissionEditVM
{
public int Id { get; set; }
public int ClientProductPurchaseRegistryId { get; set; }
public string EmployeeName { get; set; }
public int EmployeeId { get; set; }
public string Observations { get; set; }
}
My View:
#model PurchaseRegistrationProductEditVM
#{
Layout = "~/Areas/Backoffice/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("ProcessPurchases", "Client"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.ClientId)
#Html.HiddenFor(model => model.EndDate)
#Html.HiddenFor(model => model.EnterpriseId)
#Html.HiddenFor(model => model.HeadquarterId)
#Html.HiddenFor(model => model.Name)
#Html.HiddenFor(model => model.ProductId)
#Html.HiddenFor(model => model.ProductItemlist)
#Html.HiddenFor(model => model.StartDate)
#Html.HiddenFor(model => model.StatusId)
#Html.Partial("_PartialViewProductItem")
<div class="form_sep">
#Html.Label(Resources.Client_Pending_Payment_Label_Comission)
#(Html.Kendo().ComboBox()
.Name("EmployeeComissionComboBox")
.Placeholder(Resources.Employee_ComboBox)
.DataTextField("Text")
.DataValueField("Value")
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetEmployeesComboBox", "Client", new { EnterpriseId = #Model.EnterpriseId });
})
.ServerFiltering(true);
})
)
</div>
<div class="form_sep">
#Html.Label(Resources.Client_Purchase_Registry_Comission_Field_Observations)
#Html.TextBox("PurchaseComissionObservations", "", new { maxlength = 50, size = 10, #class = "form-control" })
</div>
<div class="form_sep">
#(Html.Kendo().Button()
.Name("EmployeeComissionAddButton")
.HtmlAttributes(new { type = "button", #class = "k-primary" })
.Content(Resources.Client_SelectedPayments_Button_Add_Employee_Comission)
.Events(ev => ev.Click("onClickAddEmployeeComission"))
)
</div>
<div class="form_sep">
#Html.Label(Resources.Client_Purchase_Registry_Grid_Added_Employees)
#(Html.Kendo().Grid<ClientProductPurchaseRegistryComissionEditVM>()
.Name("PurchaseCommissionGrid")
.HtmlAttributes(new { style = "height:150px;" })
.Columns(columns =>
{
columns.Bound(o => o.EmployeeName).Filterable(f => f.Cell(c => c.ShowOperators(false))).ClientTemplate("#= EmployeeName #<input type='hidden' name='ComissionList[#= indexPurchaseComissionGrid(data)#].EmployeeName' value='#= EmployeeName #' />");
columns.Bound(o => o.EmployeeId).Hidden().Filterable(f => f.Cell(c => c.ShowOperators(false))).ClientTemplate("#= EmployeeId #<input type='hidden' name='ComissionList[#= indexPurchaseComissionGrid(data)#].EmployeeId' value='#= EmployeeId #' />");
columns.Bound(o => o.Observations).Filterable(f => f.Cell(c => c.ShowOperators(false))).ClientTemplate("#= Observations #<input type='hidden' name='ComissionList[#= indexPurchaseComissionGrid(data)#].Observations' value='#= Observations #' />");
columns.Command(command =>
{
command.Custom("Remove").Text(Resources.Site_Link_Remove).Click("onDeleteEmployeeComission");
});
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(5)
)
.Pageable()
.Sortable()
.Scrollable())
</div>
<div class="form_sep">
#Html.LabelFor(model => model.RUC)
#Html.TextBoxFor(model => model.RUC, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.RUC)
</div>
<div class="form_sep">
#Html.LabelFor(model => model.RUCName)
#Html.TextBoxFor(model => model.RUCName, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.RUCName)
</div>
<div class="form_sep">
#Html.LabelFor(model => model.RUCAddress)
#Html.TextBoxFor(model => model.RUCAddress, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.RUCAddress)
<input id="btnSubmit" type="submit" value="#Resources.FO_Client_Link_Buy_Product" class="btn btn-default" />
#Html.ActionLink(Resources.Site_Link_Back, "PurchaseProduct/" + #Model.ClientId, "Client", new { Area = "Frontoffice" }, new { #class = "btn btn-default" })
}
Partial View:
#model PurchaseRegistrationProductEditVM
#for (int i = 0; i < Model.ProductItemlist.Count; i++)
{
#Html.HiddenFor(model => model.ProductItemlist[i].Amount)
#Html.HiddenFor(model => model.ProductItemlist[i].Discount)
#Html.HiddenFor(model => model.ProductItemlist[i].DiscountTypeId)
#Html.HiddenFor(model => model.ProductItemlist[i].DiscountTypeName)
#Html.HiddenFor(model => model.ProductItemlist[i].EndCourseDate)
#Html.HiddenFor(model => model.ProductItemlist[i].ExpiryDays)
#Html.HiddenFor(model => model.ProductItemlist[i].MonthlyPaymentDueDay)
#Html.HiddenFor(model => model.ProductItemlist[i].MonthlyPaymentDuePenalty)
#Html.HiddenFor(model => model.ProductItemlist[i].ProductItemId)
#Html.HiddenFor(model => model.ProductItemlist[i].ProductItemName)
#Html.HiddenFor(model => model.ProductItemlist[i].ProductItemTypeId)
#Html.HiddenFor(model => model.ProductItemlist[i].ProductItemTypeName)
#Html.HiddenFor(model => model.ProductItemlist[i].Size)
#Html.HiddenFor(model => model.ProductItemlist[i].StartCourseDate)
if (Model.ProductItemlist[i].ProductItemTypeId == 1)
{
DateTime date = DateTime.Now;
if (date < Model.ProductItemlist[i].StartCourseDate.Value)
{
date = Model.ProductItemlist[i].StartCourseDate.Value;
}
//Case Course
<div class="form_sep">
<b>#Resources.Site_Link_Course #Html.LabelFor(model => model.ProductItemlist[i].ProductItemName)</b>
</div>
<div class="form_sep">
#Html.LabelFor(model => model.ProductItemlist[i].MatriculationStartDate)
#(Html.Kendo().DatePickerFor(model => model.ProductItemlist[i].MatriculationStartDate)
.Animation(true)
.Culture("pt-PT")
.Format("dd-MM-yyyy")
.Value(date)
.Min(Model.ProductItemlist[i].StartCourseDate.Value)
.Max(Model.ProductItemlist[i].EndCourseDate.Value)
)
#Html.ValidationMessageFor(model => model.ProductItemlist[i].MatriculationStartDate)
</div>
//Observations
<div class="form_sep">
#Html.LabelFor(model => model.ProductItemlist[i].MatriculationObservation)
#Html.TextBoxFor(model => model.ProductItemlist[i].MatriculationObservation, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ProductItemlist[i].MatriculationObservation)
</div>
}
}
My Controller:
[HttpPost]
public ActionResult ProcessPurchases(PurchaseRegistrationProductEditVM model)
{
Log.Instance.Info(string.Format(LogConst.CONTROLLER, "Client", "ProcessPayments", "Get"));
string test = Request.Form["ProductItemlist[0].ProductItemId"];
return RedirectToAction("Details/" + model.ClientId, "Client");
}
After a good night sleep I was able to solve this issue! :)
In the end the problem was this line:
#Html.HiddenFor(model => model.ProductItemlist)
Since I was already storing a list of the same type the form mapper used the first he got. And since you can't save entire lists in hidden fields... it returned a list initialized with 0 elements!
After deleting the line everything started working like a charm!
I wonder why i get null model passing from the view to the controller.
Here is my code in the view (UpdatePersonal.cshtml):
#model Project.Models.UserInfo
#using (Html.BeginForm()){
#Html.LabelFor(m => m.userinfo.firstname);
#Html.TextBoxFor(m => m.userinfo.firstname, new { #Value = ViewBag.Firstname });
#Html.LabelFor(m => m.userinfo.lastname);
#Html.TextBoxFor(m => m.userinfo.lastname, new { #Value = ViewBag.Lastname });
#Html.LabelFor(m => m.userinfo.email);
#Html.TextBoxFor(m => m.userinfo.email, new { #Value = ViewBag.Email });
#Html.LabelFor(m => m.userinfo.phone);
#Html.TextBoxFor(m => m.userinfo.phone, new { #Value = ViewBag.Phone });
#Html.HiddenFor(m => m.username, new { #Value = ViewBag.Username });
<input type="submit" value="Submit" />}
Here is the action method that accepts it:
[HttpPost]
[AllowAnonymous]
public ActionResult UpdatePersonal(UserInfo userInfo){
//some code here
//my breakpoint}
i see the model being passed has null value as i used breakpoint
my model:
public class UserInfo
{
[BsonId]
public string username { get; set; }
public Info userinfo { get; set; }
public Address address { get; set; }
public class Info
{
public string firstname { get; set; }
public string lastname { get; set; }
public string email { get; set; }
public string phone { get; set; }
}
public class Address
{
public string street { get; set; }
public string address1 { get; set; }
public string address2 { get; set; }
public string postalcode { get; set; }
public string country { get; set; }
}
}
You work around the problem but your first code was good, the only problem was the name of your action method param was the same that the name of your model property.
Change your action method signature for example by :
public ActionResult UpdatePersonal(UserInfo info)
and it should be work !
I just solved my problem, instead i used and pass the subclass
#model Buch_Ankauf.Models.UserInfo.Info
#using (Html.BeginForm()){
#Html.LabelFor(m => m.firstname);
#Html.TextBoxFor(m => m.firstname, new { #Value = ViewBag.Firstname });
#Html.LabelFor(m => m.lastname);
#Html.TextBoxFor(m => m.lastname, new { #Value = ViewBag.Lastname });
#Html.LabelFor(m => m.email);
#Html.TextBoxFor(m => m.email, new { #Value = ViewBag.Email });
#Html.LabelFor(m => m.phone);
#Html.TextBoxFor(m => m.phone, new { #Value = ViewBag.Phone });
#Html.Hidden("username", new { #Value = ViewBag.Username });
<input type="submit" value="Submit" />}
in my controller:
[HttpPost]
[AllowAnonymous]
public ActionResult UpdatePersonal(UserInfo.Info userInfo)
{
I have View like this:
#model MVCApp.Models.User
#{
ViewBag.Title = "EditUser";
}
<h2>Edycja użytkownika</h2>
#using (Ajax.BeginForm("SaveUser", "My", new AjaxOptions { UpdateTargetId = "Result" }))
{
<fieldset>
<legend>Zmień dane użytkownika</legend>
<div id="EditUserForm">
<div>
#Html.LabelFor(m => Model.Login)
#Html.TextBoxFor(m => Model.Login)
</div>
<div>
#Html.LabelFor(m => Model.Password)
#Html.TextBoxFor(m => Model.Password)
</div>
<div>
#Html.LabelFor(m => Model.Name)
#Html.TextBoxFor(m => Model.Name)
</div>
<div>
#Html.LabelFor(m => Model.Surname)
#Html.TextBoxFor(m => Model.Surname)
</div>
<div>
#Html.LabelFor(m => Model.UserRole.Role)
#Html.TextBoxFor(m => Model.UserRole.Role)
</div>
<input type="submit" value="Zapisz zmiany" />
#Html.HiddenFor(m => Model.UserRole)
#Html.HiddenFor(m => Model.UserRoleID)
#Html.HiddenFor(m => Model.UserID)
</div>
</fieldset>
<div id="Result"></div>
#Html.ValidationSummary(true)
}
and method in MyController like this:
[HttpPost]
public ActionResult SaveUser(User user, UserRole role)
{
//code here
}
but object role is not passed, either user.UserRole.
My User model class:
namespace MVCApp.Models
{
public partial class User
{
public User()
{
this.Factures = new HashSet<Facture>();
this.Settings = new HashSet<Setting>();
this.Companies = new HashSet<Company>();
}
public int UserID { get; set; }
public Nullable<int> UserRoleID { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public virtual ICollection<Facture> Factures { get; set; }
public virtual ICollection<Setting> Settings { get; set; }
public virtual UserRole UserRole { get; set; }
public virtual ICollection<Company> Companies { get; set; }
}
}
And Role model class:
namespace MVCApp.Models
{
public partial class UserRole
{
public UserRole()
{
this.Users = new HashSet<User>();
}
public int UserRoleID { get; set; }
public string Role { get; set; }
public virtual ICollection<User> Users { get; set; }
}
}
so, How can I pass models like this, which has other reference types inside?
The following line in your view make no sense
#Html.HiddenFor(m => Model.UserRole)
UserRole is a complex object, and depending on whether you have overridden its .ToString() method, it will render <input ... value="MVCApp.Models.UserRole" /> so when this posts back the DefaultModelBinder is trying to do model.UserRole = "MVCApp.Models.UserRole" which of course fails and the property is therefore null
Remove it, and instead bind to the properties of UserRole that you want posted back - as you have done with #Html.TextBoxFor(m => Model.UserRole.Role). For example #Html.HiddenFor(m => Model.UserRole.UserRoleID) but you already seem to have bound this with #Html.HiddenFor(m => Model.UserRoleID) so it might not be necessay to repeat it.
you can create your own submitting mechanism. Just use $.ajax and pass in its data property all your values. A bit more js code, but a lot more flexibility.
I have some problem posting a form with 'complex type' model:
I have a Model:
public class CircleEditViewModel
{
[Key]
public int CircleId { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
public bool IsSystem { get; set; }
public class UserInCircle
{
public UserInCircle(User user)
{
this.UserId = user.UserId;
FullName = user.FullName;
}
public int UserId { get; set; }
public byte[] Picture { get; set; }
public string FullName { get; set; }
public bool isInCircle { get; set; }
}
public List<UserInCircle> Users { get; set; }
}
My first problem was that at post event, my Users where null.. so i followed a few posts on here (like MVC- Model Binding on a Complex Type) to use a for instead of a foreach,but since i did so, my form won't post anymore:
View:
#model Wims.Website.ViewModels.CircleEditViewModel
<script type="text/javascript">
$(document).ready(function () {
$.validator.unobtrusive.parse('form');
});
</script>
#using (Ajax.BeginForm(Html.ViewContext.RouteData.Values["Action"].ToString(), null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SaveDone(data)" }, new { id = "editform" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Circle</legend>
#Html.Label(DateTime.Now.ToString());
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</fieldset>
if (Model.Users != null)
{
for (int i = 0; i < Model.Users.Count; i++)
{
<div class="userDetail">
<div>
<div>
#Html.DisplayFor(model => Model.Users[i].isInCircle);
</div>
<div class="iconDiv">
#Html.Image("~/Content/Images/defaultUser.jpg", Model.Users[i].FullName, null);
</div>
<div>
#Html.TextBoxFor(model => Model.Users[i].FullName)
#Html.HiddenFor(model => Model.Users[i].UserId)
</div>
</div>
</div>
<div style="clear: both"></div>
}
}
#Html.GenerateSecureDataControls(model => model.CircleId)
<input type="submit" value="Save" />
}
My view is rendered as a partial loaded thru ajax (not sure it makes any difference here).
Any idea why it won't post? If i remove all the '[]' like 'Users[0].FullName' to Users0.FullName i will post, but of course it won't be bound.
Thanks for your help
Edit just in case needed: Action:
[HttpPost]
public ActionResult Edit(CircleEditViewModel circleData, FormCollection collection)
{
if (ModelState.IsValid)
{
using (var logic = new CircleLogic())
{
Circle circle = logic.GetCircleById(circleData.CircleId, WebMatrix.WebData.WebSecurity.CurrentUserId);
if (circle == null)
{
return HttpNotFound();
}
else
{
circle.Name = circleData.Name;
logic.UpdateCircle(circle, GetSelectedUser(collection));
}
return PartialView("_CircleAndUsers", GetData(logic, circle.CircleId));
}
}
return this.Json(new { success = false, viewdata = RenderRazorViewToString("_CircleAndUsers", circleData) });
}
Pablo Romeo was right, i added a default ctor and it worked.