Pass value of dropdownlist when click button - c#

I have a dropdownlist in my View:
#Html.DropDownListFor(m => m.APtTitleData.apt, (IEnumerable<SelectListItem>)ViewBag.apt, "-Select Apt-", new { id = "SelectedAPt", name= "SelectedAPt" })
and I have a button in the same View
GO
How do I pass the value of the dropdown to my controller (Edit)? I'm trying to get the value to the button, but I'm not sure this is the right way. Any other idea?

I would suggest that you use a form where you submit the value from the dropdown to the controller.
Please check out the following code:
#using (Html.BeginForm("APtTitle", "Edit", FormMethod.Post))
{
<div class="form-group">
<label>AptTitles</label>
<div>
#Html.DropDownListFor(m => m.APtTitleData.apt, (IEnumerable<SelectListItem>)ViewBag.apt, "-Select Apt-", new { id = "SelectedAPt", name= "SelectedAPt" })
</div>
</div>
<div class="form-group">
<div>
<input type="submit" value="Submit" />
</div>
</div>
</div>
}
And in the controller your code should look similar to the following:
[HttpPost]
public ActionResult Edit(string SelectedAPt)
{
var aPtValue = SelectedAPt;
// Do what intended with the value
}
You should now be able to see the value in the controller now.
Try it out and let me know if you run into issues.

Related

MVC Html.HiddenFor in a loop passing model back to Controller

I am looping through an IEnumerable of my model:
#model IEnumerable<Testing.Models.ProductItem>
#{
ViewBag.Title = "Buy Products";
}
<div class="row">
#foreach (var product in Model)
{
using (Html.BeginForm())
{
#Html.HiddenFor(Model => product)
... More Controls and stuff...
<input type="submit" value="Add To Kart" class="btn btn-info">
}
}
</div>
and on submit I want to pass the selected instance of my model back to my controller:
[HttpPost]
public ActionResult Index(ProductItem product)
{
... Do Stuff ...
return View();
}
However I have tried a few things but always seem to be getting null passed into the controller... Please could someone please help point me in the right direction?
EDIT
I dont actually need to the full model instance as I can get this within the controller from the ID - so I have tried the following:
#model IEnumerable<Testing.Models.ProductItem>
#{
ViewBag.Title = "Buy Products";
}
<div class="row">
#foreach (var product in Model)
{
using (Html.BeginForm())
{
#Html.HiddenFor(Model => product.ID)
#Html.TextBox("qty", "1", htmlAttributes: new { #style = "width: 30px;" })
... More Controls and stuff...
<input type="submit" value="Add To Kart" class="btn btn-info">
}
}
</div>
which posts to the controller:
[HttpPost]
public ActionResult Index([Bind(Include = "ID")] int? ID, [Bind(Include = "qty")] int? qty)
{
return null;
}
The textbox is not part of the model as it is user input - this value is passed nicely into the actions parameter, however I am still getting a null for the ID in the HiddenFor control. Is this to do with the naming of the control? I dont seem to be able to add a name to the HiddenFor control.
I know this puts a different light on the original question but I am hoping you may still be able to help.
I take the note about the BeginForm being inside the loop - creating for each item in the list... Is there an easy alternative to this (note I haven't tried anything yet).
It sounds like you're trying to use HiddenFor on a complex type and that won't work. You'll need to use a property of ProductItem like ProductId or something like that, which will most likely be an int or Guid.
Now that you have cleared up the complex binding to a simple field, you'll notice that your name is being set to product.id and that is why it is always null in your controller. You can't override the name attribute with Hidden for, so you'll want to change your code to:
#foreach (var product in Model)
{
using (Html.BeginForm())
{
#Html.Hidden("ID", product.ID)
#Html.TextBox("qty", "1", htmlAttributes: new { #style = "width: 30px;" })
<input type="submit" value = "Add To Kart" class="btn btn-info">
}
}
I have managed to arrive at my desired functionality (rightly or wrongly) with the following:
#model List<ShoppingKartTest.Models.ProductItem>
#{
ViewBag.Title = "Buy Products";
}
#foreach (var item in Model)
{
using (Html.BeginForm())
{
<input type="hidden" value="#item.ID" name="ID" />
#Html.TextBox("qty", "1", new { #style = "width: 30px;" })
<input type="submit" value="Add To Kart" class="btn btn-info">
}
}
Which correctly submits the Hidden ID and the contents of the Textbox to the Controller Action:
[HttpPost]
public ActionResult Index(int ID, int qty)
{
//... Do stuff with parameters...
return View();
}
I would be interested to hear any comments on this. I know that I was told above that I shouldn't have my BeginForm within the loop... But it just works for me.
Instead of Model => product.Id, try p=> product.Id
#model IEnumerable<Testing.Models.ProductItem>
#{
ViewBag.Title = "Buy Products";
}
<div class="row">
using (Html.BeginForm())
{
#foreach (var product in Model)
{
#Html.HiddenFor(p => product.ID)
#Html.TextBox("qty", "1", htmlAttributes: new { #style = "width:
30px;" })
... More Controls and stuff...
}
<input type="submit" value="Add To Kart" class="btn btn-info">
}
</div>

