Passing a dropdown selected value to a contorller - asp.net-mvc

I'm playing around in an MVC application and am trying to figure out something that seems pretty straight forward.
I have a Index.cshtml file in my Views/Home/ folder that is pretty simple (below)
Index view
...
<div>
Search
#Html.DropDownList("selection", MyProject.Util.Lists.GetMyList(), "Select One")
#Html.ActionLink("Search", "Index", "Search", new { st = xxx }, null)
</div>
...
I also have a Search controller that needs to take a "st" value and looks like this
public class SearchController : Controller
{
// GET: Search
public ActionResult Index(string st)
{
ApplicationDbContext db = new ApplicationDbContext();
List<Report> filteredReports = db.Reports.Where(r => r.Tag == st).ToList();
return View(filteredReports);
}
}
What I'm not sure of how do is grab what ever value is selected from the drop down and add that to my Html.ActionLink where I just have 'xxx' now.

Clicking on the link usuallly does a new GET request to the href attribute value of the link. It will not send any data from your form.
You need to use javascript and hijack the click event on the link and append the selected option value from the SELECT element as querystring to that and send it.
So give an id to the link which you can use later to wireup the click event
#Html.ActionLink("Search", "Index", "Search", null, new {#id="search"})
And the javascript
$(function(){
$("#search").click(function(e){
e.preventDefault();
window.location.href=$(this).attr("href")+"?st="+$("#selection").val();
});
});
Another option is to use the form submit. Wrap your select element inside a form and have a submt button which sends the form to the action method. This method does not need javascript. But your select input element name should match with your parameter name.
#using(Html.BeginForm("Index","Search",FormMethod.Get))
{
<div>
Search
#Html.DropDownList("st", MyProject.Util.Lists.GetMyList(), "Select One")
<input type="submit" value="Search" />
</div>
}
If you do not prefer to have button, but need the link element, you can use javascript to submit the form (like we did in the first approach). With this approach you do not need to manually append the querystring.

You have to call a AJAX POST call to your controller which store selected value, and then when your action link event fire get stored value from there.
AJAX:
$.ajax(
{
url:your url,
data:{"st":dropdown selected value},
type:"post"
});
Controller:
public ActionResult Index()
{
string st=TempData["st"].ToString();
ApplicationDbContext db = new ApplicationDbContext();
List<Report> filteredReports = db.Reports.Where(r => r.Tag == st).ToList();
return View(filteredReports);
}
public void SetSt(string st)
{
TempData["st"] = st;
}

Related

model values are not showing in partial update view

In my web app I have a grid list. I select a row and then click the edit button to show a partial update view (which I use to add new data too) in a popup window. The view shows, but I don't have any values in the textboxes. I use devextreme components, but I think, my issue has nothing to do with it (maybe I'm wrong).
This is the onClick code:
function editrow_onClick() {
var key = $("#grid").dxDataGrid("instance").getKeyByRowIndex(selectedRowIndex);
$.ajax({
url: '/MasterData/Sender/UpdateSender/'+key,
}).done(function (response) {
var popup = $("#sender-popup").dxPopup("instance");
popup.option("contentTemplate", function (content) {
content.append(response);
});
popup.show();
});
}
If I click the edit button, I get the right url like /MasterData/Sender/UpdateSender/3.
The corresponding controller action looks like this:
[Route("{id}")]
public IActionResult UpdateSender(long SenderId)
{
return PartialView("NewSender", SenderRepository.GetSender(SenderId));
}
On top of the controller class I have the corresponging attribute: [Route("MasterData/[controller]/[action]")]
I testet id, the action is reached, but the SenderId is 0. I would expect f.e. 3. This should be causing the empty view, I think. Why is SenderId 0 (the default value)?
I post the update view too, maybe this is the source of the problem (don't bother the AddSender action, I plan to change it conditionally, if I get the update data working):
#model Sender
<form asp-action="AddSender" asp-controller="Sender" method="post">
#using(Html.DevExtreme().ValidationGroup()) {
#(Html.DevExtreme().Form<Sender>()
.ID("form")
.ColCount(1)
.Items(items => {
items.AddSimpleFor(m => Model.Name);
items.AddSimpleFor(m => Model.Address);
items.AddSimpleFor(m => Model.ContactPerson);
items.AddSimpleFor(m => Model.ContactEmail);
items.AddGroup().Items(groupItem => groupItem.AddSimple().Template(
#<text>
<div style="text-align: right">
#(Html.DevExtreme().Button().ID("save").Text("Mentés").Width(100).Type(ButtonType.Success).UseSubmitBehavior(true))
#(Html.DevExtreme().Button().ID("cancel").Text("Mégsem").Width(100).Type(ButtonType.Normal).OnClick("close_onClick"))
</div>
</text>));
})
.LabelLocation(FormLabelLocation.Top)
.FormData(Model)
)
}
</form>
<script>
function close_onClick() {
$("#sender-popup").dxPopup("hide");
}
</script>
[Route("{SenderId}")] public IActionResult UpdateSender(long SenderId) { return PartialView("NewSender", SenderRepository.GetSender(SenderId)); }
Try replacing id with SenderId.
Then action method will hit with the desired value.

