Form Collection issue - c#

I have an html begin form in mvc
#using (Html.BeginForm("Search", "Reports",FormMethod.Post, new { enctype = "multipart/form-data", #class = "form-inline" }))
{
<div class="form-group">
<input type="text" class="form-control input-sm" placeholder="Value" name="SearchValue">
<input type="text" class="form-control input-sm second-value" placeholder="Value" style="display:none;" name="SearchValue1">
<button type="button" class="btn btn-default btn-Add">+</button>
</div>
<div id="othersearch"></div>
<input type="submit" value="Search" class="btn btn-primary" />
}
I want to post this form item in one controller
public ActionResult Search(FormCollection collection)
{
string searchvalue = collection.Get("SearchValue");
return View();
}
my problem is that some times second text box is not visible.. that time i dont want to collect the values.And when i press button add generate the same type of input field in the form with same name (i can add many input box). Then how can i collect all these in my controller . please help me..

You can have all the text boxes with same name "SeachValue" in your case.
string searchvalue = collection.Get("SearchValue");
This will return all text box values as comma saperated string which you can split and use further.
Check out the screen shot
the html
and the results

You can get value of all textboxes having same name using following code:
var results = ((String[])formcollection.GetValue("mytxt").RawValue).ToList();
foreach (var item in results)
{
//string name = item;
}

When ever you add a element dynamically make sure you also set it a name. so when you add a new input element it must be
<input type="text" name="NewTextBox" class="form-control input-sm" placeholder="Value" name="searchvalue">
So like this no matter how many text boxes you add, All will have same name. Once you post the form. In your controller do this.
[HTTPPOST]
public ActionResult Search(MyModel newModel,string[] NewTextBox)
{
// here as you had dynamic textbox with name = NewTextBox you
//will get all its value binded to the above string[]
}
OR
You can retrive them using Request.form["NewTextBox"] as
[HTTPPOST]
public ActionResult Search(MyModel newModel)
{
var values = Request.Form[NewTextBox];
}
But I would recommend you the first approach where you use the MVC Model Binder to take care of all the things. You will just have array of values to play with.
NOTE: Always make sure you get the names right, and use the name right while playing with MVC. As all the binding depends on the naming itself.

Related

How to overwrite one model property in ASP.Net core

I have a model with say 10 properties. A, B, C and so on...
Property A is an array.
For each value in array I generate one tag like this:
<div class="col-sm-10 row">
#foreach (var item in Model.A)
{
<div class="col-sm-1 right-buffer">
<i class="" aria-hidden="true">#item.Text</i>
</div>
}
</div>
When user clicks on some link I should redirect it to the same page, but with Some model property changed. For example:
Current url: my/controller/someaction?name=Alex&age=20&from=fr&CurrentA=
with model ?name=Alex&age=20&from=fr&CurrentA=
If user clicks on <a> with text foo it should be redirected on my/controller/someaction?name=Alex&age=20&from=fr&CurrentA=foo
then is clicks on <a> with text bar and it should be now redirected on my/controller/someaction?name=Alex&age=20&from=fr&CurrentA=bar
So entire query string (except one parameter) should be preserved to send current model state to server while I want to set one value and redirect it to the same page but with new value.
Eventually, it should acts like postback with one extra value setted to model
Is it possible or I should use JS and perform everything myself?
Manually i solved it like this:
First, create hidden fields for every property in model:
<form asp-controller="search" asp-action="index" method="get" role="form" id="searchForm" asp-antiforgery="false">
<input asp-for="SessionId" type="hidden" name="sessionId" value="#Model.SessionId" />
<input asp-for="Quantity" type="hidden" name="quantity" value="#Model.Quantity"/>
<input asp-for="SortField" type="hidden" name="sortField" value="#Model.SortField"/>
<input asp-for="IsAscending" type="hidden" name="IsAscending" value="#Model.IsAscending" />
<input asp-for="Offset" type="hidden" name="offset" value="0" />
...
</form>
Then, use JS to replace value in hidden field and then submit form. Values from inputs will be autimatically converter in query string, so everything works fine:
function sortDocuments(sortField) {
var sField = document.getElementById('SortField');
var isDescending = document.getElementById('IsAscending');
if (sField.value === sortField) {
if (isDescending.value.toUpperCase() === 'FALSE') {
isDescending.value = 'TRUE';
} else {
sField.value = 'rank';
isDescending.value = 'FALSE';
}
} else {
sField.value = sortField;
isDescending.value = 'FALSE';
}
document.getElementById('searchForm').submit();
}
Not very elegant, but it does its job.