c# mvc form: how to build view for simple feedback form leveraging the benefit of using html.editorfor?

I have simple input form (basically for feedback) with following fields:
Name, Gender, Mobile-Number, Complaint text. (To simplify I am not mentioning any POST action OR submit button on the form)
Currently, I have created following MVC structure:
public class ComplaintController
{
[HttpGet]
public ActionResult Index()
{
return View(); //This view displays the complaint form with all above fields
}
}
I read this and several other links where they suggest to use #Html.EditorFor as it creates UI based on model data-type.
Currently, I am not passing any model to the [HttpGet] view. If I want to use #Html.EditorFor, I need to pass my model to [HttpGet] Index View, how can I do that? What is best pratise to create such MVC forms?
Your Controller:
public ActionResult Index()
{
whateverModel d = new whateverModel();
return View(d);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(whateverModel m)
{
if (ModelState.IsValid)
{
//its valid, update your database or do soemthing useful here
return RedirectToAction("Success");
}
//its not valid reload the page and let data annotations show the error
return View(m);
}
Once you have your code in the controller then you can have visual studio auto-create your view. In your controller, right click the "d" in return View(d); and select "Add View." Change the Template to "create" and Model class to your Model (whateverModel in this example). It will auto generate the chtml page for you with the model imported and the editors already generated for you. Example auto generated view below. The you can work on styling and such.
cshtml:
#model YourSolution.Models.whateverModel
#{
ViewBag.Title = "Whatever";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Whatever</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Whatever</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.FriendlyName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FriendlyName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FriendlyName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Order, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Order, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Order, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Currently, I am not passing any model to the [HttpGet] view. If I want
to use #Html.EditorFor, I need to pass my model to [HttpGet] Index
View, how can I do that?
Hi sahil ,As a first step , create one model class like below
public class FeedBack
{
public string Name{get;set;}
public string Gender{get;set;}
public int Mobile-Number{get;set;}
public string Complaint{get;set;}
// other additional fields
}
And in the controller get method ,pass a model like below
public class ComplaintController
{
[HttpGet]
public ActionResult Index()
{
FeedBack OBJFeedback = new FeedBack();
return View(OBJFeedback);
}
}
And in a view , strongly type this model and post the data as you want to the controller post methods.
Here is the example of strongly typed view : http://www.c-sharpcorner.com/UploadFile/abhikumarvatsa/strongly-typed-views-in-mvc/
Important Note : In the get action method , since you dont want to display any values by default in the view , even if you dont pass model object it will work in the same way.
Hope the above information was useful
Thanks
Karthik
If you want to use #Html.EditorFor, then you mast pass the model to the view.What does #Html.EditorFor do? It makes the html tag like
<input class="text-box single-line" id="Name" name="Name" type="text" value="">
So if you do not want to pass the model to the view then you need to write the raw html tag like above. It is important to keep the html tag's name property same as the mvc's model property because when you want to post the data to the controller the name property of the html tag will map the mvc model property and get the corresponding value at the Controller method.
At the view(somthing.cshtml) you can use html tags, because .cshtml==.cs+html . So the whole code look like
Controller methods
public ActionResult FeedBack()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult FeedBack(FeedBackModel Model)
{
var feedBack = Model;
return View();
}
And the View
<form action="/Home/FeedBack" method="post" id="feedBackForm">
#Html.AntiForgeryToken()
<hr>
<div class="form-group">
<div class="col-md-5">
<label for="Name">Name</label>
</div>
<div class="col-md-5">
<input class="text-box single-line" name="Name" type="text">
</div>
</div>
<div class="form-group">
<div class="col-md-5">
<label for="Name">Gender</label>
</div>
<div class="col-md-5">
<select name="Gender">
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-md-5">
<label for="Name">MobileNumber</label>
</div>
<div class="col-md-5">
<input class="text-box single-line" name="MobileNumber" type="text">
</div>
</div>
<div class="form-group">
<div class="col-md-5">
<label for="Name">Complaint</label>
</div>
<div class="col-md-5">
<textarea class="text-box single-line" name="Complaint"></textarea>
</div>
</div>
<div class="col-md-5">
<input type="submit" value="Create" class="btn btn-default">
</div>
</form>
If you do not want to use submit then you can use ajax.

#Html.DropDownList return null to controller

The DropDownList in my view shows the relevant options to choose, but no matter what i choose, the folders in the Controller get value null.
Why? How can i fix it so the folders in the Controller will get the chosen option from the DropDownList from the view?
P.S - I have no Model.
This is my Controller:
//POST: Home
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(IEnumerable<HttpPostedFileBase> file, string folder, IEnumerable<SelectListItem> folders)
{
// some code here
}
This is my view:
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken();
<div class="container">
<div class="form-horizontal">
<div class="form-group">
<p></p>
<label for="file">Upload Photo:</label>
<input type="file" name="file" id="file" accept="image/*" multiple="multiple"/>
</div>
<div class="form-group">
<div>
<label>Choose Album:</label>
#if (ViewBag.Folders != null)
{
#Html.DropDownList("folders", new SelectList(ViewBag.Folders as IEnumerable<SelectListItem>, "Value", "Text"), "--- Select Album ---", new { #class = "form-control" })
}
</div>
</div>
<div class="form-group">
<div>
<input type="submit" value="Upload" class="btn btn-default" />
</div>
</div>
</div>
</div>
}
Thanks.
in order to get the folder, give your dropdownlist the corresponding name ...
#Html.DropDownList("folders"...
will result in your DDL to have the name "folders" ... which will try to post back a single item... folders in your method is a IEnumerable<SelectListItem> ... the modelbinder is incapable to convert that ...
try
#Html.DropDownList("folder"...
note the missing s
now the name corresponds to the string folder parameter in your method... which the binder will most likely be able to bind for you...
if you debug errors like this, use the debugger to have a look at HttpContext.Request.Params, which will show you what was coming back when the request was made...
Parameter type should be changed from IEnumerable to String as view returns only selected item NOT collection.
//POST: Home
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(IEnumerable<HttpPostedFileBase> file, string folder, string folders)
{
// some code here
}
Just wanted to give another option. If you're able to leverage a client-side solution, then you could muscle this a bit with a hidden input value and JQuery.
Add a hidden input control:
<input name="selectedFolder" type="hidden" value="" />
Add some Jquery:
<script type="text/javascript">
$(function(){
$("#folders").on("change", function {
$("#selectedFolder").val($(this).text());
});
});
</script>
Thank you Sakthivel Ganesan, after changing the IEnumerable<SelectListItem> folders in the Controller to string folders, the only thing left to do is to change my Html.DropDownList Value to Text like this...
from :
#Html.DropDownList("folders", new SelectList(ViewBag.Folders, "Value", "Text"), "--- Select Album ---", new { #class = "form-control" })
To:
#Html.DropDownList("folders", new SelectList(ViewBag.Folders, "Text", "Text"), "--- Select Album ---", new { #class = "form-control" })

