Using C# with Razor syntax
I cannot figure out what is wrong...
I have a simple HTML form (I'm going to convert it to HTML Helpers soon). I have a form and within the form I have two <select> elements that contain names. For some reason the data is posting, but without any parameters
HTML
<form method="post" action="~/modules/parts/bom_ervd.cshtml">
<div class="row">
<div class="col-md-12 col-xs-12 col-sm-12">
<div class="col-md-3">
<div class="input-group">
<label>Unit Size<span class="req">*</span></label>
<select class="form-control isReq" name="ervd_unitsize" id="sel_ervd_custom_unitsize">
<option value="">--Select--</option>
<option value="101" disabled>Box 1 (1,500 to 3,000CFM)</option>
<option value="102">Box 2 (2,000 to 4,800CFM)</option>
<option value="103">Box 3 (3,500 to 7,500CFM)</option>
<option value="104">Box 4 (5,000 to 10,000CFM)</option>
</select>
</div>
</div>
<div class="col-md-3">
<div class="input-group">
<label>Power<span class="req">*</span></label>
<select class="form-control isReq" name="ervd_power" id="sel_ervd_custom_power">
<option value="">--Select--</option>
<option value="208/3/60" data-val="7" data-typ="0">208/3/60</option>
<option value="230/3/60" data-val="12" data-typ="0">230/3/60</option>
<option value="460/3/60" data-val="20" data-typ="1">460/3/60</option>
<option value="575/3/60" data-val="23" disabled>575/3/60</option>
</select>
</div>
</div>
<div class="col-md-3"></div>
<div class="col-md-3"></div>
</div>
<div id="form_subcomponents">
<div class="col-md-12">
<hr class="hr1" style="margin-top:40px !important;" />
<input class="btn-block btn btn-info" type="submit" id="btn_ervd_custom_submit" value="Submit"/>
</div>
</div><!-- end form sub components-->
</div><!-- end row -->
</form><!-- end form -->
Here's the code for page: bom_ervd.cshtml
#{
if (isPost) {
if (Request.Form["ervd_unitsize"] == null) {
/* this is what I'm seeing */
<p>I'm getting null values</p>
}
else {
<p>The value is: #Request.Form["ervd_unitsize"].ToString()</p>
}
}
else {
<p>No Data posted!</p>
}
}
In this scenario I ensure I select an option that has a value
I have also tried Request["ervd_unitsize"] and still get null values
Why is it Posting but getting null values?
What am I doing wrong?
Related
I have a country field and a state field. I want to show the state field when the user chooses United States. Otherwise, I want it to be hidden.
This is my cshtml page of the form.
<div class="form-group col-sm-4 mt-4">
<label asp-for="Form.Country" class="control-label"></label>
<select asp-for="Form.Country" class="form-control">
<option disabled selected>Choose your Country</option>
<option>Canada</option>
<option>United States</option>
<option>Mexico</option>
</select>
<span asp-validation-for="Form.Country" class="text-danger"></span>
</div>
<div class="form-group col-sm-4 mt-4">
<label asp-for="Form.State" class="control-label"></label>
<select asp-for="Form.State" asp-items="Model.States" class="form-select">
<option disabled selected>Choose your State</option>
</select>
<span asp-validation-for="Form.State" class="text-danger"></span>
</div>
<div class="form-group col-sm-4 mt-4">
<label asp-for="Form.City" class="control-label"></label>
<input asp-for="Form.City" class="form-control" />
<span asp-validation-for="Form.City" class="text-danger"></span>
</div>
I tried searching for a solution, but most involve using JS which I don't know and don't want to use now.
I know razor is server side code, but maybe I can integrate a blazor component or use css to achieve this.
I'm very glad to see you can receive to use javascript to do it, Here is a simple demo with annotations, I hope it can solve your issue.
add a onchange() method on the first dropdown list:
<select asp-for="Form.Country" class="form-control" onchange="Select()">
add an Id for the second dropdown list:
<div class="form-group col-sm-4 mt-4" id="demo">
.........
</div>
Then write a javascript in your view:
#section scripts
{
<script>
function Select(){
//get the element by id
var select = document.getElementById("Form_Country");
//get the option's text
var index = select.selectedIndex;
var text = select.options[index].text;
//if option's text is not United States, hide the second dropdownlist.
if(text!="United States"){
//hiden the dropdownlist
document.getElementById("demo").style.display='none';
}else{
//show the dropdownlist
document.getElementById("demo").style.display='block';
}
}
</script>
}
Demo:
I think this is what you're looking for
#if (Form.Country == "UnitedStates")
{
MARKUP FOR STATE DROPDOWN
}
I am trying to return a meetingSpace object from the last form group in this razor page:
<form method="post">
<input type="hidden" asp-for="Booking.Id" />
<div class="form-group">
<label asp-for="Booking.Name"></label>
<input asp-for="Booking.Name" class="form-control" />
<span class="text-danger" asp-validation-for="Booking.Name"></span>
</div>
<div class="form-group">
<label asp-for="Booking.Start">Start</label>
<input asp-for="Booking.Start" class="form-control" />
<span class="text-danger" asp-validation-for="Booking.Start"></span>
</div>
<div class="form-group">
<label asp-for="Booking.Duration">Duration</label>
<input asp-for="Booking.Duration" class="form-control" />
<span class="text-danger" asp-validation-for="Booking.Duration"></span>
</div>
<div class="form-group">
<label asp-for="Booking.MeetingSpace">Room</label>
<select data-value="true" data-va-required="The meeting space field is required" id="MeetingSpace.Id" name="MeetingSpace.Name">
#foreach (var meetingSpace in Model.meetingSpaces)
{
<option value="meetingSpace">#meetingSpace.Name</option>
}
</select>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
I am unsure how set this select dropdown to return the value to the Booking.MeetingSpace property. I can see the list of meetingSpace objects in the drop down but after selecting an option the meetingSpace field in the created/edited object is not returned as with the other properties in the form. I have also tried the same using the Booking.MeetingSpaceId int as well but it is still not populated after submission of the form.
it could be a binding problem try to change the name attribute value like this:
<select data-value="true" data-va-required="The meeting space field is required" id="Booking.MeetingSpace.Id" name="Booking.MeetingSpace.Name">
#foreach (var meetingSpace in Model.meetingSpaces)
{
<option value="#meetingSpace.Id">#meetingSpace.Name</option>
}
</select>
also option value should start with # to be recognized.
I'm doing a user management page for a personal project and I want to rename every combobox
distinguishing if it is a combo linked to a menu, a tab or a function to make database management easier. Indeed, depending on the permissions, users can do what admins decide what they can do.
This is the code that I've written so far:
<div class="card card-block bg-white">
<label for="permessimenu" class="col-sm-12">Menu</label>
#foreach (var colMenu in ManageMenu.GetAll())
{
<div class="col-sm-12">
<div class="col-sm-1"></div>
<div class="col-sm-4" name="combo_m"><label>#colMenu.Description</label></div>
<div class="col-sm-2"></div>
<div class="col-sm-3">
<select class="form-control" style="overflow:auto;" id="Description">
<option id="tipoUtente" value="0"><Permesso></option>
#foreach (var menu in
Permission.GetAll())
{
<option value="#menu.Id">#menu.Description</option>
}
</select>
</div>
<div class="col-sm-2"></div>
</div>
#foreach (var colTab in GestioneTab.Select(new WhereStatementBuilder() { { GestioneTab.Empty.IdMenu, Operator.Equals, colMenu.Id.Get() } }))
{
<div class="col-sm-12">
<div class="col-sm-2"></div>
<div class="col-sm-4">
<label>#colTab.Description</label>
</div>
<div class="col-sm-1"></div>
<div class="col-sm-3">
<select class="form-control" style="overflow:auto;" id="Description">
<option id="tipoUtente" value="0"><Permesso></option>
#foreach (var tab in
Permission.GetAll())
{
<option value="#tab.Id">#tab.Description</option>
}
</select>
</div>
<div class="col-sm-2"></div>
</div>
#foreach (var colFunzioni in FuncPermission.Select(new WhereStatementBuilder() { { FuncPermission.Empty.IdTab, Operator.Equals, colTab.Id.Get() } }))
{
<div class="col-sm-12">
<div class="col-sm-3"></div>
<div class="col-sm-4">
<label >#colFun.Description</label>
</div>
<div class="col-sm-3">
<select class="form-control" style="overflow:auto;" id="Description">
<option id="userType" value="0"><Permesso></option>
#foreach (var user in
Permission.GetAll())
{
<option value="#user.Id">#user.Description</option>
}
</div>
<div class="col-sm-2"></div>
</div>
}
}
}
What I'd like to do is to have combobox named like this: combo_menu_1, combo_menu_2, combo_tab_1, combo_tab_2, combo_func_1, combo_func_2...
You can use an array in HTML like this
combo_menu[]
combo_tab[]
I am creating a loop of objects/forms that will enable a user to update data for each object in a partial view. The unique data properly displays in the loop of forms but when I try to submit to the action, the model data that passes to the action is blank and doesn't pull the data from the form I'm submitting from.
In debugging, object data is successfully passed to each var item in the loop.
#foreach (var item in ViewData["CtaList"] as
IEnumerable)
Ex. There are 5 individual forms that are created by the loop each with their own Save and Delete button. If I click Save on the 3rd form in the loop, it goes to the action but the MedInfoModel model for that individual object is blank.
View
#{
ViewData["Title"] = "Edit";
ViewData["hidePluginCSS"] = "yes";
#model POR.Common.MedInfoModel;
}
#foreach (var item in ViewData["CtaList"] as IEnumerable<POR.Common.CtaListModel>)
{
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Edit CTA</h3>
</div>
<div id="partialPlaceHolder">
#using (Html.BeginForm("SaveCtaInfo/" + item.CtaId, "Med", FormMethod.Post, new { #Id = item.CtaId, #class = "content-form form-horizontal" }))
{
<div class="panel-body">
<form class="content-form form-horizontal">
<div class="form-group justify-content-end">
<label for="inputEmail" autocomplete="false" class="col-md-9 control-label">Select Type</label>
#Html.DropDownListFor(m => item.CtaType, Model.CTATypeDropdown, new { #class = "form-control"})
</div>
<div class="form-group justify-content-end">
<label for="inputEmail" autocomplete="false" class="col-md-9 control-label">Select Priority</label>
#Html.DropDownListFor(m => item.CtaOrder, Model.CTAOrderDropdown, new { #class = "form-control" })
</div>
<div class="row mt-2">
<div class="col-md-12 r">
<button class="btn btn-raised btn-danger r" name="ctaSave" value="ctaDelete">Delete</button>
<button class="btn btn-raised btn-success r" name="ctaSave" value="ctaSave">Save</button>
</div>
</div>
</form>
</div>
}
</div>
</div>
}
Controller:
[HttpPost]
public ActionResult SaveCtaInfo(MedInfoModel model, int id)
{
string _sSubmit = Request.Form["ctaSave"].ToString();
if (_sSubmit == "ctaSave")
{
// Code for cta save
model.CtaActionType = "UPDATE";
Helper.SQLSPCrudModel(ConnectionString, "storedProcedure", model);
}
else if (_sSubmit == "ctaDelete")
{
// code for cta delete
model.CtaActionType = "DELETE";
Helper.SQLSPCrudModel(ConnectionString, "storedProcedure", model);
}
return RedirectToAction("Edit/" + id);
}
Rendered Form HTML:
<form action="/Med/SaveCtaInfo%2F1000" class="content-form form-horizontal" id="1000" method="post"> <div class="panel-body">
<div class="form-group justify-content-end">
<label for="inputEmail" autocomplete="false" class="col-md-9 control-label">Select Type</label>
<select class="form-control" id="item_0__CtaType" name="item[0].CtaType"><option value="PDF">PDF</option>
<option selected="selected" value="Call">Call</option>
<option value="Menu">Menu</option>
<option value="Video">Video</option>
</select>
</div>
<div class="form-group justify-content-end">
<label for="inputEmail" autocomplete="false" class="col-md-9 control-label">Select Priority</label>
<select class="form-control" data-val="true" data-val-required="The CtaOrder field is required." id="item_0__CtaOrder" name="item[0].CtaOrder"><option value="0">0</option>
<option selected="selected" value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
</select>
</div>
<div class="row mt-2">
<div class="col-md-12 r">
<button class="btn btn-raised btn-danger r" name="ctaSave" value="ctaDelete">Delete</button>
<button class="btn btn-raised btn-success r" name="ctaSave" value="ctaSave">Save<div class="ripple-container"></div></button>
</div>
</div>
</div></form>
EDIT:
I just noticed however that the form data is passing through via chrome dev tools as:
item[0].CtaType: Call
item[0].CtaOrder: 1
item[0].CtaLink:
Where in a succesfull passing of the model in another action is passing through as:
CtaType: Call
CtaOrder: 1
CtaLink:
Does the action need to be set up differently since it is no longer the parent model of the page?
The answer was to simply replace the following in the controller in original code I posted:
public ActionResult SaveCtaInfo(MedInfoModel model, int id)
with
public ActionResult SaveCtaInfo(MedInfoModel item, int id)
Thanks for your help mxmissile. Sorry for wasting your time.
I have a Core 2 MVC web app which I am trying to add some Ajax into.
I have a Create view which loads a standard web form. What makes this a bit different to what I have learned/done so far is that I would like to add some semi-dynamic content to the page.
The ViewModel for the page is a bunch of simple properties, but part of it is also a nested collection.
I am trying to dynamically add values into the nested collection via a modal, and then reload the partial view to reflect what I have added without causing a page reload - I only want to reload the partial view and close the Modal.
I can see the JS is actioning the request and firing the call to the controller and getting a 200 response but it is not closing the modal or reloading the partial view with the data from the Modal.
There is something I am definitely not getting here. Can anyone advise?
ViewModel
public class RaceViewModel
{
public Race RaceData { get; set; }
public ObservableCollection<CurrencyDetails> Currencies { get; set; }
public CurrencyDetails BaseCurrency { get; set; }
public CurrencyDetails RaceCurrency { get; set; }
public ObservableCollection<RaceOptions> RaceOptionData { get; set; }
[DisplayFormat(DataFormatString = "{0:0.00")]
public decimal BaseFee { get; set; }
}
Main view (Irrelevant sections omitted)
#using TechsportiseOnline.Helpers
#model TechsportiseOnline.ViewModels.RaceViewModel
#{
ViewData["Title"] = "Create";
}
<h2>Create a new race</h2>
<div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true" id="optionsmodal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h2 class="modal-title">New Race Option</h2>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label value="Name" class="control-label">Option Name</label>
<br /><small class="text-muted">The name of this Race Option</small>
<input name="Name" placeholder="Your 10k" type="text" class="form-control" aria-label="Name">
#*<span asp-validation-for="RaceData.Name" class="text-danger"></span>*#
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label name="RaceDistance" value="Race Distance" class="control-label">Distance</label>
<br /><small class="text-muted">Choose a race distance, used for Age Grading </small>
<select name="RaceDistance" class="form-control">
<option value="" selected>--select--</option>
<option value="M1">1 mile</option>
<option value="KM5">5 km</option>
<option value="KM6">6 km</option>
<option value="M4">4 miles</option>
<option value="KM8">8 km</option>
<option value="M5">5 miles</option>
<option value="KM10">10 km</option>
<option value="KM12">12 km</option>
<option value="KM15">15 km</option>
<option value="M10">10 miles</option>
<option value="KM20">20 km</option>
<option value="Half">Half Marathon</option>
<option value="KM25">25 km</option>
<option value="KM30">30 km</option>
<option value="Marathon">Marathon</option>
<option value="KM50">50 km</option>
<option value="M50">50 miles</option>
<option value="KM100">100 km</option>
<option value="KM150">150 km</option>
<option value="M100">100 miles</option>
<option value="KM200">200 km</option>
<option value="Other">Other</option>
</select><br />
#*<span asp-validation-for="RaceData.RaceDistance" class="text-danger"></span>*#
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label name="MaxEntries" value="Maximum Entries" class="control-label">Maximum Entries</label>
<br /><small class="text-muted">The maximum capacity of the race</small>
<input name="MaxEntries" class="form-control" />
#*<span asp-validation-for="RaceData.MaxEntries" class="text-danger"></span>*#
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label name="Start Time" value="Start Time" class="control-label">Race Start Time</label>
<br /><small class="text-muted">Start time in HH:MM</small>
<input name="Start Time" value="19:00" asp-format="{0:hh:mm}" class="form-control" type="time" />
#*<span asp-validation-for="RaceData.RaceStartTime" class="text-danger"></span>*#
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label value="Entry Price" class="control-label">Entry Price</label>
<br /><small class="text-muted">The price of the normal race entry</small>
<input name="Entry Price" type="text" class="form-control" aria-label="Amount" placeholder="10.00" asp-format="{0:0.00}">
#*<span asp-validation-for="RaceData.EntryPrice" class="text-danger"></span>*#
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label class="control-label">Affiliation Discount</label>
<br /><small class="text-muted">Value of discount for being an affiliated runner</small>
<input name="AffiliatedDiscountValue" type="text" class="form-control" aria-label="Amount" value="2.00" asp-format="{0:0.00}">
#*<span asp-validation-for="AffiliatedDiscountValue" class="text-danger"></span>*#
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="addoption" >Add</button>
</div>
</div>
</div>
</div>
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="panel panel-default">
<div class="panel-heading">Race Options</div>
<div class="panel-body">
<div id="container">
Create your different Race Options here, if you want to have more than one distance/race in the same event. You must have at least 1 Race Option.
<div id="dvRaceOptionsResults">
#{Html.RenderPartial("RaceOptions", Model);}
</div>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target=".bd-example-modal-lg">Add Race Option</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script type="text/javascript">
$("#addoption").click(function(){
$.ajax({
url: '#Url.Action("GetRaceOptions", "Races")',
type: 'POST',
success: function(data) {
if (data) { // check if data is defined
$("#dvRaceOptionsResults").html(data);
}
}
});
});
</script>
}
Partial View
#model TechsportiseOnline.ViewModels.RaceViewModel
<table>
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
#if (Model.RaceOptionData != null)
{
foreach (var option in Model.RaceOptionData)
{
<tr>
<td>#option.Name</td>
</tr>
}
}
</tbody>
</table>
Controller Method
[HttpPost]
public async Task<IActionResult> GetRaceOptions(RaceViewModel race)
{
var viewModel = race;
return PartialView("RaceOptions", viewModel);
}
This is your VideModel right?
public class RaceViewModel
{
...
}
From what I understand, your AJAX request is getting routed to method GetRaceOptions which receives a RaceViewModel parameter. Unfortunately, your AJAX POST Request is not sending the required RaceViewModel object. You have to pass it in the data body.
Make sure your JS data object has the same property name as the ViewModel so Model Binding will work properly.
Example:
data: {BaseFee: 842350, property2: 'abc'}; //and so on
$.ajax({
url: '#Url.Action("GetRaceOptions", "Races")',
type: 'POST',
data: data,
dataType : 'html', //expect html back
success: function(data) {
if (data) { // check if data is defined
$("#dvRaceOptionsResults").html(data);
}
}
You are calling ajax without data: parameter. So you are not posting data to your controller. Than controller is trying to return the partial view with empty viewModel.
If you want to save newly added options you will need to do something like this.
create data object and send it as data parameter in ajax.
modify the controller to save new options and return old + new options
[HttpPost]
public async Task<IActionResult> GetRaceOptions(RaceViewModel race)
{
//save options from RaceViewModel
//get old options + newly added options
var viewModel = old + newly added data
return PartialView("RaceOptions", viewModel);
}
You need to close modal in the success part of ajax
success: function(data) {
if (data) { // check if data is defined
$("#dvRaceOptionsResults").html(data);
$('#modalId').modal('hide');
}