I have the following details in my project
MODEL
public class AnimalModels
{
public string AnimalId { get; set; }
public List<SelectListItem> AnimalList { get; set; }
}
VIEW
#model DropDownList.Models.AnimalModels
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<script src="#Url.Content("~/Scripts/Animal/Index.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<div>
<fieldset>
<div>#Html.LabelFor(model => model.AnimalId)</div>
<div>#Html.DropDownListFor(model => model.AnimalId, Model.AnimalList)</div>
<div>#Html.ValidationMessageFor(model => model.AnimalId)</div>
</fieldset>
<input type="submit" name="Submit" value="Submit" />
</div>
}
CONTROLLER
public class AnimalController : Controller
{
//
// GET: /Animal/
public ActionResult Index()
{
AnimalModels model = new AnimalModels();
model.AnimalList = new List<SelectListItem>();
return View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(AnimalModels model)
{
//TODO: get animal list
model.AnimalList = new List<SelectListItem>();
return View(model);
}
}
Index.js
//[B]Document ready
$(document).ready(function () {
//Populate ddl using ajax (jquery)
$.ajax({
url: 'Resources/Animals.xml', // name of file with our data - link has been renamed
dataType: 'xml', // type of file we will be reading
success: parse, // name of function to call when done reading file
error: showError // name of function to call when failed to read
});
});
//[E]Document ready
function parse(xmlDoc) {
var options = new Array();
$(xmlDoc).find("ITEMS").each(function () {
$(this).find("ITEM").each(function () {
var optionValue = $(this).find('VALUE').text();
var optionLabel = $(this).find('TEXT').text();
options.push('<option value="' + optionValue + '">' + optionLabel + '</option>');
});
});
options = options.join('');
$('#AnimalId').append(options);
}
var showError = function (xhr, status, err) {
alert("Error loading file Animals.xml in Resources folder.\n" + xhr.status + " " + err + ".");
};
Animals.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<ITEMS>
<ITEM>
<VALUE>-1</VALUE>
<TEXT></TEXT>
</ITEM>
<ITEM>
<VALUE>0</VALUE>
<TEXT>Tiger</TEXT>
</ITEM>
<ITEM>
<VALUE>1</VALUE>
<TEXT>Lion</TEXT>
</ITEM>
</ITEMS>
my question is there any way to get all drop down list items when i hit submit button?
because the value is always null when i tried to debug it
add into the form -
#for (int i = 0; i < Model.AnimalList.Count; i++)
{
#Html.HiddenFor(model=>model.AnimalList[i].Value)
#Html.HiddenFor(model=>model.AnimalList[i].Text)
}
Code solution suggested by https://stackoverflow.com/users/2984635/user2984635
Model, index.js (unused), Animal.xml (unused) is remaining the same.
View and controller code are updated. bellow are the updates:
VIEW
#model DropDownList.Models.AnimalModels
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#*<script src="#Url.Content("~/Scripts/Animal/Index.js")" type="text/javascript"></script>*#
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<div>
<fieldset>
<div>#Html.LabelFor(model => model.AnimalId)</div>
<div>#Html.DropDownListFor(model => model.AnimalId, Model.AnimalList)</div>
<div>#Html.ValidationMessageFor(model => model.AnimalId)</div>
//[B]the update
#for (int i = 0; i < Model.AnimalList.Count; i++)
{
#Html.HiddenFor(model=>model.AnimalList[i].Value)
#Html.HiddenFor(model=>model.AnimalList[i].Text)
}
//[E]the update
</fieldset>
<input type="submit" name="Submit" value="Submit" />
</div>
}
CONTROLLER
public class AnimalController : Controller
{
//
// GET: /Animal/
public ActionResult Index()
{
AnimalModels model = new AnimalModels();
model = new AnimalModels();
//[B]the update
model.AnimalList = new List<SelectListItem>();
model.AnimalList.Add(new SelectListItem { Value = "0", Text = "Tiger" });
model.AnimalList.Add(new SelectListItem { Value = "1", Text = "Lion" });
//[E]the update
return View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(AnimalModels model)
{
//[B]the update
model.AnimalList[int.Parse(model.AnimalId)].Selected = true;
//[E]the update
return View(model);
}
}
Related
I have dropdownlist and want to pass value in Controller. View
#using (Html.BeginForm())
{
#Html.DropDownList("dropOrg", ViewBag.dropOrg as SelectList)
<input type="submit" value="save" />
}
Controller
foreach (int tmp in org)
{
string s = tmp + " - " + orgNames[tmp];
SelectListItem item1 = new SelectListItem() { Text = s, Value = tmp.ToString() };
items.Add(item1);
}
ViewBag.dropOrg = items;
What should i do?
It will be better if you create ViewModel for your View:
public class SampleViewModel
{
public string DropDownListValue { get; set; }
}
then in your controller's get method:
public ActionResult SomeAction()
{
var org = GetOrg(); //your org
var orgNames = GetOrgNames(); //your orgNames
// . . .
ViewBag.DropDownListValue = new SelectList(org.Select(s =>
new SampleViewModel
{
DropDownListValue = $"{s} - {orgNames[s]}"
}, "DropDownListValue", "DropDownListValue");
return View(new SampleViewModel())
}
your SomeAction View:
#model YourAppNamespace.SampleViewModel
<h1>Hello Stranger</h1>
#using (Html.BeginForm())
{
#Html.DropDownList("DropDownListValue")
<input type="submit" value="Submit"/>
}
Note that:
The DropDownList helper used to create an HTML select list
requires a IEnumerable<SelectListItem>, either explicitly or
implicitly. That is, you can pass the IEnumerable<SelectListItem>
explicitly to the DropDownList helper or you can add the
IEnumerable<SelectListItem> to the ViewBag using the same name for
the SelectListItem as the model property.
We have used here implicit passing, that is we have used same name for SelectListItem and ViewBag (which is DropDownListValue).
Then when you hit Submit, you need HttpPost method for SomeAction:
[HttpPost]
public ActionResult SomeAction(SampleViewModel model)
{
var org = GetOrg(); //your org
var orgNames = GetOrgNames(); //your orgNames
//. . . Validation etc..
ViewBag.DropDownListValue = new SelectList(org.Select(s =>
new SampleViewModel
{
DropDownListValue = $"{s} - {orgNames[s]}"
}, "DropDownListValue", "DropDownListValue", model.DropDownListValue);
var doSomething = model.DropDownListValue; //Your selected value from DropDownList
return View(model)
}
References: DotNetFiddle Example,
Using the DropDownList Helper with ASP.NET MVC
I am having a strange issue when serializing a form to post back to a controller method. Some of the fields being passed are null (in the case of strings or nullable values) or zero (in the case of numeric values). For instance, with this simple configuration:
ViewModel:
public class HomeViewModel
{
public int FakeId { get; set; }
public string StringDataValue { get; set; }
public int IntegerDataValue { get; set; }
public HomeViewModel() { }
public HomeViewModel(int fakeId)
{
FakeId = fakeId;
StringDataValue = "This is some string data";
IntegerDataValue = 42;
}
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
HomeViewModel viewModel = new HomeViewModel(15);
return View(viewModel);
}
[HttpPost]
public JsonResult PostData(HomeViewModel model)
{
return JsonResult
{
Data = new
{
FakeId = model.FakeId,
StringData = model.StringDataValue,
IntegerData = model.IntegerDataValue
}
};
}
}
View:
#model WebApplication1.Models.HomeViewModel
#{
ViewBag.Title = "Home Page";
}
#using(Html.BeginForm())
{
#Html.HiddenFor(m => m.FakeId)
<div>
Fake ID: #Html.DisplayFor(m => m.FakeId)
</div>
<div>
String Data: #Html.TextBoxFor(m => m.StringDataValue)
</div>
<div>
Integer Data: #Html.TextBoxFor(m => m.IntegerDataValue)
</div>
<button id="btnPost">Post</button>
}
#section scripts
{
<script type="text/javascript">
$(function () {
$("#btnPost").on("click", function (e) {
e.preventDefault();
var model = $("form").serialize();
console.log(model);
$.post("PostData", JSON.stringify(model))
.success(function (d) {
console.log(d);
})
.error(function () {
console.log("error");
})
})
})
</script>
}
If I click the Post button I get this output for the two console.log() lines:
console.log(model): FakeId=15&StringDataValue=This+is+some+string+data&IntegerDataValue=42
console.log(d):
Object {FakeId: 0, StringData: "This is some string data", IntegerData: 0}
As you can see only the StringDataValue actually made it to the controller. However, if I add #Html.Hidden("dummy") in the view just above the hidden field for Model.FakeId then I get the following output:
console.log(model):
dummy=&FakeId=15&StringDataValue=This+is+some+string+data&IntegerDataValue=42
console.log(d):
Object {FakeId: 15, StringData: "This is some string data", IntegerData: 0}
That's a little better, but the IntegerDataValue still didn't make it to the controller. However, if I add #Html.Hidden("dummy2") somewhere after where the Model.IntegerDataValue is shown in the view I get the following output:
console.log(model):
dummy=&FakeId=15&StringDataValue=This+is+some+string+data&IntegerDataValue=42&dummy2=
console.log(d):
Object {FakeId: 15, StringData: "This is some string data", IntegerData: 42}
Now all of my view model values are being passed to the controller properly. I just don't understand why I have to put the dummy fields in to make it happen. It took me a long time to figure out why I was getting incomplete data in the controller methods until I realized what was happening.
Is it just me? Can anyone else duplicate this behavior? Am I missing something?
Take out JSON.stringify and try that. So something like
<script type="text/javascript">
$(function () {
$("#btnPost").click(function(e) {
e.preventDefault();
var model = $("form").serialize();
console.log(model);
$.post("Home/PostData", model)
.success(function(d) {
console.log(d);
})
.error(function() {
console.log("error");
});
});
});
</script>
Ok, I am trying to have a listbox in which the user can add a variable amount of values to, and then submit these values in a collection.
Here is my model:
public sealed class TestModel
{
public IList<string> MyStrings { get; set; }
}
Here is my controller:
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult SubmitTest(TestModel testModel)
{
return Index();
}
}
And my view:
#model WebApplication4.Models.TestModel
#{
ViewBag.Title = "Test Page";
}
<br />
#using (Html.BeginForm("SubmitTest", "Test", FormMethod.Post))
{
<input type="text" id="testTestbox" />
<input id="testButton" type="button" value="Add" /><br />
#Html.ListBoxFor(x => x.MyStrings, new List<SelectListItem>(), new { id = "testListbox", style = "width:100px;" })
<input type="submit" value="Submit" />
}
#section Scripts{
<script>
$("#testButton").click(function () {
var value = $("#testTestbox").val();
$('<option value="' + value + '">' + value + '</option>').appendTo("#testListbox");
});
</script>
}
However, the MyStrings property is always blank when I submit. Am I making a mistake somewhere which could be fixed with a small amend, or is what I am trying to do just not possible?
Thanks
Use this..
$("<option value='"+ value + "' selected='selected'>" + value +"</option>").appendTo("#testListbox");
selected='selected' will select the options which entered by user and binds to model property "MyStrings"
After adding values to the listbox, select the values from listbox before submitting it to the controller.
I think you are submitting the form without selecting values from listbox...
I am using the asp.net Razor with C#. I am trying to verify that a value entered is a currency but I can't seem to do it correctly.
This is in my PaymentModel:
[Required]
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:F2}", ApplyFormatInEditMode = true)]
[Display(Name = "Payment Amount:")]
public decimal Amount { get; set; }
This is my Prepayment view:
#model SuburbanCustPortal.Models.PaymentModel.PrePayment
#{
ViewBag.Title = "Make a payment!";
}
<script>
$(function(){
$("#AccountId").change(function(){
var val=$(this).val();
$("#currentBalance").load("#Url.Action("GetMyValue","Payment")", { custid : val });
document.forms[0].Amount.focus();
});
});
</script>
<h2>Make a Payment</h2>
#using (Html.BeginForm("SendPayment", "Payment", FormMethod.Post))
{
#Html.ValidationSummary(true, "Please correct the errors and try again.")
<div>
<fieldset>
<legend>Please enter the amount of the payment below:</legend>
<div class="editor-label">
Please select an account.
</div>
#Html.DropDownListFor(x => x.AccountId, (IEnumerable<SelectListItem>)ViewBag.Accounts)
<div class="editor-label">
#Html.LabelFor(m => m.AccountBalance)
</div>
<div class="editor-field">
<label class="sizedCustomerDataLeftLabel" id="currentBalance">#Html.DisplayFor(model => model.AccountBalance) </label>
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Amount)
</div>
<div class="editor-field focus">
#Html.TextBoxFor(m => m.Amount, new { #class = "makePaymentText" })
#Html.ValidationMessageFor(m => m.Amount)
</div>
<p>
<input id="btn" class="makePaymentInput" type="submit" value="Pay Now" onclick="DisableSubmitButton()"/>
</p>
</fieldset>
</div>
}
This is my Prepayment ActionResult:
[Authorize]
public ActionResult PrePayment(PaymentModel.PrePayment model)
{
var list = new List<SelectListItem>();
var custs = _client.RequestCustomersForAccount(User.Identity.Name);
foreach (var customerData in custs)
{
var acctno = customerData.Branch + customerData.AccountNumber;
var acctnoname = string.Format(" {0} - {1} ", acctno, customerData.Name);
// msg += string.Format("*** {0} - {1} ***{2}", customerData.AccountId, acctnoname, Environment.NewLine);
list.Add(new SelectListItem() { Text = acctnoname, Value = customerData.AccountId });
}
if (custs.Length > 0)
{
model.AccountBalance = String.Format("{0:C}", Decimal.Parse(custs[0].TotalBalance));
}
ViewBag.Accounts = list;
return View(model);
}
The post of the view calls SendPayment and this was my check at the begining of the view:
if (model.Amount == 0)
{
ModelState.AddModelError("Amount", "Invalid amount.");
return RedirectToAction("PrePayment", model);
}
I can't seem to get the PrePayment to get my error back that I sent from AddModelError. I changed it to:
if (model.Amount == 0)
{
ModelState.AddModelError("Amount", "Invalid amount.");
return View("PrePayment", model);
}
But it never calls the controller and the screen errors out since it doesn't have the data it is expecting.
How do I redirect back to the calling view with the errors?
==== ADDITIONAL INFO ====
Here is my PrePayment View:
[Authorize]
public ActionResult PrePayment(PaymentModel.PrePayment model)
{
var list = new List<SelectListItem>();
var custs = _client.RequestCustomersForAccount(User.Identity.Name);
foreach (var customerData in custs)
{
var acctno = customerData.Branch + customerData.AccountNumber;
var acctnoname = string.Format(" {0} - {1} ", acctno, customerData.Name);
// msg += string.Format("*** {0} - {1} ***{2}", customerData.AccountId, acctnoname, Environment.NewLine);
list.Add(new SelectListItem() { Text = acctnoname, Value = customerData.AccountId });
}
if (custs.Length > 0)
{
var amt =String.Format("{0:C}", Decimal.Parse(custs[0].TotalBalance));
model.AccountBalance = amt;
decimal namt;
if (decimal.TryParse(amt.Replace(",",string.Empty).Replace("$", string.Empty), out namt))
{
model.Amount = namt;
}
}
ViewBag.Accounts = list;
return View(model);
}
There are several issues needs to be addressed.
1. return View("PrePayment", model);
This will not call the controller, as the function name suggests, it only passing your object to the specified "View"(.cshtml file)
2. return RedirectToAction("PrePayment", model);
You will not persist modelstate data, because you are doing a redirect.
Suggested workflow which will solve your issue. At least it solved mine.
1. Get the form to post to "PrePayment" instead of SendPayment and you will create a new method with the following signature and have all you validation logic in the method
[Authorize]
[HttpPost]
public ActionResult PrePayment(PaymentModel.PrePayment model)
2. If everything goes well then redirect to the success/send payment page depending on your requirement
3. If somehow you need to pass model object onto the next action. Use TempData like following. This will temporarily persist the data till the next action. Then it get disposed:
TempData["payment"]=model;
May be you should add a data annotation to your property and use ModelState.IsValid property to validate it
[Required]
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:F2}", ApplyFormatInEditMode = true)]
[Display(Name = "Payment Amount:")]
[Range(0.01, Double.MaxValue)]
public decimal Amount { get; set; }
In your POST method, check whether the validation is passed, if not send the model back to the view.
[HttpPost]
public ActionResult SendPayment(PrePayment model)
{
if(ModelState.IsValid)
{
//do the fun stuff
}
return View(model);
}
I am using Razor HtmlHelpers.
using the code below i tried to print the value of ViewItemDto but it always show 0 for using #Html.TextBoxFor or any #Html...For(x=>..) method.
Does anybody have a idea why this is happening?
Note - The method is returning proper value as i can debug and see the value in debug window on views side.
[DataContract]
[Serializable]
public class ViewItemDto
{
[DataMember]
public decimal ViewItemId { get; set; }
[DataMember]
public string ItemName { get; set; }
}
From Controller Return
public ActionResult Index()
{
ViewItemDto viewItem = new ViewItemDto();
viewItem.ItemName = "OldData";
viewItem.ViewItemId = 10;
return View(viewItem);
}
public PartialViewResult SaveData(ViewItemDto viewItem)
{
viewItem.ItemName = "NewData";
viewItem.ViewItemId = 100;
return PartialView("ViewUserControl1", viewItem);
}
On View ViewUserControl1
#model Testing.Models.ViewItemDto
<div id="divSave">
#using (Ajax.BeginForm("SaveData", "Home", new AjaxOptions()
{
UpdateTargetId = "divSave",
OnSuccess = "OnSuccess",
InsertionMode = InsertionMode.Replace
}))
{
#Html.TextBoxFor(x => x.ViewItemId)//Shows 10
#Html.TextBox("ID", Model.ViewItemId) //Shows proper value 100
#Html.TextBoxFor(x => x.ItemName)//Shows oldData value
<input type="submit" name="name" value="Submit" />
}
and Index.cshtml
#model Testing.Models.ViewItemDto
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
#Html.Partial("ViewUserControl1", Model);
Shouldn't you be:
return PartialView(viewItem);
instead of:
return viewItem;
By changing the code of your controller to the following it worked here:
public PartialViewResult SaveData(ViewItemDto viewItem)
{
viewItem.ViewItemId = 100;
return viewItem;
}
I was unabled to reproduce your problem, since the code provided not even compiled.