I have a jQuery script that captures a form into an object and is supposed to send that object to a controller method. Here's the script:
var modalConfirm = function (callback) {
$("#modal-btn-si").on("click", function () {
callback(true);
$("#modal-confirm").modal('hide');
});
$("#modal-btn-no").on("click", function () {
callback(false);
$("#modal-confirm").modal('hide');
});};
function confirmar(form, text) {
$("#modal-confirm").modal('show');
modalConfirm(function (confirm) {
if (confirm) {
enviar(form);
}
}); };
function enviar(form) {
debugger;
var datos = $('#' + form).serializeArray(),
dataObj = {};
$(datos).each(function (i, field) {
dataObj[field.name] = field.value;
});
if (typeof dataObj["precio"] === "undefined") { dataObj["precio"] = 0; }
$.post("NuevaOpcion", {
contentType: "application/JSON",
data: JSON.stringify(dataObj),
}); }
Note: the script was originally much simpler, but trying to fix the issue I'm describing forced me to divide the code in the functions you see.
I created a model to receive the form's data:
public class NuevaOpcionFormModel {
public NuevaOpcionFormModel() { }
public int Id { get; set; }
public string nombre { get; set; }
public int cantidad { get; set; }
public int precio { get; set; }
public int idrespuesta { get; set; }
public int OptionSelectedItem { get; set; }
}
And the controller's method signature:
[HttpPost]
public ActionResult NuevaOpcion (Dayvo.Presupuestador.Web.Models.Form.NuevaOpcionFormModel nuevaOpcion) { ... }
What I've tried
On the script:
.serialize() instead of .serializeArray().
Not serialize at all.
Passing entire 'form' into object and then to controller.
JSON.stringify (actual state) and not using it.
Stablishing each field in data manually.
Stablishing each field in data manually and apllying JSON.stringify.
On the controller:
[FromForm] & [FromBody]
[Bind]
A single variable for each field, matching names and types.
Everything I've tried ends up with the controller's method receiving nothing. I tracked the script (that's why you're seeing a debugger; breakpoint in it), it gets the object into the array correctly, each field with it's proper value:
But still hits the controller with empty object:
Any clue about what I'm doing wrong is more than welcome. Thanks in advance.
EDIT
As requested, here's the view part I'm capturing into the form:
<div class="panel-footer">
#using (Html.BeginForm("NuevaOpcion", "Home", FormMethod.Post, new { #id = "frm_nueva_opcion" })) {
#Html.HiddenFor(m => m.Id)
<div class="row">
<div class="col-md-6">
<div class="form-group" style="margin-bottom: .7em;margin-top: .7em;">
<button class="btn btn-success btn-xs" type="button" onclick=" $('#row-nueva-opcion').toggle()" id="add-opcion">
<span class="glyphicon glyphicon-plus-sign"></span> Añadir nueva opción
</button>
</div>
</div>
</div>
<div class="row" id="row-nueva-opcion" style="display:none">
<div class="col-md-10">
<label>
<input type="checkbox" id="opcion-extra" onclick=" $('#nuevo-precio').attr('disabled', !this.checked);" />
Es opción extra
</label>
<div class="input-group" style="margin-bottom:1.7em;">
<input type="text" placeholder="Opción" class="form-control" name="nombre" style="max-width:70%;">
<input type="number" placeholder="Cantidad" min="1" value="1" class="form-control" name="cantidad" style="max-width:15%;">
<input type="number" placeholder="Precio" class="form-control" id="nuevo-precio" name="precio" style="max-width:15%;" disabled>
<input type="hidden" name="idrespuesta" id="idrespuesta" value="#listItems.Select(x=>x.Value).FirstOrDefault()" />
<div class="input-group-addon">€</div>
<span class="input-group-btn">
<a class="btn btn-primary" data-title="Confirmación de acción" data-toggle="modal" data-target="#modal_confirm" onclick="confirmar('frm_nueva_opcion')">
<span class="glyphicon glyphicon-floppy-disk"></span> Guardar
</a>
</span>
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label>
¿Para que pregunta es la opción?
#Html.DropDownList("OptionSelectedItem", listItems, new { #class = "form-control" })
</label>
</div>
</div>
</div>
}
</div>
The jquery $.post() method sends data using the default contentType='application/x-www-form-urlencoded; charset=UTF-8' where the data needs to be PlainObject.
For the DefaultModelBinder to bind to your model, the name/value pairs of the object need to match the model properties, so the format needs to be
var data = { Id: someValue, nombre: anotherValue, .... };
To generate that object, either generate it manually, or better, use the .serialize() method (not .serializeArray()) to correctly serialize all form controls. Change the script to
function enviar(form) {
var data = $('#' + form).serialize();
$.post("NuevaOpcion", data, function(response) {
... // code to execute when the response is returned
});
Note it is not clear what you where expecting with the if (typeof dataObj["precio"] === "undefined") { dataObj["precio"] = 0; } code, but it is unnecessary and can be omitted - your precio property is int and it will have a value of 0 if it is not included in the request.
I also strongly recommend you use the HtmlHelper methods to strongly bind to your model, and to ensure the correct name, value and data-val-* attributes are added for 2-way model binding and client side validation.
Related
im using Razor pages and in my page model i have empty list. I need it to by filled by user. And i do not know how many items there will be. Currently im using post methods to add inputs to my page like this:
public async Task OnPostAddLicence()
{
await SetDials();
LicenceList.Add(new Licence());
}
public async Task OnPostRemoveLicence(int index)
{
await SetDials();
ModelState.Clear();
LicenceList.RemoveAt(index);
}
problem with this aproach is that it reloads the page and scroll to TOP of the page.
Unfortunately i did not find any way to scroll back on where i was. And because its razor pages maintain scroll position is not working.
so i would like to add these item dynamicaly with javascript. i tried using this:
<div id="divCont">
<div>
<input type="text" class="form-control" asp-for="Salaries[0].HoursWorked" placeholder="Odpracovaných hodin">
<input type="button" onclick="AddTextBox()" value="Add" />
</div>
</div>
<script type="text/javascript">
function GetDynamicTextbox(value) {
return '<div><input type="text" name="txttest" style="width:200px;" asp-for="Salaries[0].HoursWorked" /><input type="button" onclick="RemoveTextBox(this)" value="Remove" /></div>';
}
function AddTextBox() {
var div = document.createElement('DIV');
div.innerHTML = GetDynamicTextbox("");
document.getElementById("divCont").appendChild(div);
}
function RemoveTextBox(div) {
document.getElementById("divCont").removeChild(div.parentNode.parentNode);
}
</script>
but it is not binding the value to the list.
And all others methods that i could find online are not working with razor pages but just mvc
Do you mean you cannot bind data to input?If so,sometimes asp-for cannot work,you can have a try to change asp-for="Salaries[0].HoursWorked" to
id="Salaries_#(0)__HoursWorked"
name="Salaries[#(0)].HoursWorked"
value=#Salaries[0].HoursWorked
Here is a example to show how to bind data without asp-for:
<input type="text" asp-for="#Model.Locations[0].Street" /></td>
<input type="text" id="Locations_0__Street" name="Locations[0].Street" value=#Model.Locations[0].Street />
result:
Here is a worked demo to show the binding:
Page:
<form method="post">
<input asp-for="#Model.postdata.data[0].id" class="form-control" />
<input id="postdata_data_0__name" name="postdata.data[0].name" value="#Model.postdata.data[0].name" class="form-control" />
<div>
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
PageModel:
public class TestModel : PageModel
{
[BindProperty]
public Postdata postdata{ get; set; }
public IActionResult OnGet()
{
List<TestDT> data = new List<TestDT>();
TestDT testDT = new TestDT { id = 1, name = "test1" };
TestDT testDT2 = new TestDT { id = 2, name = "test2" };
data.Add(testDT);
data.Add(testDT2);
postdata = new Postdata();
postdata.data = data;
return Page();
}
public IActionResult OnPost()
{
return Page();
}
}
Result:
I'm working on an asp.net core mvc website for a homework. The app is using identity server for login. I'm trying to show a pop-up alert after an user enters the correct credentials and presses the Login button(something like javascript alert). I've created a boolean property inside the .cs file which becomes true when an user succesfully logs in. In the .cshtml file I've added a script block which contains a function that shows an alert when the boolean property is true. The issue is that the function is executed when the page is created(at that moment the property is false) even though I'm calling the function on button click.
Any suggestions which might be the issue?
Login.cshtml
#page
#model LoginModel
#{
ViewData["Title"] = "Log in";
}
<div class="container w-50 text-center">
<h1 class="display-4" style="margin-bottom: 80px;">#ViewData["Title"]</h1>
<section>
<form id="account" method="post">
<h4>Use a local account to log in.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label asp-for="Input.RememberMe">
<input asp-for="Input.RememberMe" />
#Html.DisplayNameFor(m => m.Input.RememberMe)
</label>
</div>
</div>
<div class="form-group">
<button onclick="showAlert()" type="submit" class="btn btn-primary">Log in</button>
</div>
<div class="form-group">
<p>
<a asp-page="./Register" asp-route-returnUrl="#Model.ReturnUrl">Register as a new user</a>
</p>
</div>
</form>
</section>
</div>
<script type="text/javascript">
showAlert = function () {
if (#LoginModel.alert) {
alert("Logged in succesfully");
#LoginModel.alert = false;
}
}
</script>
#section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Login.cshtml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using BookingApp.ApplicationLogic.DataModel;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace BookingApp.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class LoginModel : PageModel
{
private readonly UserManager<User> _userManager;
private readonly SignInManager<User> _signInManager;
private readonly ILogger<LoginModel> _logger;
[BindProperty] static public bool alert { get; set; } = false;
public LoginModel(SignInManager<User> signInManager,
ILogger<LoginModel> logger,
UserManager<User> userManager)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
}
[BindProperty]
public InputModel Input { get; set; }
public IList<AuthenticationScheme> ExternalLogins { get; set; }
public string ReturnUrl { get; set; }
[TempData]
public string ErrorMessage { get; set; }
public class InputModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
public async Task OnGetAsync(string returnUrl = null)
{
if (!string.IsNullOrEmpty(ErrorMessage))
{
ModelState.AddModelError(string.Empty, ErrorMessage);
}
returnUrl = returnUrl ?? Url.Content("~/");
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
ReturnUrl = returnUrl;
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
alert = true;
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
}
}
Are you sure #LoginModel.alert gives out a JS-boolean? Because it usually doesn't when writing JS with razor.
If the output is not exactly understood as boolean by Javascript at this point, it is "truthy". E.g. if it is parsed as a string, the condition is "true" for JS.
In JS I would always suggest checking values with ===, just to be on the type-safe side. For example:
if (#Json.Encode(LoginModel.alert) === true) {
// ...
}
My page contains multiple partial pages like this. Suppose there are two partial views. And both of those views have their own forms.
<div class="row">
#await Html.PartialAsync("_partialNameInfo") //For First and Last
Name
#await Html.PartialAsync("_partialAddressInfo") // For address info
</div>
partialNameInfo looks similar to this:
<form id="nameinfo">
<input type="text" id="firstname"/>
<input type="text" id="lastname"/>
<input type="submit" onclick="checknames()" value="Submit"/>
<form>
//Also, there is JS function checknames similar to this which stores names in json format
<script type="javascript">
function checknames() {
var namedetails=
{
fname : document.getelementbyid .... // gets firstname and stores
lname : document.getelementbyid .... // gets lastname and stores
};
</script>
//_partialAddressInfo looks similar to this:
<form id="addressinfo">
<input type="text" id="StreetName"/>
<input type="text" id="ApartmentNumber"/>
<input type="submit" value="Submit"/>
<form>
What I want it to be like:
It should only load first page view by default i.e _partialNameInfo
When _partialNameInfo forms validation is correct, then on clicking its Submit button, it should pass the values of checknames and also display
another view _partialAddressInfo as first page view is valid.
A. How can I load only the _partialNameInfo page by default ? And not display the other page
B. How to check condition that first page form was correctly submitted so that another page can be displayed?
C. How to pass information obtained from checknames to another view ?
You could use return PartialView() to render the other page when the first page was correctly submitted.And pay attention to that the input type should be button not submit.
Here is a simple workaround like below:
1.Model:
public class NameInfo
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string StreetName { get; set; }
public int ApartmentNumber { get; set; }
}
2._partialNameInfo.cshtml:
<form id="nameinfo">
<input type="text" id="firstname" />
<input type="text" id="lastname" />
<input type="button" onclick="checknames()" value="Submit" />
3._partialAddressInfo.cshtml:
#model Address
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.StreetName)
</th>
<th>
#Html.DisplayNameFor(model => model.ApartmentNumber)
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
#Html.DisplayFor(model => model.StreetName)
</td>
<td>
#Html.DisplayFor(model => model.ApartmentNumber)
</td>
</tr>
</tbody>
</table>
4.Index.cshtml:
<div id="partial1">
#await Html.PartialAsync("_partialNameInfo")
</div>
<div id="partial2">
</div>
#section Scripts{
<script>
function checknames() {
var flag;
var firstname = $("#firstname").val();
var lastname = $("#lastname").val();
var data = { firstname, lastname };
$.ajax({
url: "/Home/Test",
type: "POST",
data :data,
dataType: 'html',
success: function (result) {
$("#partial2").html(result);
}
})
}
</script>
}
5.Controller:
public IActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Test(NameInfo nameInfo)
{
var model = new List<NameInfo>()
{
new NameInfo(){ Id=1,FirstName="a",LastName="b",Address=new Address(){ StreetName="aa",ApartmentNumber=1001} },
new NameInfo(){ Id=2,FirstName="c",LastName="d",Address=new Address(){ StreetName="bb",ApartmentNumber=1002} }
};
var data = model.Where(m => m.FirstName == nameInfo.FirstName).Where(m => m.LastName == nameInfo.LastName).Select(m => m.Address).FirstOrDefault();
return PartialView("_partialAddressInfo",data);
}
6.Result:
This is my form to submit
#using (Html.BeginForm("SigningAsync", "Signing", FormMethod.Post,
new { onsubmit = "return confirm('Do you really want to submit the form?');"}))
{
<div class="col-md-6 col-sm-12 form-group" style="margin-bottom:5px !important">
<input type="submit"
id="btnConf"
name="Sign" value="Confirm"
class="btn btn-primary pull-right" style="margin-right:2px" />
<div class="form-group">
<input type="hidden" id="arr" name="arr" />
</div>
</div>
}
<input type="checkbox" value="#masterData.DocNo" name="selected" class="inforID" id="#masterData.NewDocNo" plant="#masterData.Plant" flowno="#masterData.FlowNo"/>
When checkbox is checked and Confirm button is pressed, I put attribute from checkbox to input arr
$(document).ready(function() {
$("#btnConf").click(function () {
var selected = [];
$.each($("input[name='selected']:checked"), function () {
selected.push({
DocNo: $(this).val(),
NewDocNo: $(this).attr("id"),
Plant: $(this).attr("plant"),
FlowNo: $(this).attr("flowno")
});
document.getElementById("arr").value = JSON.stringify(selected);
});
console.log(JSON.stringify(selected));
});
});
The input arr will like this
<div class="form-group">
<input type="hidden" id="arr" name="arr" value="[
{"DocNo":"100400020719-006","NewDocNo":"ABS-02072019","Plant":"VDNF","FlowNo":"FLW-000001"},
{"DocNo":"100400020719-007","NewDocNo":"ABS-02072019","Plant":"VDNF","FlowNo":"FLW-000001"}
]">
</div>
And this is the Action
public async Task<ActionResult> SigningAsync([Bind(Include = "arr")] PurchaseRequestViewModel purchaseRequestViewModel, string Sign, string[] arr)
{
bool result = false;
if(arr != null)
{
if (ModelState.IsValid && !String.IsNullOrWhiteSpace(Sign))
{
for(int i = 0; i < arr.Length; i++)
{
string test = a[i].NewDocNo;
}
}
}
}
I can't get the property of object in arr, I have tried string test = a[i][NewDocNo]; or string test = a[i]["NewDocNo"];.
But it wasn't right. How can I get the properties of array in the Controller?
I have tried console.log(selected[0].NewDocNo); in Javascript and it's ok, but in the Controller, it wasn't right.
The value that you have in your HTML will be treated as a string value as there are not multiple values passed to the controller. You are only passing a single value. You need to change the method signature and use string arr and have the value as a string. Then do the conversion on the server.
Also, instead of submitting a form manually, better to use Javascript and AJAX to submit the data. Then you can pass the value of arr in the request body as JSON. Then that will automatically be converted into an array.
I've seen many posts on SO considering this topic, though applying solutions didn't work for me and I am confused right now. Mb I'm missing sth?
Please consider I'm a noob at .js stuff.
So I get my values from dynamicly created form elements with this JS and attempt to post it:
EDIT 12:21: I got this script which should parse each element from form into custom made array resembling json. I still get null reference though. Got any idea how to get it?
var getValues = function (myForm) {
var array = [];
var parser;
$("formElement").each( function (i, elem) {
parser.empty()
parser = {
Id: $(elem,"#Id ").val(),
someOption: $(elem, "#someOption ").val(),
someText: $(elem, "#someText ").val(),
someNumber: $(elem, "#someNumber ").val()
}
array.push(parser);
});
console.log(array);
$.ajax({
type: "POST",
url: 'angus',
traditional: true,
data: {json: array },
success: function (data) {
$("#getData").empty();
$("#getData").append(array);
}
});
};
I get this in log:
(objects of index like i,i+1,i+2,i+3 match the viewmodels - is it right? and I have mixed feelings about those proto and functions - what is it?)
In my controller action I get null exception:
[HttpPost]
public ActionResult angus(IEnumerable<TrashViewModel> json)
{
return View(json.ToList());
}
I created my viewmodel:
[Serializable]
public class TrashViewModel
{
public int Id { get; set; }
public string someOption { get; set; }
public string someText { get; set; }
public string someNumber { get; set; }
}
I had my forms HTML attributes names match those of viemodel class.
EDIT:
html:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="formExample" ng-controller="ExampleController">
<button class="btn btn-primary" ng-controller="addRow" ng-click="addLine()">Dodaj przycisk</button>
<form novalidate class="simple-form">
<div class="here">
<div class="formElement row">
<input type="hidden" name="Id" value="1"/>
<div class="col-md-2">
<select name="someOption" class="optns form-group col-md-12" ng-model="user.class">
<option selected value="1"> Rodzaj... </option>
<option value="test">2</option>
<option value="2">test</option>
<option value="2">2</option>
<option value="3">3</option>
#*tutaj beda dodane opcje*#
</select>
</div>
<div class="col-md-1">
<input name="someNumber" class="form-group col-md-12" type="number" ng-model="user.number" value="" text="Ilość..." /><br />
</div>
<div class="col-md-9">
<input name="someText" class="form-group col-md-12" type="text" ng-model="user.text" value="" text="Uwagi..." /><br />
</div>
</div>
</div>
<input type="button" value="Reset" />
<input type="submit" value="Save" />
</form>
</div>
appended html:
var strVar = "";
strVar += "<div class=\"formElement row\">";
strVar += " <input type=\"hidden\" name=\"Id\" value=\" "+ $scope.counter +"\"\/>";
strVar += " <div class=\"col-md-2\">";
strVar += " <select name=\"someOption\" class=\"optns form-group col-md-12\" ng-model=\"user.class\">";
strVar += " <option selected value=\"1\"> Rodzaj... <\/option>";
strVar += " <option value=\"test\">2<\/option>";
strVar += " <option value=\"2\">test<\/option>";
strVar += " <option value=\"2\">2<\/option>";
strVar += " <option value=\"3\">3<\/option>";
strVar += " #*tutaj beda dodane opcje*#";
strVar += " <\/select>";
strVar += " <\/div>";
strVar += " <div class=\"col-md-1\">";
strVar += " <input name=\"someNumber\" class=\"form-group col-md-12\" type=\"number\" ng-model=\"user.number\" value=\"\" text=\"Ilość...\" \/><br \/>";
strVar += " <\/div>";
strVar += " <div class=\"col-md-9\">";
strVar += " <input name=\"someText\" class=\"form-group col-md-12\" type=\"text\" ng-model=\"user.text\" value=\"\" text=\"Uwagi...\" \/><br \/>";
strVar += " <\/div>";
strVar += " <\/div>";
I end up with null exception which by what other posts suggest is because of viemodel class doesn't match the serialized objects. Don't know what to do at this point.
Thank you!
In order to POST your array, you need to stringify the data and set the contentType option. You ajax code needs to be
$.ajax({
type: 'POST',
url: '#Url.Action("angus")', // do not hard code url's
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ model: array }),
success: function (data) {
and the controller
[HttpPost]
public ActionResult angus(IEnumerable<TrashViewModel> model)
try replacing
var parsed = $(myForm).serializeArray();
with
var parameters = {
Id : $("#Id ").val(),
someOption : $("#someOption ").val(),
someText : $("#someText ").val(),
someNumber : $("#someNumber ").val()
};
then pass it to the submit
JSON.stringify(parameters)
in your JavaScript code, 3 things jump out at me:
you're using .serializeArray(), which creates an array of objects each with a name and value property. this does not match the structure of your TrashViewModel object
you're wrapping the serialized object inside a new object with a single property called "json", which adds more structure to your data
you're stringifying said object
all of that is unnecessary, since the .ajax() method will package the data in the correct format for you. you simply need to pass the serialized form as the data parameter.
data: $(myform).serialize()
on the controller, you should just set the parameter on the action to be your TrashViewModel object. please note that it's a single object, not an enumerable.
public ActionResult Angus(TrashViewModel form)
{
// do something
}
if you were to use .serializeArray(), then you'd need to create a model object with Name and Value properties so that the model binder can properly resolve the params.
// JavaScript
data: $(myform).serializeArray()
// Controller
public class NameValueModel
{
public string Name { get; set; }
public string Value { get; set; }
}
public ActionResult Angus(NameValueModel[] form)
{
// do something
}
I'm not 100% happy about outcome, because I still have to parse json string at the end on server side. I think I'll soon do Q&A, so others won't have to fight a week to do sth like this. Thanks to:
#StephenMuecke
#Emil
#Jeff M
So actually what I did:
js to get inputs and push it custom style then do post ajax request:
var array = [];
var parser;
$(".formElement").each( function (i, elem) {
//parser.empty()
parser = {
Id: $("#Id", $(this)).val(),
someOption: $("#someOption", $(this)).val(),
someText: $("#someText", $(this)).val(),
someNumber: $("#someNumber", $(this)).val()
};
console.log(parser);
array.push(parser);
});
console.log(array);
$.ajax({
type: "POST",
url: 'angus',
traditional: true,
data: { json: JSON.stringify(array) },
success: function (data) {
$("#getData").empty();
$("#getData").append(array);
}
});
controller:
(don't mind the logic, because it's useless here except it gave info during debugging)
the most important thing was to give string type as parameter; I'm 100% sure that my json bounced off of the complex type viewmodel
[HttpPost]
public ActionResult angus(string json)
{
var check = json.ToString() == null;
return RedirectToAction("ErrorAction");
}