I have MVC webpage with DropDownList, this list is full of items and after click on the button i have notice that my controller method (Index) received an number as string so i have checked in my database and this number is my object ID.
is it possible to get another property of this item instead of this ID ?
Here is my view code:
#using (Html.BeginForm()) {
<div>
#Html.DropDownList("File", new SelectList(ViewBag.Files, "Id", "protocol_site"), "Select webmail site", new { style = "vertical-align:middle;" })
<button type="submit">Select</button>
</div>
}
[HttpPost]
public ActionResult Index(string File)
{
}
Just change the second parameter of your SelectList to the property name of the object you want to send to your controller.
new SelectList(ViewBag.Files, "PropertyName", "protocol_site")
Related
I have two <slect> list and I want to pass only Text to the controller. I don't know if its possible.
This is Html :
<form asp-action="Crea" method="post">
<select asp-for="Azienda_cliente" class="select2 form-control" id="ddlClienti" onchange="LoadSottoCliente(value)"></select>
<select asp-for="Azienda_sotto_clienti" class="select2 btn-block" id="ddlSottoClienti"></select>
<input type="submit" value="Crea" class="w-50 btn btn-success" />
</form>
And this is controller:
[HttpPost]
public async Task<IActionResult> Crea(Attiivita attivita)
{
if (ModelState.IsValid)
{
_db.Add(attivita);
await _db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View();
}
Is it possible to post only Text from the select list?
Any suggestions how to do that?
Thanks in advance!
I have two <select> list and I want to pass only Text to the controller.
In your form, when you submit the form, the Value of the selected option would be posted to controller action method.
If you'd like to post Text of the selected option to controller action, you can try following two approaches:
Approach 1: populate your dropdown(s) with expected data as Value property.
<select asp-for="Azienda_cliente" asp-items="ViewBag.ClientItems" class="select2 form-control" id="ddlClienti" onchange="LoadSottoCliente(value)"></select>
In action method
ViewBag.ClientItems = new List<SelectListItem>
{
//normally we populate Value property with Id etc field
//in your code logic, you can populate it with your expected data (same as you set for Text property)
new SelectListItem { Value = "ClientName", Text = "ClientName" },
//...
//other items
};
For the second dynamic dropdown, you can set Value property with same data as Text of each <option>.
$("select#ddlSottoClienti").append(`<option value="${text_here}">${text_here}</option>`);
Approach 2: you can get text of the selected option(s), then submit data using jQuery Ajax etc on JavaScript client side.
$("input[type='submit']").click(function (ent) {
ent.preventDefault();
var Azienda_cliente = $("select#ddlCLienti option:selected").text();
var Azienda_sotto_clienti = $("select#ddlSottoClienti option:selected").text();
//make ajax request to your controller action
//...
})
I have dynamically created radio buttons in my view and i am trying to pass the checked value to my controller. When my controller is hit the Agentcode string is Empty and i cant figure out how to grab the value so i can send it to my controller.
EDIT my radio buttons are generated in a foreach which i think may be causing the difficulty in reaching the value.
This is what the html rendered by the MVC control looks like
<div>
<input name="XXXXX" type="radio" value="{ data_bind = checkedValue: $data,checked: $root.AgentCode }">
</div>
foreach (var code in Model.ActiveAgentCodes)
{
<div>
#Html.RadioButton(code.AgentCode, new { data_bind="checkedValue: $data,checked: $root.AgentCode"})
#Html.RadioButton(code.AgentCode, new {data_bind="checkedValue: $data,checked: $root.AgentCode"}) }
my knockout ViewModel looks like this.
function ViewModel(){
var self = this;
self.AgentCode = ko.observable();
};
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
and the post method in my controller looks like this
[HttpPost]
public ActionResult GetAgentCodeForHomeController(string AgentCode)
{
return RedirectToAction("Home", "Home");
}
In my view i am posting using like so
#using (Html.BeginForm("GetAgentCodeForHomeController", "ChangeAccount"))
{
#Html.RadioButton(code.AgentCode, new {data_bind="checkedValue: $data,checked: $root.AgentCode"})
#Html.HiddenFor(model => model.AgentCode, new { data_bind = "text:AgentCode" })
}
<button type="submit">OK</button>
I needed to send data back to my controller and the best way that i found was to add properties to my viewmodel.
public string AgentCode {get; set;}
Then give the radio buttons an Id so that when the controller is hit MVC maps the properties correctly. I decided to not go with knockout and instead post the form back to the controller. It ended up looking like this on my buttons.
#Html.RadioButton("AgentCode", code.AgentCode, new {id = code.AgentCode})
What I want to do
I am very new to MVC.
I'm trying to create a page that allows users to perform the following actions on the same page:
View the list (table)
Add a new item (Filling the form and clicking the Add button should update the table)
Delete an item from the list (Clicking the Delete button in a row should update the table)
A simple example looks like this but I actually have two lists on one page (Fees and Costs):
Question
What would be the best way to achieve this?
Should I go with Dylan Beattie's method posted here which would look something like this?
public ActionResult MyAction(string submitButton, MyViewModel form)
{
switch (submitButton)
{
case "AddFee":
return (AddFee(form));
case "AddCost":
return (AddCost(form));
case "RemoveFee":
return (RemoveFee(form));
case "RemoveCost":
return (RemoveCost(form));
}
}
public ActionResult AddFee(MyViewModel form)
{
Fee newFee = ....; // Get entered data from `form`
_repository.InsertFee(newFee);
return View("Create"); //Back to the original page
}
Or is there any other recommended methods to handle this such as using JavaScript?
You could create the table as a partial view and re render this via ajax.
Wrap the partial view in a div and Wrap the form in #using (Ajax.BeginForm(.... and target the wrapper div. Your controller action that is targeted by the ajax request will need to return a partial view.
Here is a simple example
public class HomeController : Controller
{
public ActionResult Index()
{
MYvm vm = new MYvm() { id = 1, name = "This is my View Model" };
return View(vm);
}
public ActionResult DA(MYvm vm)
{
vm.name = "CHANGED";
return PartialView("Part", vm);
}
View:
#model MvcApplication1.Controllers.HomeController.MYvm
#{
ViewBag.Title = "Home Page";
}
#using (Ajax.BeginForm("DA", "Home", new AjaxOptions() { UpdateTargetId = "cont", HttpMethod = "Get" }))
{
<div>
Id: #Html.EditorFor(model => model.id)
</div>
<div>
Name: #Html.EditorFor(model => model.name)
</div>
<input type="submit" value="SubmitForm" />
}
<div id="cont">
#{Html.RenderPartial("part", Model);}
</div>
Partial View
#model MvcApplication1.Controllers.HomeController.MYvm
#{
ViewBag.Title = "part";
}
<h2>part</h2>
#Model.name
Should I go with [previous SO answer]
No. That answer was for a different scenario where the question had a form with two submit buttons that wanted to do two different actions (and wasn't even the accepted answer to that question).
Your sample screenshot indicates that some javascript/jquery and ajax would solve the issue cleanly.
As you're new to MVC, try to keep it relatively simple. Break up the page into separate parts:
the containing page
the edit form
the list with remove
the edit/list work independently and should be written in a way that they could be put on any other page - the page is just there to contain them and doesn't do much else (obviously your real page will contain more, but add those parts as separate components as well).
1 Create actions for your list and edit forms that return partialviews - just the parts that are needed for that view (self-contained)
controller:
[HttpGet]
public ActionResult AddCost()
{
var model = new Cost();
return PartialView(model);
}
[HttpPost]
public void AddCost(Cost model)
{
if (ModelState.IsValid) {
db.SaveCost(model);...
}
}
form Views/Home/AddCost.cshtml:
#using (Ajax.BeginForm(...
{
<div class='editor-label'>#Html.LabelFor(model=>model.Description)</div>
...etc...
}
I'll leave you to set the Ajax.BeginForm properties. But make sure the on-success calls reloadCostList() (see below)
controller
public ActionResult CostList()
{
var model = db.loadCosts(); ...
return PartialView(model);
}
list, Views/Home/CostList.cshtml
#model IEnumerable<ViewModels.Cost>
<table>
<thead>
<tr>
<th>Cost Description</th>
...
<tbody>
#foreach (var cost in Model.Costs)
{
<tr data-id='#cost.Id'>
<td>#Html.DisplayFor(x=>cost.Description)</td>
...
<td><a href='#' class='remove-button'>Remove</a></td>
}
...
2 Create an action + view for the main page with placeholder for the form and calls the list partial-action, eg:
<div id="body">
<div id="formWrapper">
#Html.Action("AddCost")
</div>
<div id="listWrapper">
#Html.Action("ListView")
</div>
</div>
if you already load the data for the page, you can pass it directly to the partial, but there's no need:
#Html.Partial("ListView", Model.Costs)
this allows you to refresh the list via an ajax call, something like:
function reloadCostList() {
$(".listWrapper").load("Home/CostList");
}
(ideally, $.ajax and add some fancy UI to indicate loading)
3 Add a remove action to your controller
[HttpPost]
public void RemoveCost(int id)
{
}
4 Wire up the Remove link
$(function() {
$(".remove-button").click(function() {
var id = $(this).closest("tr").attr("id");
$.post("/Home/RemoveCost/" + id, null, function() {
$(".listWrapper").load("Home/CostList");
// or reloadCostList(); from above
// or:
//$(".listWrapper tr[id=" + id + "]").hide();
});
});
}
rather than re-load the entire list, you could just remove the row (add some fancy UI like fade-out...)
I have a page which represents data from ICollection<> model, it generates #Html.BeginForm() for each item in ICollection<> and shows data with #Html.Labels, and I want to create a link from each form to item details, so it will be like, when I press form with item with id=4, it sends Model.ElementAt(4) as a model to new page, and display it. How can I do that?
EDIT: I guess I need to add something like #Html.ActionLink("DetailsPage","Shops",shop)
#using WebShops
#model ICollection<WebShops.Shop>
#foreach (Shop shop in Model)
{
using (Html.BeginForm())
{
#Html.Label(shop.name)
#Html.Display(shop.name)
<br />
#Html.Label(shop.image)
#Html.Display(shop.image)
<hr />
}
}
To display a specific item there is no need for Html.BeginForm because it makes a POST request and you need to make a GET request.
You need to create a new Action that will make use of GET request.
public ActionResult Shop(string id)
{
var shop = //get shop by id from database
return View(shop)
}
You call the new action like below.
#using WebShops
#model ICollection<WebShops.Shop>
#foreach (Shop shop in Model)
{
#Html.Label(shop.name)
#Html.Display(shop.name)
<br />
#Html.Label(shop.image)
#Html.Display(shop.image)
<hr />
#Html.ActionLink("Display", "Shop","ControllerName", new {id = shop.id})
}
You can do that using the object routeValues from this overload of Html.ActionLink:
#Html.ActionLink("DetailsPage","Shops", new { id = shop.ID })
This doesn't "send the model to the new page", it makes a link to Shops/DetailsPage/4, causing GET request when clicked.
So in the DetailsPage action method you'll have to look up the shop on ID again in order to display it.
I'm working on a MVC production project.
In my Production details view I have some buttons to get some more data from the database, but for this I need the id of the Product. I can see it exist but can I catch it?
Here's my controller that return data:
public ActionResult Details(long AProductionOrderId)
{
ProductionOrderList item = new ProductionOrderList();
item = ProductionOrderReg.GetProductionOrders(conn, AProductionOrderId);
ViewData["item"] = item;
return View();
}
Here's my details page when it load, I can see the id, but how to catch and use it in the buttons in the left to bring more date ?
You could use a hidden input on your view page to submit the ID.
your View:
<form method="post">
<button type="submit">Button Text</button>
<input type="hidden" name="AProductionOrderId" value="#ViewData['item']">
</form>
i wrote this im my controller
ViewData["id"] = AProductionOrderId;
and catched it in my view
long id = Convert.ToInt64( ViewData["id"]);
If you controller is:
public ActionResult Details(long AProductionOrderId)
{
var item = ProductionOrderReg.GetProductionOrders(conn, AProductionOrderId);
ViewBag.ProductionOrderId = AProductionOrderId;
return View(item);
}
then your AProductionOrderId will be in the ViewBag although I don't see the reason why you need it since whatever the type of item is (single object instance or list of objects) it contains your ID as a property because you're fetching the item by this ID. Anyway in your model you then need to declare your model like this:
#model YourModelNamespace.ProductionOrderList
and now you can access any property of your model in your view. But if you really want you can access it via ViewBag like this:
#{
long AProductionOrderId = Viewbag.AProductionOrderId;
}