Passing selected button value from view to controller

I would like to pass the selected button value to the controller. See my code below.
In my controller I am passing through the ProductId which I will then use to set up my product value inside my controller.
Controller:
public ActionResult PlaceOrder(int ProductId, string OrderType)
{
// Do something
}
Inside my view I have a foreach loop which will create radio like buttons and I have also got a hiddenfor(SelectedProductId)
View:
<div class="panel panel-primary">
<div class="panel-heading">Panel Name</div>
<div class="panel-body">
<div class="row">
<div class="form-group">
#Html.HiddenFor(m => m.SelectedProductId)
#if (Model.Products != null && Model.Products.Count > 0)
{
<div class="btn-group" data-toggle="buttons">
#foreach (var product in Model.Products)
{
<label class="btn btn-default productButton">
<div class="labelProduct">#Product.Name</div>
<input type="radio" name="ProductGMX" id="#("product" + #product.Id)" autocomplete="off" checked data-id="#product.Id">
</label>
}
</div>
I will want to pass the Product Id in the ActionLink which will then pass it to the controller but I am not sure how this can be achieved
Button Click:
#Html.ActionLink("Order with standard delivery", "PlaceOrder", "Standard", new { ProductId = ?, OrderType = "Standard delivery" }, new { area = "Standard" })
#Html.ActionLink("Order with Next day Delivery", "PlaceOrder", "Elevated", new { ProductId = ?, OrderType = "NextDay" }, new { area = "Elevated", })
You either need to use JavaScript to update the ActionLink's url whenever the product changes, using the data-id from the radio button.
Or
Use submit buttons instead of ActionLinks, and set the value on the radio button to the product id. You'll need to put some logic in your controller to handle the two different buttons.
Those aren't buttons. They're links, which don't participate in the form submission.
Use real buttons, i.e. <button></button> and give them a name. Then you can see which was clicked by inspecting the Request object:
<button name="_StandardDelivery">Order with standard delivery</button>
Then in your action:
if (Request["_StandardDelivery"] != null) {
// user chose standard delivery
}

Mutiple buttons on MVC form - get item id in the action controller

I have a view with a list of items. Each item have a textbox and a button.
What is the best way to get the item id of the button clicked in the controller action?
I need the value from the associated textbox in the controller action, so I do not think I can use action links.
There are a number of ways to do this. Some use javascript, others don't. I personally prefer to NOT use javascript for basic functionality, unless your design is itself javascript based (such as using ajax)
For instance, you can have each item be wrapped in it's own form, with a different submit value. Just be careful not to nest forms, as that's not valid HTML.
For instance:
#using(Html.BeginForm("MyAction", "MyController", new { id=1 })) {
<input type="submit"/>
#Html.TextBox("TheValue", "One")
}
#using(Html.BeginForm("MyAction", "MyController", new { id=2 })) {
<input type="submit"/>
#Html.TextBox("TheValue", "Two")
}
public ActionResult MyAction(int? id, string TheValue) {
// if they click the first one, id is 1, TheValue = "One"
// if they click the second one, id is 2, TheValue = "Two"
}
this answer is using jquery - If you do not know how to add jQuery to your view or just simply do not want to use it let me know and I can re-work the answer
I would do something like this
<li>
<input type="text" id="1" name="1" class="whatever" />
<input type="button" value="CliCk mE" class="myButton" />
</li>
<li>
<input type="text" id="2" name="2" class="whatever" />
<input type="button" value="CliCk mE" class="myButton" />
</li>
<input type="hidden" id="myHiddenText" name="myHiddenText" />
then add this jQuery:
<script>
$(function(){
$('.myButton').click(function(){
// this is how to get the closest textbox
// you didn't show your html , maybe .prev() or .next()
var textValue = $(this).closest("input[type='text']").val();
// this sets your hidden field with the value from desired textbox
$('#myHiddenText').val(textValue);
});
});
</script>
now when you submit this form to server you can just use myHiddenText on the server
public ActionResult Index(string myHiddenText = "")
{
// hidden fields in the HTML form automatically get passed to server on submit
return View();
}
The best option would be to use jquery but if you only want to use c# I would suggest the following:
I imagine you are using some sort of repeating statement (for or foreach) to generate your textboxes, so what I would do is create a form inside that foreach this new form would contain your textbox, and foreach item you would pass the textbox id to the form submit.
something like this pseudo code:
foreach(item in array){
<form action="address/"#item.Id>
<input type="text" value=""/>
<input type="submit" value="submit textbox"/>
</>
}