MVC 5 Viewmodel binding works but post back is partial filled

I have a parameterless Index for the HttpGet which works. But when I post it the HttpPost version of Index is invoked and the viewmodel object is passed in, but there is only the value of the dropdown in it. The rest is null (products, title)
[HttpPost]
public ActionResult Index(ProductsViewModel pvm)
{
// breakpoint on line 36, shows that pvm.Title is null and Products too.
return View(pvm);
}
My compilable and running example can be downloaded from my OneDrive http://1drv.ms/1zSsMkr
My view:
#model KleinKloteProductOverzicht.Models.ProductsViewModel
#using (Html.BeginForm("Index", "Products"))
{
<h2>#Html.DisplayFor(m => m.Title)</h2>
<input type="submit" value="post dit" /><br/>
<div class="row">
<div class="col-lg-2 col-md-2">
#Html.DropDownListFor(x => x.CurrentSort, EnumHelper.GetSelectList(typeof(SortOptions)), new { #class = "multiselect"})
</div>
</div>
if (Model.Products.Count() > 0)
{
<div class="row">
#foreach (var item in Model.Products)
{
#Html.DisplayFor(i => item.Name);
}
</div>
}
}
If I have this view model:
public class ViewModel
{
public string Name {get;set;}
public string SelectedLocation {get;set;}
public IEnumerable<SelectListItem> Locations {get;set;}
}
And your actions look like this:
public ActionResult MyForm()
{
var vm = new ViewModel
{
Locations = context.Locations.ToList() // Some database call
}
return View(vm);
}
[HttpPost]
public ActionResult MyForm(ViewModel vm)
{
vm.Locations // this is null
}
It is null because the model binder can't find a form control that is setting its data.
The <form> must set some data in the view for the model binder to pick it up.
<form>
Name: <input type="text" id="name" />
</form>
This will set the Name property on the view model, because the model bind can see the id of the form control and uses that to know what to bind to.
So in terms of your view, you need to make sure you wrap any content that you want to post back to the server with #using(Html.BeginForm())
Anyway this is my guess.
Well, you seem to be confused as to how [HttpPost] and form tags interact with eachother.
You see, when .NET MVC binds your parameters in your controller actions, it tries to derive that data from the request. For [HttpGet] it does this by looking at the query string.
For [HttpPost] calls, it also looks at the Request.Form. This variable is populated with the values of all input fields that were inside the form you submitted.
Now, this is your view:
#using (Html.BeginForm("Index", "Products"))
{
<h2>#Html.DisplayFor(m => m.Title)</h2>
<input type="submit" value="post dit" /><br/>
<div class="row">
<div class="col-lg-2 col-md-2">
#Html.DropDownListFor(x => x.CurrentSort, EnumHelper.GetSelectList(typeof(SortOptions)), new { #class = "multiselect" })
</div>
</div>
if (Model.Products.Count() > 0)
{
<div class="row">
#foreach (var item in Model.Products)
{
#Html.DisplayFor(i => item.Name);
}
</div>
}
}
You only have one select tag (generated by Dropdownlistfor) but no other inputs. That's why .NET MVC cannot infer any other data for your view model.
If you change your view to this:
#model KleinKloteProductOverzicht.Models.ProductsViewModel
#using (Html.BeginForm("Index", "Products"))
{
<h2>#Html.DisplayFor(m => m.Title)</h2>
<input type="submit" value="post dit" /><br/>
<div class="row">
<div class="col-lg-2 col-md-2">
#Html.DropDownListFor(x => x.CurrentSort, EnumHelper.GetSelectList(typeof(SortOptions)), new { #class = "multiselect" })
</div>
</div>
if (Model.Products.Count() > 0)
{
<div class="row">
#for (var i = 0; i < Model.Products.Count; i++)
{
#Html.DisplayFor(model => model.Products[i].Name)
#Html.HiddenFor(model => model.Products[i].ID)
}
</div>
}
}
You'll see I've added a hidden input (<input type="hidden">) for the product id. Note that the product name still will be null.
I would suggest you follow a tutorial on .NET MVC and read up on some of the concepts behind it, because the very fact that you ask this question reveals that you have much to learn.
Best of luck!
P.S. One last tip: #Html.Blablabla writes directly to your view. You usually don't need that ";" at the end, because it will be inside your generated html.
Your property is not associated with a "postable" control, therefore it will not be submitted along with the form data. If your really want to get the value in your Title property, just set it as a hidden input.
#Html.HiddenFor(m => m.Title)
A label will not be posted when submitting a form but an input will. This is exactly what HiddenFor does; it creates a hidden input element which will be picked up by the form submit.