How can send html text box value with Url.Action to controller action method input argument?

I'm new in asp.net mvc and want to read html text box value and send it to the controller action method argument,for that purpose in view page write this code:
#item.BookName
in url action in this segment:
UserID=html text box value
read value and send it to this action in controller:
public ActionResult Item(int parentPartId,int UserID)
{
}
in view page my text box is this:
<input type="text" id="USERID"/>
How can i solve that problem?thanks.
You can handle the click event of the hyperlink and inject the value from the textbox into it, like this:
HTML:
<a class="BookName" href="" data-id="#item.Id">#item.BookName</a>
Script (assumes you have jQuery, but easily re-writable if not):
$(".BookName").click(function(event)
{
event.preventDefault();
var url = '#Url.Action("Item", "Store", new {parentPartId = "PARENT_ID",UserID="USER_ID"})';
url = url.replace("USER_ID", $("#USERID").val());
url = url.replace("PARENT_ID", $(this).data("id"));
alert(url); //just for debugging
window.location.href = url;
});
You might want to check the input value is valid before you do this, but this will get you started.
Textbox value is dynamic. It depends on user input. Razor tags are compiling at the server and posting to the client.So your razor code can not understand what user going to do to your text area. You need an action trigger the method that includes determining the text box values and send to the server. You can use ajax function.
With Jquery's help.
I think #item is a loop variable.
you can change your code like below
<a onClick="myFunction(#item.id)">#item.BookName</a>
as you see i catch the id and type down as a paramenter.
this is your text area
<input type="text" id="USERID"/>
this is the javascript function that gets the textbox value and sends it to your action
function myFunction(id){
var userId = document.getElementById("UserID").value;
var data ={
parentPartId:id,
UserID:userId
}
$.ajax({ //Jquery stuff
url : '/Store/Item'
type:'POST',
data:data
dataType:'json'
success:function(){//You can handle succes scenario}
});
}
See the data's structure it is a JSON object. And parameter names are same as your actions parameters. When you send it. MVC going to understand the logic and match the parameters and values. )
You need to place form and post your data via model/Form collection
view code
#using (Html.BeginForm("SaveData", "TestCont", FormMethod.Post, new { Id = "frmTest", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<input type="text" id="USERID" name="UserID"/>
}
controller:
[HttpPost]
[ValidateInput(false)]
public ActionResult SaveData(FormCollection form)
{
string html = Convert.ToString(form["UserID"]);
}
make sure to mark [ValidateInput(false)] otherwise it will raise error on posting html
You can place a submit button in form to post it, or in JavaScript use $('#frmTest').submit()

chaining the items of Razor DropDownLists

I have 3 DropDownLists; when I select an item in #1, I want the items in #2 to be filled according the value of #1. And when I select an item in #2, the items in #3 should be filled according the selection in #2. They all are located in a form named GetItemsForLeve1. I've started by using onchange of the drop-down.
<% using (Html.BeginForm("GetItemsForLeve1", "Index"))
{ %>
Main Group: <%:Html.DropDownList("Level1", (SelectList)ViewBag.Level1, "Select One", new { onchange = "$this.form.submit()" })%>
<%:Html.DropDownList("Level2", (SelectList)ViewBag.Level2, "-", new { onchange = "$this.form.submit()" })%>
<%:Html.DropDownList("Level3", (SelectList)ViewBag.Level3, "-", new { onchange = "$this.form.submit()" })%>
<input type="submit" value="Filter" />
<%}%>
Is it possible to fill the level 2 and level 3 drop-down lists without sending the page back to the server?
How can I tell which drop-down list has been clicked in the GetItemsForLevel action?
I am completely new to MVC, so I appreciate telling me in a simple way?
Thank you
As far as I know, there's not really a component that does this for you. But you can use the Ajax.BeginForm helper to build it.
the first ajax form should contain the first select list, and post back to an action that returns a partial view
the partial view in 1. should return the second ajax form with a second select list
and so forth
So the main Razor view should contain something like this:
#using (Ajax.BeginForm("SecondAjaxForm", new AjaxOptions() { UpdateTargetId = "secondFormDiv" })
{
#Html.DropDownList("selectList1", Model.FirstSelectList, new { onchange = "this.form.submit()")
}
<!-- the second AJAX form + drop-down list will get populated here
<div id="secondFormDiv"></div>
And the SecondAjaxForm action:
public ActionResult SecondAjaxForm(string selectList1)
{
SelectList secondSelectList;
// populate the second select list here
return PartialView("SecondAjaxForm", secondSelectList);
}
The partial view SecondAjaxForm should be basically the same as the first form above.
#model SelectList
#using (Ajax.BeginForm("ThirdAjaxForm", new AjaxOptions() { UpdateTargetId = "thirdFormDiv" })
{
#Html.DropDownList("selectList2", Model, new { onchange = "this.form.submit()")
}
<!-- the third AJAX form + drop-down list (if any) will get populated here
<div id="thirdFormDiv"></div>

