Sorry if I am missing something obvious as I am new to ASP.NET MVC.
As shown in the code sample below, I have Kendo Textbox and Multiselect controls inside a partial view. When "change" event of Textbox is fired I am posting the form and trying to Rebind Kendo Multiselect control to Model.
Multiselect control binds to the Model on the intial load but after the ajax call it does not rebind/refresh to reflect the changes in the model.
Can anybody help with where I might be going wrong?
Please see code sample below:
Index.cshtml:
#model MVCTest20.Models.Config
#{
ViewBag.Title = "Home Page";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script type="text/javascript">
jQuery(function ($) {
$('#SalesOrder').on("change", function () {
$.ajax({
url: '/Home/Index',
data: $('#form').serialize(),
type: 'POST'
});
});
});
</script>
<form>
#{Html.RenderPartial("_SOLookup", Model);}
</form>
_SOLookup.cshtml
<p><strong>Sales Order / Project</strong></p>
#(Html.Kendo().TextBox()
.Name("SalesOrder")) <div id="sales-order-arrow" class="help_arrow"></div>
<p><strong>Line Item</strong></p>
#(Html.Kendo().MultiSelect()
.Name("LineItems")
.Placeholder("Select Line(s)")
.HtmlAttributes(new {#class= "cb-create-control" })
.DataTextField("Name")
.DataValueField("Id")
.AutoBind(true)
.BindTo(Model.LineItemCollection))
HomeController:
public class HomeController : Controller
{
private static Config config;
public ActionResult Index()
{
if (config == null)
{
config = new Config();
}
config.LineItemCollection = new LineItem[]
{
new LineItem {Name = "500.1 - FAS8060AE - 001 - R6", Id = "700"}
}.ToList();
return View(config);
}
[HttpPost]
public ActionResult Index(Config data)
{
data.LineItemCollection = new LineItem[]
{
new LineItem {Name = "1.1 - FAS8060AE - 001 - R6", Id = "100"},
new LineItem {Name = "3.1 - FAS8060AE - 001 - R6", Id = "200"},
new LineItem {Name = "6.1 - FAS8060AE - 001 - R6", Id = "300"}
}.ToList();
return View(data);
}
Model:
public class Config
{
public Config()
{
LineItemCollection = new List<LineItem>();
}
private string _salesorder;
public string SalesOrder
{
get
{
return _salesorder;
}
set
{
_salesorder = value;
}
}
public string LineItems { get; set; }
public List<LineItem> LineItemCollection { get; set; }
}
public class LineItem
{
public string Id { get; set; }
public string Name { get; set; }
}
Related
Selected value is not coming when I am trying to check, drop down list is showing all the names, but when I am trying to show the selected value of the dropdownlist in the controller, option is not coming.
Controller:
public ActionResult Index1()
{
Class1 cs1 = new Class1();
return View(cs1);
}
[HttpPost]
public ActionResult Index1(Class1 cs)
{
var selecteditem = cs.psudetail.Find(p => p.Section_PSU == cs.psudetail.ToString());
if (selecteditem != null)
{
}
}
Model class:
namespace WebApplication1.Models
{
public class Class1
{
public List<PSUMaster> psudetail
{
get
{
PSUEntities pe = new PSUEntities();
return pe.PSUMasters.ToList();
}
}
}
}
And the View with Model:
#model WebApplication1.Models.Class1
#{
ViewBag.Title = "Index1";
}
<br />
#Html.DropDownListFor(m => m.psudetail, new SelectList(Model.psudetail, "S_no", "Section_PSU"), "--Select PSU--")
You need to have a property that can "store" the selection you make in the list. Extend the view model (Class1) to include a property SelectedPSU. I guess that S_no in the PSUMaster is the ID, and of type integer. Otherwise adjust the code accordingly!
I have also changed the list to be just a list, and then the controller can worry about populating it. This pattern fits MVC better (keep the model simple).
Updated class:
namespace WebApplication1.Models
{
public class PsuViewModel
{
public int SelectedPSU { get; set; }
public List<PSUMaster> PSU { get; set; }
}
}
Next, the controller has to be updated to pass the list to the view model in the GET Index method:
public ActionResult Index1()
{
var pe = new PSUEntities();
return View(new PsuViewModel {
PSU = pe.PSUMasters.ToList()
});
}
Now we can use the SelectedPSU property in our view:
#model WebApplication1.Models.Class1
#{
ViewBag.Title = "Index1";
}
<br />
#Html.DropDownListFor(m => m.SelectedPSU, new SelectList(Model.PSU, "S_no", "Section_PSU"), "--Select PSU--")
...and we can get the ID in the controller:
[HttpPost]
public ActionResult Index1(PsuViewModel model)
{
var pe = new PSUEntities();
var selectedPsu = pe.PSUMasters.FirstOrDefault(p => p.S_no == model.SelectedPSU);
if (selectedPsu != null) {
// ...
}
}
Here are my model classes:
public class SensorTest
{
public int SerialNo { get; set; }
public string SensorName { get; set; }
public string TestName { get; set; }
public List<string> ImpactSide { get; set; }
}
public class SensorTestsViewModel
{
public List<SensorTest> SensorTestList { get; set; }
}
Controller action methods:
GET:
[HttpGet]
public ActionResult SensorTests()
{
SensorTestsViewModel obj = new SensorTestsViewModel();
obj.SensorTestList = new List<SensorTest>();
SensorTest sensortest;
sensortest = new SensorTest();
sensortest.SerialNo = 1;
sensortest.SensorName = "FLAT 13 KMH";
sensortest.TestName = "";
obj.SensorTestList.Add(sensortest);
sensortest = new SensorTest();
sensortest.SerialNo = 1;
sensortest.SensorName = "CURB IMPACT 40KMH";
sensortest.TestName = "";
obj.SensorTestList.Add(sensortest);
return View(obj);
}
POST:
[HttpPost]
[ActionName("SensorTests")]
public ActionResult SensorTests_Post(SensorTestsViewModel sensortests)
{
//SensorTestsViewModel model = new SensorTestsViewModel();
//UpdateModel(model);
return View(sensortests);
}
View code:
#model Safety.Models.SensorTestsViewModel
#using (Html.BeginForm("SensorTests", "Safety"))
{
var grid = new WebGrid(Model.SensorTestList, canSort: false, canPage: false);
int rowNum = 0;
<div>
#grid.GetHtml(columns:
grid.Columns
(
grid.Column("SerialNo", format: item => rowNum = rowNum + 1),
grid.Column("SensorName"),
grid.Column("TestName", format: (item) => Html.TextBox("TestName[" + (rowNum - 1).ToString() + "].TestName", (object)item.TestName))
), mode: WebGridPagerModes.Numeric)
</div>
<input type="submit" value="Submit" />
}
See the Viewmodel is null during POST. I have tried UpdateModel as well. My requirement is I need to post whole viewmodel data to controller and do the necessary actions from there. Not sure what I am missing? Can someone Please suggest?
First, take a look at this example: post items of webgrid asp.net mvc3
Try making the textbox name like this: "SensorTestList[someIndexHere].SensorName"
I am trying to build a web application having multiple drop downs. I have used enums in my model to populate these drop down and there is a single from submit button in my view. I am trying to figure out how could I get all the selected Index from these drop down with 1 button click.
My Controller looks something like this:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new DropDownModel();
return View(model);
}
[HttpPost]
public ActionResult Index(DropDownModel model)
{
// Get the selected value
int id = model.SelectedId;
return View();
}
public ActionResult About()
{
return View();
}
}
DropDown in my view:
#Html.DropDownListFor(x => x.SelectedId, Enum.GetNames(typeof(BTSWeb.Models.BillTemplate)).Select(e => new SelectListItem { Text = e }),"--BillTemplate--",new { style = "width:108px;font-size:90%;border-radius: 6.5px 6.5px 6.5px 6.5px" })
<span style="margin-left:1px"></span>
#Html.DropDownListFor(x => x.SelectedId, Enum.GetNames(typeof(BTSWeb.Models.ReadType)).Select(e => new SelectListItem { Text = e }),"--Read Type--",new { style = "width:70px;font-size:90%;border-radius: 6.5px 6.5px 6.5px 6.5px" })
<input type="submit" value="Submit" hidden="hidden"/>
and My Model:
namespace BTSWeb.Models
{
public enum States { ANY, FL, TX, GA, NE };
public enum PaymentType { ANY, Email, Paper, No };
public class DropDownModel
{
public int SelectedId { get; set; }
}
}
The problem is you are using DropDownModel as your view model. You will only ever be able to populate on selectedID using this. What you need to do is somehting like
public class ViewModel
{
public int SelectedStateId { get; set; }
public int SelecPaymentTypeId { get; set; }
}
then in your controller you would pass in
var viewModel = new ViewModel()
return View(ViewModel);
and on your view you would have
#Html.DropDownListFor(x => x.SelectedStateId, Enum.GetNames(typeof(BTSWeb.Models.BillTemplate)).Select(e => new SelectListItem { Text = e }),"--BillTemplate--",new { style = "width:108px;font-size:90%;border-radius: 6.5px 6.5px 6.5px 6.5px" })
<span style="margin-left:1px"></span>
#Html.DropDownListFor(x => x.SelecPaymentTypeId , Enum.GetNames(typeof(BTSWeb.Models.ReadType)).Select(e => new SelectListItem { Text = e }),"--Read Type--",new { style = "width:70px;font-size:90%;border-radius: 6.5px 6.5px 6.5px 6.5px" })
and finally on your controller post method you would have
[HttpPost]
public ActionResult Index(ViewModelmodel)
{
// Get the selected value
int id = model.SelectedStateId;
int id2 = model.SelecPaymentTypeId;
return View();
}
Using a few answers here, I ended up using a Tuple<> with two Models for a single View. For simplicity, tuple.Item1 has a number known in the view, and I'm submitting info for tuple.Item2 to its controller. I want to send back the value of tuple.Item1.num in the submitted tuple.Item2, for the specific member tuple.Item2.num.
Currently, I have this for the message submission:
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "createMessage", #action = "/api/Message" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.Hidden("ID", #Model.Item2.ID)
<div class="editor-field">
#Html.TextArea("Text", #Model.Item2.Text)
#Html.ValidationMessageFor(tuple => tuple.Item2.Text)<br />
</div>
<input type="submit" value="Post Discussion" />
}
So, I'd like to have something sending the value of tuple.Item1.num within the Item2 (Message) Model posted to the Controller. How would I do this?
Mind you, I'm verrry new to the MVC and ASP.net frameworks, so I likely have some things mixed up. I understand that this HtmlHelper knows it's working with MessageController due to its #action attribute, but I'm still confused on how it's posting values to it. Any help would be great, thanks!
As per requested, my models:
DrugEntry.cs
namespace Project.Models
{
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using FileHelpers;
[DelimitedRecord(",")]
[Table("DRUGS")]
public class DrugEntry
{
private string ndc;
private string dosage;
private string brand;
private string generic;
private string currentStatus;
public DrugEntry()
{
this.ndc = string.Empty;
this.dosage = string.Empty;
this.brand = string.Empty;
this.generic = string.Empty;
this.currentStatus = "good"; // By default, a drug has no shortages associated with it, and thus is considered 'good'
}
public DrugEntry(string ndc, string dosage, string brand, string generic, string currentStatus)
{
this.ndc = ndc;
this.dosage = dosage;
this.brand = brand;
this.generic = generic;
this.currentStatus = currentStatus;
}
[Key]
[Column("NDC")]
public string NDC
{
get
{
return this.ndc;
}
set
{
this.ndc = value;
}
}
[Column("DOSAGE")]
public string Dosage
{
get
{
return this.dosage;
}
set
{
this.dosage = value;
}
}
[Column("BRAND_NAME")]
public string Brand
{
get
{
return this.brand;
}
set
{
this.brand = value;
}
}
[Column("GENERIC_NAME")]
public string Generic
{
get
{
return this.generic;
}
set
{
this.generic = value;
}
}
[Column("CURRENT_STATUS")]
public string CurrentStatus
{
get
{
return this.currentStatus;
}
set
{
this.currentStatus = value;
}
}
}
}
Message.cs
namespace Project.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
using FileHelpers;
[Table("MESSAGE")]
public class Message
{
private int id;
private int shortageID;
private string ndc;
private string user;
private DateTime date;
private string text;
[Key]
[Column("ID")]
public int ID
{
get
{
return this.id;
}
set
{
this.id = value;
}
}
[Column("SHORTAGE_ID")]
public int ShortageID
{
get
{
return this.shortageID;
}
set
{
this.shortageID = value;
}
}
[Column("NDC")]
public string NDC
{
get
{
return this.ndc;
}
set
{
this.ndc = value;
}
}
[Column("USER")]
public string User
{
get
{
return this.user;
}
set
{
this.user = value;
}
}
[Column("DATE")]
public DateTime Date
{
get
{
return this.date;
}
set
{
this.date = value;
}
}
[Column("TEXT")]
public string Text
{
get
{
return this.text;
}
set
{
this.text = value;
}
}
}
}
Use ViewModels
Instead of using a tuple, I would recommend to use a ViewModel. A ViewModel is just a simple class that you specifically create to meet the requirements of your view.
A ViewModel is an Asp Mvc standard, you don't modify a model just for the view, instead you create ViewModels.
What is ViewModel in MVC?
You would setup your view model like so.
// You typically name your ViewModel to the View
// that it represents.
public class MessageSubmission
{
public Message Message { get; set; }
public DrugEntry DrugEntry { get; set; }
}
ViewModels should be stored in their own folder. Create a folder called ViewModels and store them there. The following is a folder structure of an applicaton created by Microsoft, notice the ViewModels folder?
View
Since you are using weakly-typed html extensions, I would suggest the following.
#model MyMvcApplication1.ViewModels.MessageSubmission
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "createMessage", #action = "/api/Message" }))
{
#Html.ValidationSummary(true)
#Html.Hidden("ID", #Model.Message.ID)
<!-- // You can assign the DrugEntry.NDC, to a Message.NDC like this -->
#Html.Hidden("NDC", #Model.DrugEntry.NDC)
<div class="editor-field">
#Html.TextArea("Text", #Model.Message.Text)
#Html.ValidationMessageFor(model => model.Message.Text)<br />
</div>
<input type="submit" value="Post Discussion" />
}
Controller
Simply setup your controller like you normally would.
[HttpPost]
public ActionResult Message(Message message)
{
// Add your stuff here.
}
The MVC default model binder automatically assigns the values from the view page(ID,NDC,Text) to the waiting model in the controller (Message.ID, Message.NDC, Message.Text)
The binder aligns the fields by comparing the ID of the html controls to the properties of the model.
View | Model Properties
------------------------------
Hidden.ID | Message.ID
Hidden.NDC | Message.NDC
TextArea.Text | Message.Text
You can try this in ajax
#using (Ajax.BeginForm("ActionOfItem2", "ControllerOfItem2", new AjaxOptions { UpdateTargetId = "UpdateDiv"}))
{
#Html.Hidden("ID", #Model.Item2.ID)
<input type="submit" value="Post Discussion" />
}
Controller
public ReturnType ActionOfItem2(string ID)
{
// Use the ID here
}
I have a view which has a partial view in it, which has a text box in it. The main view has a model of type person and the partial view a model of type person.other. When I do a ajax post back the other model is empty, I expected it to pick up the textbox data. This is the code;
Classes
public class Person
{
public string PersonID { get; set; }
public string Name { get; set; }
public Other Other { get; set; }
}
public class Other
{
public string OtherName { get; set; }
}
Controller
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index()
{
Person person = new Person();
person.Other = new Other();
person.Other.OtherName = "avbc";
return View(person);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Test(Other other)
{
if (Request.IsAjaxRequest())
{
return PartialView("Test");
}
return null;
}
View
#model PartialViewTest.Models.Person
<h2>Index</h2>
<div id="mydiv">
#Html.Partial("Test", Model.Other)
</div>
PartialView
#model PartialViewTest.Models.Other
<h1>Test</h1>
#using (Html.BeginForm("Test", "Home", FormMethod.Post, new { id = "testForm" })) {
#Html.TextBoxFor(m => m.OtherName)
<input type="submit"/>
}
Jquery submit
$(document).ready(function () {
$('#testForm').submit(function () {
$.post($(this).attr("action"),
$(this).serialize(),
function (result) {
$('#mydiv').html(result);
});
);
});
Make sure you cancel the default form submission by returning false from the submit callback. Also you seem to be missing a closing }:
$(document).ready(function () {
$('#testForm').submit(function () {
$.post($(this).attr("action"), $(this).serialize(), function (result) {
$('#mydiv').html(result);
});
return false;
});
});
Also you might need to modify your controller action like this because what is actually sent to the server is Other.OtherName=foo:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Test([Bind(Prefix="Other")]Other other)