table id is not passing from view to controller in ASP.NET MVC5

I am using asp.net mvc5 app and I have partialView which I am using for both add and delete operations and I have separate actionResult to deal each requested according that is fire by jQuery Ajax functions.... I got figure problem when I try to edit record. it pick right record and display in screen in HttpGet actionResult but when I submit record with updated field, it doesn't update that in database and is because it doesn't send recordID {PK} back to action in controller unless I use hidden value for primary key in view... however with this I can't create new record!
partial View
#model DatabaseLayer.TableMappings.FeeZone
<script>
function CancelPage() {
$.ajax({
type: "POST",
url: "/Qualification/FeeZoneHome",
dataType: 'json',
success: function (jsonData) {
window.location = jsonData.redirectUrl;
},
error: function (error) {
}
});
}
</script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>FeeZone</h4>
<hr />
#Html.ValidationSummary(true)
<!--<div class="form-group">
<div class="col-md-10">
#Html.HiddenFor(model => model.FeeZoneID)
</div>
</div>-->
<div class="form-group">
#Html.LabelFor(model => model.FeeZoneDescription, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FeeZoneDescription)
#Html.ValidationMessageFor(model => model.FeeZoneDescription)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default">
<input type="button" value="Cancel" class="btn btn-default" onclick="CancelPage();" />
</div>
</div>
</div>
}
controller Method
[HttpGet]
public ActionResult EditFreeZoneByID(string FreeZoneID)
{
int numID = Convert.ToInt32(FreeZoneID);
return PartialView("Partial_CreateNewFreeZone", Q_UOF.GetFreeZoneByID(numID));
}
[HttpPost]
public ActionResult EditFreeZoneByID(FeeZone obj)
{
try
{
if (ModelState.IsValid)
{
Q_UOF.EditSubject(obj);
}
}
catch (DataException)
{
ModelState.AddModelError("FeeZone", "Unable to Save Changes.");
}
return RedirectToAction("FreeZone");
}
You need to send the Primary Key value from your form to your Action method so that it can update the proper record. For this you definitly need to keep the ID in the form in a hidden field.
I am not sure what you mean by "You can not create new record if you keep the hidden variable". I do not think it is going to be a problem. You can use the same HttpPost action method to save New record and update an existing record. You may simply check the value of your primary key property and If it is 0, Add a new record , else update existing record
[HttpPost]
public ActionResult EditFreeZoneByID(FeeZone obj)
{
if(obj.FreeZoneID==0)
{
//This is a new record. Save it
}
else
{
//Update an existing record now.
}
// to do : Return somethign valid or redirect
}

Categories