I have a strongly typed view and I'm trying to pass the input from a textbox upon a button click to an action using BeginForm. My code keeps passing a null object to the action method in the controller. How do I pass the object to the controller via the form ?
#using (#Html.BeginForm("GetQueueInfoWorkorder","Home", FormMethod.Post, new { id = Model}))
{
#Html.TextBoxFor(x=> x.ID);
<input type="Submit" value ="Search" class="ui-button-icon-secondary"/>
}
Here is the actionmethod :
[HttpPost]
public ActionResult GetQueueInfoWorkorder(UserResponse id)
{
//Check queue complete
int woNumber = Convert.ToInt32(id);
tb_QueueCompleted completed = db.tb_QueueCompleted.SingleOrDefault(x => x.WorkOrderNumber == woNumber);
if (completed != null)
{
var u = new UserResponse { ID = completed.QueueId.ToString() };
GetLogInfoCompleted(u);
return View("GetLogInfo");
}
//check queue pending
return View();
}
I think you're fairly close, but make these changes & it should work as expected:
Model:
public class UserResponse
{
public int ID { get; set; }
}
View:
#model UserResponse
#using (Html.BeginForm("GetQueueInfoWorkorder", "Home"))
{
#Html.TextBoxFor(x => x.ID);
<input type="Submit" value ="Search" class="ui-button-icon-secondary"/>
}
Action method:
public ActionResult GetQueueInfoWorkorder(UserResponse model)
{
int woNumber = model.ID;
//...
}
if the #model of your view is UserResponse , then on submission of this page the model (UserResponse) will automatically get submitted to the controller. Where have you declared the #model for the view.
Related
This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 4 years ago.
I ran out of options checking why my HttpPost parameter is always null.My Models, View and Controllers are below. In general, I have a model with all details of medication administered to patients (Model 1) below. Then, I created another model with one property which is a list of my first model (Model 2). Model 2 is being passed to the view as shown in the HttpGet action. My HttpPost action accepts a parameter which is a list of Model 1. This list is being passed in my view in the following line which is within the View:
using (Html.BeginForm("ClientChargeInput", "Home", new { #vm = Model.patients.ToList() }, FormMethod.Post, null))
Any feedback?
Model
public class ControlledSubstancesEntity
{
public string facility { get; set; }
public string program_x_rrg_value { get; set; }
public string PATID { get; set; }
//More properties
}
Model being passed to View
public class ControlledSubsViewModel
{
public List<ControlledSubstancesEntity> patients { get; set; }
}
HttpGet Controller Action
[HttpGet]
public ActionResult ClientChargeInput(DateTime adminDate, string Facility)
{
ControlledSubsViewModel vm = new ControlledSubsViewModel();
//Some logic that populates vm
return View(vm);
}
View
#model ControlledSubstancesChargeInput.Models.ControlledSubsViewModel
#{
ViewBag.Title = "ClientChargeInput";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#if (Model != null && Model.patients.Count() > 0)
{
using (Html.BeginForm("ClientChargeInput", "Home", new { #vm = Model.patients.ToList() }, FormMethod.Post, null))
{
<input type="submit" value="Charge Input" id="btnSubmit" class="btn btn-info btn-sm" onclick="PostCharge()" />
#*Fields are shown*#
#foreach (var p in Model.patients)
{
#Html.HiddenFor(model => p.facility)
#Html.HiddenFor(model => p.program_x_rrg_code)
#Html.HiddenFor(model => p.program_x_tx_setting_code)
}
}
}
else
{
#*#Html.Action("ShowReport");*#
}
HttpPost Controller Action
[HttpPost]
public ActionResult ClientChargeInput(List<ControlledSubstancesEntity> vm)
{
//On breakpoint vm is always null
}
You can try to use ControlledSubsViewModel instead of List<ControlledSubstancesEntity> class, then you can use vm.patients to do your logic.
because you use ControlledSubsViewModel in the razor view that pass the parameter format will like ControlledSubsViewModel.
[HttpPost]
public ActionResult ClientChargeInput(ControlledSubsViewModel vm)
{
//vm.patients use this property
}
Because Model.patients is a collection, you can use for loop set input tag (hidden or text) look like this.
#if (Model != null && Model.patients.Count() > 0)
{
using (Html.BeginForm("ClientChargeInput", "Home",FormMethod.Post))
{
<input type="submit" value="Charge Input" id="btnSubmit" class="btn btn-info btn-sm" onclick="PostCharge()" />
for (int i = 0; i < Model.patients.Count; i++)
{
#Html.TextBoxFor(m => Model.patients[i].PATID);
#Html.TextBoxFor(m => Model.patients[i].facility);
#Html.TextBoxFor(m => Model.patients[i].program_x_rrg_value);
}
}
}
else
{
#*#Html.Action("ShowReport");*#
}
You still need to create ControlledSubstancesEntity as hidden-fields even if you do not want to display them on the page.
#using (Html.BeginForm("Index", "Home", FormMethod.Post, null))
{
for (int i = 0; i < Model.patients.Count; i++)
{
#Html.HiddenFor(x => Model.patients[i].facility)
#Html.HiddenFor(x => Model.patients[i].program_x_rrg_value)
#Html.HiddenFor(x => Model.patients[i].PATID)
}
<input type="submit" value="Charge Input" id="btnSubmit"
class="btn btn-info btn-sm" onclick="PostCharge()" />
}
Then use ControlledSubsViewModel as a parameter in HttpPost action method.
(click on the image to view in full screen)
I'm very new to MVC and I'm not sure quite how the forms work. Here's what i want to do:
So I've got two text boxes and an enter button in a form I want to put two values into the textboxes and use them in my external link. Here's the code I am trying to use, i know it's not correct at all but should show you what I'm trying to do:
View:
#model Test.Models.Home
#{
ViewBag.Title = "Main";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("GetMessage()", "Home", FormMethod.Post))
{
#Html.Label("Location1: ")
#Html.TextBoxFor(model => model.Location1)
#Html.ValidationMessageFor(model => model.Location1)
#Html.Label("Location2: ")
#Html.TextBoxFor(model => model.Location2)
#Html.ValidationMessageFor(model => model.Location2)
<button type="submit">Enter</button>
}
Controller:
using System.Web.Mvc;
using BBWebApp.Models;
namespace Test.Controllers
{
public class HomeController : Controller
{
public ActionResult Main()
{
//var name = new Home() { Name = "Google maps API" };
return View();
}
[HttpPost]
public ActionResult Location(Home model)
{
if (ModelState.IsValid)
{
//TODO: SubscribeUser(model.Email);
}
return View("Main", model);
}
[HttpPost]
public ActionResult GetMessage()
{
return Redirect("https://example.com/" + Location1 + "/" + Location2);
}
}
}
Model:
public class Home
{
public string Location1 { get; set; }
public string Location2 { get; set; }
public string Name { get; set; }
}
As you can see I'm trying to get the form to trigger the redirect function under getMessage() but obviously this code is flawed as I don't fully understand how it works. As i said I'm very new to MVC so any help with this would be much appreciated.
This code is very good for starting. Only have some minor problems:
On your view's using block, remove paranthesis from action method
GetMessages
like that
#using (Html.BeginForm("GetMessage", "Home", FormMethod.Post))
{
#Html.Label("Location1: ")
#Html.TextBoxFor(model => model.Location1)
#Html.ValidationMessageFor(model => model.Location1)
#Html.Label("Location2: ")
#Html.TextBoxFor(model => model.Location2)
#Html.ValidationMessageFor(model => model.Location2)
<button type="submit">Enter</button>
{
Then you need to get your model and use variables on your controller's method
[HttpPost]
public ActionResult GetMessage(Home model)
{
return Redirect("https://example.com/" + model.Location1 + "/" + model.Location2);
}
and you are good to go.
I have an ASP.NET MVC project with entities based on EF6 (model first). So my entities are all auto-generated for me. I have an entity, Site and I just want the user to select a Site before proceeding. I have tried a couple of ways, all of them work, but they seem very messy and unnecessary.
I was curious about the cleanest way to create a DropdownList of Sites, then get the selected site when the form is submitted (by Id or whatever other mechanism is better).
Currently I have:
The index where the user is asked to select a site:
public ActionResult Index()
{
ViewBag.Sites = new SelectList(db.Sites.ToList(), "Id", "Name");
return View();
}
The view:
#using (Html.BeginForm("SetSite", "Home"))
{
#Html.Label("sites", "Site:");
#Html.DropDownList("Sites", null, new { #class = "selectpicker" });
<div style="width:100%;height:25px"></div>
<button class="btn btn-default" style="width:100%">Go</button>
}
And the SetSite action, where the form is submitted
[HttpPost]
public ActionResult SetSite()
{
if (Request.Form["Sites"] != null)
{
Session["Site"] = db.Sites.Find(Request.Form["Sites"]);
return RedirectToAction("Home");
}
else
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
}
A few problems arise from this method. First, I really wanted to take advantage of the #model functionality in razor and point it towards my Site class, but since it's auto-generated, I don't want to go poking around and adding a whole bunch of view properties. (beggars can't be choosers?)
Second, the Request.Form['Sites'] returns a string, and converting it to and int is ugly as hell.
As I mentioned, I'd like to use the #model functionality with Html.DropDownListFor. Is that possible when working with a list of Sites from the DB?
How can I get this done cleanly?
Solution 1:-
Controller:-
private List<Country> GetCountries()
{
var list = new Entity.Result<List<Entity.Country>>();
list = _context.Countries.Select(tc => new Entity.Country
{
Id = tc.Id,
Name = tc.Name,
IsdCode = tc.Code,
}).ToList();
return list.Data.Select(x => new Country
{
id = x.Id,
Name = x.Name,
}).ToList();
}
HttpGet Method:-
public ActionResult Add(int id)
{
try
{
}
catch (Exception ex)
{
}
finally
{
ViewBag.countryList = GetCountries();
}
return View()
}
View Method:-
#Html.DropDownListFor(x => x.countryId, new SelectList(ViewBag.countryList, "id", "Name"), KahandasDhanji.Common.Localization.Application.Resources.ddlCountry,
new { #id = "ddlCountry", #rows = 1 })
In Http Post Form Submitimg u handle that model value in HTTPPOST Method.
Solution 2:-
FormCollection class we can capture the form's values within the controller.
[HttpPost]
public ActionResult Add(FormCollection form)
{
string strDDLValue = form["Sites"].ToString();
return View(MV);
}
Hope Its Work !!!
You can use a ViewModel to avoid converting the string value from Request.Form. Below is how your ViewModel class should look like
public class MyViewModel
{
public MyViewModel()
{
this.DropdownItems = new List<SelectListItem>();
}
public int SelectedSiteId { get; set; }
public List<SelectListItem> DropdownItems { get; set; }
}
Change the get action method in your controller as below
public ActionResult Index()
{
List<Site> sites = db.Sites.ToList();
MyViewModel model = new MyViewModel();
foreach(var site in sites)
{
model.DropdownItems.Add(new SelectListItem() { Text = site.Name, Value = site.ID.ToString() });
}
return View(model);
}
Add #model MyViewModel at the first line in your view code and use Html.DropDownListFor method to generate the dropdownlist
#model MyViewModel
#using (Html.BeginForm("SetSite", "Home"))
{
#Html.Label("SelectedSiteId", "Site:");
#Html.DropDownListFor(m => m.SelectedSiteId, Model.DropdownItems, new { #class = "selectpicker" })
<div style="width:100%;height:25px"></div>
<button class="btn btn-default" style="width:100%">Go</button>
}
The post action method in your controller should look like below. model.SelectedSiteId will be the selected value of the dropdownlist and the type is int so you won't have to do any conversion such as Convert.ToInt32(Request.Form['Sites']).
[HttpPost]
public ActionResult SetSite(MyViewModel model)
{
Session["Site"] = model.SelectedSiteId;
return RedirectToAction("Home");
}
I am starting in asp.net Mvc and making test, i am doing a simple chat using PubNub api and i want finish it using only razor code only and one page only.
Model Chat.cs:
namespace SimpleChat.Models
{
public class Chat
{
public string NuevoMensaje { get; set; }
public string TextArea { get; set; }
}
}
View:
#model SimpleChat.Models.Chat
#using (Html.BeginForm("Index","Chat",FormMethod.Post))
{
#Html.LabelFor(model => model.NuevoMensaje, "Nuevo Mensaje")
#Html.TextBoxFor(model => model.NuevoMensaje)
<input type="submit" class="btn-default" value="Enviar" />
#Html.TextAreaFor(model => model.TextArea)
}
Controller:
static string variante = "";
public ActionResult Index()
{
pubnub.Subscribe<string>("Chat", subCallback, connecCallBack, errorCallback);
//Chat nuevochat = new Chat();
return View();
}
[HttpPost]
public ActionResult Index(Chat chat)
{
pubnub.Publish<string>("Chat", chat.NuevoMensaje, userCallback, puberror);
chat.NuevoMensaje = "";
chat.TextArea =variante;
return View("Index",chat);
}
private void subCallback(string obj)
{
string[] retorno = obj.Split(',','"');
variante += "Richard dice:" + retorno[0] + "\n";
}
When i press submit don't get the new data, why?
If you want to render the updated value of TextArea property of your view model, You should clear the model state dictionary.
Model state dictionary has the initial values of your form inputs. So when razor (re)render the same view, It gives priority to the content in model state dictionary than the view model object you passed to the view.
You can use the ModelState.Clear() method to clear the model state dictionary values before returning to the view.
chat.TextArea = variante;
ModelState.Clear();
return View("Index",chat);
Assuming your variante variable has the updated text.
I've read a couple of questions and answers on this matter but none of them gets me any closer to solving this issue. My problem is I can't seem to retain the RadioButtonFor checked value to the post action method. It's alot of unrelated stuff so i'll try to boil it down to the related issue.
So I've got a ViewModel like this:
public class QEventHandlerVM
{
//Removed unrelated
public QueueEventHandlerModel QEventHandler { get; set; }
public string SelectedOption { get; set; }
}
The Get Method for the edit view. I'm setting the SelectedOption here so I can work with it on the frontend. The task is to show and hide div depending on the SelectedOption value. This part is working as far as I know, the value gets set and is used in the view via jQuery.
[HttpGet]
public ActionResult Edit(int id)
{
try
{
//Removed unrelated...
QueueEventHandlerModel model;
QEventHandlerVM vm = new QEventHandlerVM();
ApiCommunicator.Get("QueueEventHandlers/" + id, out model);
vm.QEventHandler = model;
if (...)
vm.SelectedOption = "toQueue";
if (...)
vm.SelectedOption = "redirection";
if (...)
vm.SelectedOption = "hangup";
return View(vm);
}
catch (HttpResponseUnsuccessfulException e){...}
}
The Edit view simplified:
#model Foo.WebSites.Web.Views.QueueEventHandlers.QEventHandlerVM
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
//Unrelated stuff...
#Html.HiddenFor(s => s.SelectedOption)
#Html.RadioButtonFor(s => s.SelectedOption, "toQueue", new { id = "rdToQueue", #class = "q-event" })
<label for="rdToQueue">Transfer call to queue</label>
#Html.RadioButtonFor(s => s.SelectedOption, "redirect", new { id = "rdRedirect", #class = "q-event" })
<label for="rdRedirect">Transfer call to destination</label>
#Html.RadioButtonFor(s => s.SelectedOption, "hangup", new { id = "rdHangup", #class = "q-event" })
<label for="rdHangup">Hangup</label>
<button type="submit" class="btn btn-primary btn-sm">Save</button>
}
The Post method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(QEventHandlerVM model, int id)
{
if (!ModelState.IsValid) {... return View(model); }
if (model.SelectedOption == "hangup" || model.SelectedOption == "redirection")
{
model.QEventHandler.QueueId = null;
}
else if (model.SelectedOption == "toQueue")
{
model.QEventHandler.Phrase = string.Empty;
model.QEventHandler.Redirection = string.Empty;
}
else if (model.SelectedOption == "hangup")
{
model.QEventHandler.Redirection = string.Empty;
model.QEventHandler.QueueId = null;
}
try {// Update}
catch (HttpResponseUnsuccessfulException e){...}
}
Now, here the SelectedOption value is the same as it was from the Get method. There's probably something simple I've missed and there's most likely some better way to go about this.
Thanks in advance.
That's because you have a HiddenFor and associated edit fields for your SelectedOption property. Simply remove the HiddenFor and that should work:
#Html.HiddenFor(s => s.SelectedOption)