Posting an array of HTML.DropDownList values to controller action method

So in my view I am dynamically creating dropdown lists in a for loop. I use the same name value in unique id values.
#foreach(var item in Model.Items)
{
#Html.DropDownList("Items" Model.GenerateSelectList(item.id), new { id = item.id })
}
In my controller action method for the post I can get the values of the dropdowns like this:
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize]
public ActionResult ClassicLineup(IList<int> items)
{
}
I cannot figure out how to get BOTH the dropdown id and associated value.
Seems like it should be simple but it has me stumped...
Thanks.
On form submit browser sends only the selected value of a dropdown, so there is no bult in mechanism to read the text of selected item, but you can create one for you.
In below code i have created a hidden input which stores the text of current selected item, and is send to the server on form post.
You can create below list in controller or in view (preferred place in controller);
var items= (from item in Model.Items
select new SelectListItem
{
Value= item.DisplayProperty
Text= item.Value
}).toList();
<form action="controller/test">
#*This will create DD*#
#Html.DropDownList("MyDropDownList", items)
#*Hidden input*#
<input type="hidden" id="ddSelectedName" name="ddSelectedName" />
<br>
<input type="submit" value="submit"/>
</form>
Include jQuery in ur code and then add this
<script type="text/javascript">
$('#MyDropDownList').change(function () {
$('#ddSelectedName').val($(this).find(':selected').text());
});
</script>
Controller
public string test(string MyDropDownList, string ddSelectedName)
{
return MyDropDownList+ "--"+ddSelectedName ;
}
I just ended up looping through the forms collection and parsing the dropdown id (form.key) and the dropdown value (form.key.value).
Apparently there is not an easy way to have MVC bind the dropdown values and id to a collection in the controller action parameter.

Actionresult doesnt get called by routelink. Formcollection the culprit?

I am fairly new to MVC. I am trying to set up a search page that searches a database and returns results. The search box is within a Html.BeginForm in my View, and looks like this:
<% using (Html.BeginForm())
{ %>
<%= Html.TextBox("searchBox", null, new { #id = "searchBox" })%>
<div id="searchButtonsDiv">
<input type="submit" value="Search" />
</div>
<% } %>
//Results are returned in a ul and orgainized
//Pagination below
<% if (Model.HasPreviousPage)
{ %>
<%= Html.RouteLink("Previous", "SearchResults", new { page = (Model.PageIndex - 1) })%>
<% } %>
<% if (Model.HasNextPage)
{ %>
<%= Html.RouteLink("Next", "SearchResults", new { formCollection = "", page = (Model.PageIndex + 1) })%>
<% } %>
I am using a FormCollection to pass to my controller that looks like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection formCollection, int? page)
{
var searchString = formCollection["searchBox"];
var results = resultsRepository.GetResults();
var paginatedResults = new PaginatedList<Driver>(results, page ?? 0, pageSize);
return View(paginatedResults);
}
So far so good. When I type a word and press the submit button, Index gets called and the database returns accordingly. The ul gets populated with the results, and when there are more than pageSize results (10 in my case), the Next link shows up.
When I click "Next", the default page just loads. No pagination or anything like that. I'm pretty sure it has to do with the fact that my Index ActionResult has a FormCollection as a paramater. I thought I read somewhere that only strings/ints can be handled? Here is the MapRoute:
routes.MapRoute(
"SearchResults",
"Drivers/Index/{formCollection}/{page}",
new { controller = "Drivers", action = "Index", formCollection = "", page = "" }
);
Am I completely missing something or is there a way to handle this? I know I could just use jquery/ajax to send the string contained in the search listbox, but I don't want to do that because later I plan on adding checkbox's as means of filtering searches, etc.
I tried several different ways of setting the formCollection's value, including creating a new FormCollection that adds the searchBox, and just passing strings, etc.
The FormCollection argument in the action isn't the problem. That will always work.
It absolutely does not belong in your route, however! Just get rid of that and you'll probably solve the problem. Form elements don't go in the URI, and only stuff in the URI should be in the route.
It's not how I'd write that action signature, however. I'd suggest:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string searchBox, int? page)
{
var results = resultsRepository.GetResults();
var paginatedResults = new PaginatedList<Driver>(results, page ?? 0, pageSize);
return View(paginatedResults);
}
Finally: You shouldn't return a View from a POST in this case. This will cause weird behavior for the user; e.g., when they press refresh their browser will warn them about re-submitting the form.
You should either:
Use a GET, not a POST for search results.
Redirect instead of returning a view.
I'd pick the first, personally.

Resources