how to post array of unknown depth/length to c#/mvc - c#

My background is primarily PHP, so i'm used to being able to use deep arrays in forms very easily. What I need is the c#/MVC equivelant of the following:
<input type="text" name="data[0][index_name][0]">
<input type="text" name="data[0][index_name][1]">
<input type="text" name="data[1][index_name][0]">
<input type="text" name="data[1][index_name][1]">
<input type="text" name="data[2][index_name][0][something_else]">
<input type="text" name="data[2][index_name][0]">
<input type="text" name="data[2][index_name][1]">
These could then be accessed in this way in php...
$_POST['data'][0]['index_name'][0];
$_POST['data'][0]['index_name'][1];
$_POST['data'][1]['index_name'][0];
$_POST['data'][1]['index_name'][1];
$_POST['data'][2]['index_name'][0]['something_else'];
$_POST['data'][2]['index_name'][0];
$_POST['data'][2]['index_name'][1];
I've tried looking at/looping over the formColletion object i receive, but the keys are simply the name attribute string, such as "data[2][index_name][0][something_else]," and there is no depth to the data.
How do I parse this data and put in some usable data type? I do not know how deep the array will be as the form changes dynamically on the front end.
So you have some context, this will is being used to build a "table" of data that has a flexible number of rows and columns and each row can be treated as a standard row or grouping row (meaning it contains other rows), so the data can, in theory, get very deep.
On a side note, i've also thought about cleaning up the data on the client side, but it appears there's nothing standard out there that supports this. Jquery.serialize and JQuery.serializeArray() do the same thing as C#/MVC and simply index everything with the full name attribute without taking into account the array indexes.
Thanks for any help!

I'm not sure about the deep aspect but if you post items with the same name then MVC reconstructs this as an array.
<input type="hidden" name="MyArray" value="1"/>
<input type="hidden" name="MyArray" value="2"/>
<input type="hidden" name="MyArray" value="3"/>
<input type="hidden" name="MyArray" value="4"/>
And on your controller
[HttpPost]
public ActionResult MyActionMethod(string[] MyArray)
{
// Do stuff with MyArray
}
You can also access the Request.Form collection in the controller. The key is from the name part of the input on the HTML form.
You can access it like this:
Request.Form["data[2][index_name][0][something_else]"]
Or iterate over it like this:
[HttpPost]
public ActionResult MyActionMethod()
{
foreach(var key in Request.Form.Keys)
{
var item = Request.Form[key];
// Do stuff with each item
}
}

Model Binding turned out to be the correct solution. It support recursion out of the box. Here is a nice write-up:
http://msdn.microsoft.com/en-us/magazine/hh781022.aspx

Related

boolean fields in a model are not being updated in the controller when the data is sent

I had a view without a model in Razor with a form and some inputs and checkboxes, in the controler I'am waiting for a Model to be mapped with the sended data and the input are already well-mapped but the checkboxes not.
I saw the Network Tab in the DevTool and the checkboxes fields are being sent but with an empty data.
[HttpPost]
public async Task<IActionResult> EditLink(LinkDto editedLinkDto)
{
// the text fields of editedLinkDto are correctly received, but the booleans (the ckeckboxes) not...
...
}
The view:
...
<form asp-area="Admin" asp-controller="Features" asp-action="EditLink" method="post">
<input name="LinkName">
<input name="LinkUrl">
<input name="BlankTarget" value="true" type="checkbox" />
<input name="AllowEdit" value="true" type="checkbox" />
...
</form>
...
PD: The name attributes in the fields has the same name that the attributes of the dto I'm receiving in the dto
As I said before, the LinkName and the LinkUrl fields are being sent but the BlankTarget and AllowEdit fields always are false in the controller and in the DevTool I'm seeing that they are being sent with an empty value.
If not using asp-for attribute , you can modify your codes to add a hidden field. It will be submitted regardless whether the checkbox is checked or not. If the checkbox is checked, the posted value will be true/false. The model binder will correctly extract true from the value. Otherwise it will be false :
<input type="checkbox" data-val="true" id="BlankTarget" name="BlankTarget" value="true" checked>
<label for="BlankTarget">Name</label>
<input name="BlankTarget" type="hidden" value="false">
But it is recommend to use Tag Helpers in asp.net core :
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-2.2