Passing data to a Controller method via POST

I have a 'Survey' page which is declared as follows:
#using (Html.BeginForm("Survey", "Home", new { questionList = Model.Questions }, FormMethod.Post))
{
<div class="survey">
<ol class="questions">
#foreach (Question q in Model.Questions)
{
<li class="question" id="#q.QuestionName">
#q.QuestionText<br />
#foreach (Answer a in q.Answers)
{
<input class="answer" id="#a.DisplayName" type="checkbox" /><label for="#a.DisplayName">#a.AnswerText</label>
if (a.Expandable)
{
<input type="text" id="#a.DisplayNameFreeEntry" maxlength="250" /> <span>(250 characters max)</span>
}
<br />
}
</li>
}
</ol>
</div>
<div class="buttons">
<input type="submit" value="Finish" />
</div>
}
When I'm stepping through my code, it hits the method I've set up to process their survey:
[HttpPost]
public ActionResult Survey( List<Question> questionList, FormCollection postData)
{
//Process Survey
}
However, when I step through I am finding that the variable questionList is null and the variable postData does not contain any data from the Form. Trying to access checkboxes via Request[a.Displayname also does not work.
Everything I've read indicates that this is the correct way to persist values from the Model to the submission method, and that I should be able to access the FormCollection this way.
What am I doing wrong?
You have to save questionList as a hidden field on the page. Non-primitive types do not get persisted simply by passing them in.
One way you can do that is
#Html.HiddenFor(m => m.Foo)
Or you could do it directly in HTML like this
<input type="hidden" name="Var" value="foo">
where m is your model.
The fact that the postData is empty is weird, since every input element with id inside a form tag should be passed with the POST request.
But the questionList won't be received that way, since its a list of complex class (not just a string or int), and the default ModelBinder (the thing that turns the HTTP Request Variables into parameters passed to the action method) don't support lists of complex classes.
If you want to be able to receive List you will have to implement your own binding mechanism with CustomModelBinder.
This article can help you implement it.
One problem is your checkbox and your textbox are not properly bound to your model.
You should be using #Html.CheckBoxFor and #Html.TextBoxFor

How can I pass a value from my page to the controller?

I'm using MVC with Razor and C#. I would like to update an element... a counter with ajax. Here is my code:
#model Domain.CounterObject
#using (Ajax.BeginForm("Count", "CounterObject", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "my-control" }))
{
<div id="my-control" class="bid-object">
<div>
<span class="title">#Html.Encode(Model.Title)</span>
</div>
<div>
<span class="display">#Html.Encode(Model.GetFinalDate())</span>
</div>
<div>
<span class="display">#Html.Encode(Model.GetValue())</span>
</div>
<div>
<input type="submit" value="Count" />
</div>
</div>
}
In my controller I have this code:
[HttpPost]
public PartialViewResult Count(CounterObject counter)
{
// Special work here
return PartialView(counter);
}
The problem is that my CounterObject counter I receive in my Count method is always null. How can I pass a value from my page to the controller?
I receive in my Count method is always null
First of all you are not submitting anything from the form then how does the binding happens?
If the user is not allowed to edit the values but still you want to submit them through the form then you have to use hidden fields along with them.
For ex.
<div>
<span class="title">#Html.Encode(Model.Title)</span>
#Html.HiddenFor(m => m.Title)
</div>
Note that the hidden fields should have the same names as the properties to make the binding happen successfully.
It is better to have properties in the Model that store the GetFinalDate() and GetValue() results so you can easily bind the things like in Title.
You'll have to define a input field with a name and id that the ModelBinder can then Bind to your CounterObject.
You could use #Html.EditorForModel once and then inspect the generated Html to see what kind of name/id pairs it is generating. With those you can go on and handcraft your Html if you wanted to.
use
<span class="title">#Html.Encode(Model.Title)</span>
<div class="editor-field">#Html.EditorFor(Model => Model.Title)<div>
//For other fields
In this way you can bind to your object.

Categories

Resources