ASP.NEŠ¢ MVC 5 checkbox/radio buttons binding in action

I've searched google/SO for a lot of time now. And I didn't find a decent answer. My question is simple. How can I bind the radio selected button or the checked checkboxes to my action.
NO HTML HELPERS(I think that most people use the radio button and checkbox helpers cuz they don't know actually how they work, and use them by heart).
Simple example:
<input type="checkbox" id="foo" name="foo" value="1" checked>
<input type="checkbox" id="foo2" name="foo" value="2">
<input type="checkbox" id="foo3" name="foo" value="3">
<input type="radio" id="male" name="foo10" value="male">
<input type="radio" id="female" name="foo10" value="female">
I read many examples using an object with IsChecked property inside etc. I just want to use a view model like this in my action:
public class FooViewModel {
public int ChosenRadioButtonId {get;set;}
public List<int> ChosenCheckboxes {get; set;}
}
(PS: I don't know if I am mistaking but those helpers generate flaw html - duplicate ids, and everyone knows the basic HTML principles that one id can be used only ONCE)
the name of the checkboxes should exactly be the same as the name in ViewModel, so try to change the names to ChosenCheckboxes[] if you wanna bind them to a list.

Input data is not returning by passing through object

I am passing the input data from the .cshtml page to the action method.
Here is my .cshtml page:
#model passingdata
<form asp-controller="Home" method="post" asp-action="About" >
<button class="btn-danger" type="submit" value="Submit"></button>
<div class="form-group">
<label>
<input asp-for="date" placeholder="Date" class="col-md-8" />
</label>
<label>
Select from these Four Classes
<input type="radio" name="class" asp-for="classselect1" id="classselect1" value="classselect1" class="col-md-4" /> <p> #Model.classname1</p>
<input type="radio" name="class" asp-for="classselect2" id="classselect2" value="classselect2" class="col-md-4" /> <p> #Model.classname2</p>
<input type="radio" name="class" asp-for="classselect3" id="classselect3" value="classselect3" class="col-md-4" /> <p> #Model.classname3</p>
<input type="radio" name="class" asp-for="classselect4" id="classselect4" value="classselect4" class="col-md-4" /> <p> #Model.classname4</p>
</label>
</div>
</form>
And here is my controller code which is invoked when i Click on the button.
[HttpPost]
public IActionResult About(passingdata p)
{
ViewData["Message"] = "Your application description page.";
Teacher.classselect1 = p.classselect1;
Teacher.classselect2 = p.classselect2;
Teacher.classselect3 = p.classselect3;
Teacher.classselect4 = p.classselect4;
Teacher.date = p.date;
return View();
}
The input data like date and bool value from the radiobutton is not passing through the object of the class which contain these variables.
Please help me in this.
If i remember correctly, the Name attribute of each radiobutton is how .net MVC will map the values to your model.
In this case, all of your names are "class", which essentially means you have 1 form field named class with 4 options.
I would recommend using the html helper classes, because they will automatically create the proper html for you. The answer to this post should help: When using .net MVC RadioButtonFor(), how do you group so only one selection can be made?
If you dont want to use the helper just remember that when you submit a form, the data that is posted is based on the name of each form field. .Net does some magic in the background to serialize your Model for you, but essentially you are just submitting data in the format "?prop1=val1&prop2=val2".
Update
I figure maybe I should clarify a little better why what you are doing is not working how you expect.
When you post or put data via a form, it passes the input fields (text box, radio button, checkbox, etc...) as either querystring params or are part of the body. Radio buttons work a little differently than other input type. For a radio button, there are multiple input elements, but only one of them is valid. That is handled by using the name attribute. In your case, all of the names are "class", which means that the only thing being passed to the server is a single "?class={val}" (val is the value of which ever radio button is selected).
If your passingdata model had a property called "class", it would be populated. If your goal is to populated all 4 of the classselect properties with different values, you would need the name of each radio button to be different. But if there was only one radio button with each name, then each property could only have 1 value. You would need multiple RadioButtons with the same name to have multiple values (only one of which is selectable for each property).
Hopefully that clarifies what is wrong and gets you in the right direction.

Realex MVC Solution (Redirect method)

I have a solution that I built using Webforms that passes over approximately 10 fields to the Realex payments processor server (I use the redirect method), and all works fine there. I'm brand new to MVC and am trying to put in place the same functionality using MVC as I currently have set up with Webforms. With my Webforms solution, I use a buttonclick event handler and a Postback URL, to gather the data I need to pass to Realex and the URL is managed in the Postback.
Using MVC, I don't seem to have the use of an event handler or a Postback URL declaration, or if I do, I can only post back to the form, whereas I need to post my data to an external website.
So in my MVC controller, I have hardcoded in the values (for testing purposes), that I am trying to pass to Realex.
The last line above (return Redirect), is bringing me to the Realex page (it is not letting me see the boxes though for entering credit card details, instead it is returning a 506 error saying "Invalid MerchantID or account number)...
I've been onto Realex and they are telling me that they can see the data above that I'm trying to pass to their server, like my account ID, my order reference, etc.
I've also tried doing it this way within my View, just to get this to post properly:
<input id="ORDER_ID" name="ORDER_ID" type="hidden" value="6264286038162642860381" />
<input id="ACCOUNT" name="ACCOUNT" type="hidden" value="XXXXXXXXX" />
<input id="AMOUNT" name="AMOUNT" type="hidden" value="100" />
/>
But I don't know how to hook up my form fields with my controller, I know I'm still thinking "Webforms" here, and am just not thinking MVC, because I've so little experience with MVC and am finding the transition to MVC more difficult than I though.
Thanks in advance for any help with this...
I think you want something like this, I'm sure there's a more elegant solution but this should work.
public ActionResult ShoppingCart(decimal _TotalPriceBox = 1)
{
//After populating your shopping cart model
ViewBag.MerchantId = My_Cart.MYUSERIDSTRING;
ViewBag.Account = My_Cart.ACCOUNT;
ViewBag.OrderId = My_Cart.ORDER_ID;
ViewBag.Amount = My_Cart.AMOUNT;
//Rest of needed properties
return View()
}
Then in the form inside your view
<form action="https://epage.payandshop.com/epage.cgi" method="post">
<input id="ORDER_ID" name="ORDER_ID" type="hidden" value="#ViewBag.OrderId" />
<input id="ACCOUNT" name="ACCOUNT" type="hidden" value="#ViewBag.Account" />
<input id="AMOUNT" name="AMOUNT" type="hidden" value="#ViewBag.Amount" />
//Rest of inputs needed
<input type="submit" value="send" />
</form>

How do you post an array of textboxes (containing commas) in ASP.NET MVC

I am trying to post a list of addresses from a form to a controller
<input type="text" name="address" value="sample1, sample1">
<input type="text" name="address" value="sample2, sample2">
But this creates a problem since I get four values for address i.e. sample1, sample2, sample3, sample4 there is no difference between the values for the 1st and 2nd address.
What would be the best way to achieve this in C#.
Change the names of the controls?
<input type="text" name="address1" value="sample1, sample1">
<input type="text" name="address2" value="sample2, sample2">
What I'm considering is having jQuery replace all comma's in the inputs to something like ~#~ then after it is posted and split, I convert the ~#~ back to comma's. Pretty lame. PHP has figured this out, why can't Microsoft? If there was a way to choose the delimiter, that would be nice too.

Categories