I have strongly typed view model and in one of class object I am passing list of options that I need to present in #html.Dropdownlist
View Model
public class CreateCampaign_VM
{
public MarketingCampaign MarketingCampaign { get; set; }
public List<MarketingCampaignType> MarketingCampaignType { get; set; }
}
Controller method
private CreateCampaign_VM GetCampaignObject()
{
CreateCampaign_VM _CampaignObject = new CreateCampaign_VM();
_CampaignObject.MarketingCampaignType.Add(new MarketingCampaignType {
CampaignTypeID = 1,
CampaignTypeTitle = "Email",
Description = "Email"
});
_CampaignObject.MarketingCampaignType.Add(new MarketingCampaignType
{
CampaignTypeID = 2,
CampaignTypeTitle = "Text",
Description = "Text"
});
_CampaignObject.MarketingCampaignType.Add(new MarketingCampaignType
{
CampaignTypeID = 3,
CampaignTypeTitle = "Post",
Description = "Post"
});
return _CampaignObject;
}
...
public ActionResult CreateCampaign_Title()
{
return PartialView("CreateCampaign_Title_Partial", GetCampaignObject());
}
Razor view
#model App.Business.Entities.CreateCampaign_VM
#using (Html.BeginForm("CreateCampaign_Title", "Campaign", FormMethod.Post, new { id = "CreateCampaignTitleForm" }))
{
.....
#Html.DropDownListFor(// 'MarketingCampaignType object' need help here
//...
}
Try this:
#Html.DropDownListFor(m => m.MarketingCampaign , new SelectList(Model.MarketingCampaignType, "CampaignTypeTitle", "CampaignTypeId"), new { id = "yourElementIdIfAny", #class = "yourClassNameIfAny" })
Related
It's just a simple application that allows me to add music to a database via a HTML form.
What is happening is when I try to submit the data to be committed into the DB, I get this error:
System.InvalidOperationException: There is no ViewData item of type
'IEnumerable' that has the key 'Genre'.
This error is appearing on the HTML page and from my assumptions, is passing a NULL value instead of the what I have chosen.
Music service class:
public void AddMusic(MusicGenreArtist musicGenreArtist, string userID)
{
Music newMusic = new Music()
{
Title = musicGenreArtist.Title,
num_track = musicGenreArtist.num_track,
duration = musicGenreArtist.duration,
DateReleased = musicGenreArtist.DateReleased,
Price = musicGenreArtist.Price,
Image = musicGenreArtist.Image
};
using (var context = new ForestContext())
{
musicDAO.AddMusic(newMusic, context);
Genre genre = genreDAO.GetGenre(musicGenreArtist.Genre, context);
genreDAO.AddMusicToCollection(newMusic, genre, context);
Artist artist = artistDAO.GetArtist(musicGenreArtist.Artist, context);
artistDAO.AddMusicToCollection(newMusic, artist, context);
userDAO.AddMusicToCollection(newMusic, userID, context);
}
}
Genre DAO:
public Genre GetGenre(Music music, ForestContext context)
{
IList<Genre> genres = GetGenres(context);
for (int i = 0; i < genres.Count; i++)
{
if (genres[i].Musics.Contains<Music>(music))
{
return genres[i];
}
}
return null;
}
DAO for music:
public void AddMusic(Music music, ForestContext context)
{
context.Musics.Add(music);
context.SaveChanges();
}
Music Controller:
public ActionResult AddMusic()
{
Helper helper = new Helper();
ViewBag.genreList = helper.GetGenreDropDown();
ViewBag.artistList = helper.GetArtistDropDown();
return View();
}
// POST: AddMusic/Create
[HttpPost]
public ActionResult AddMusic(MusicGenreArtist musicGenreArtist)
{
try
{
// TODO: Add insert logic here
musicService.AddMusic(musicGenreArtist, "user");
return RedirectToAction("GetGenre", "Genre",
new { id = musicGenreArtist.Genre });
}
catch
{
return View();
}
}
Helper controller for dropdown:
public class Helper
{
private IGenreService genreService;
private IArtistService artistService;
public Helper()
{
genreService = new GenreService();
artistService = new ArtistService();
}
public List<SelectListItem> GetGenreDropDown()
{
List<SelectListItem> genreList = new List<SelectListItem>();
IList<Genre> genres = genreService.GetGenres();
foreach (var item in genres)
{
genreList.Add
(
new SelectListItem()
{
Text = item.Name,
Value = item.ID.ToString(),
Selected = (item.Name == (genres[0].Name) ? true : false)
}
);
}
return genreList;
}
public List<SelectListItem> GetArtistDropDown()
{
List<SelectListItem> artistList = new List<SelectListItem>();
IList<Artist> artists = artistService.GetArtists();
foreach (var item in artists)
{
artistList.Add
(
new SelectListItem()
{
Text = item.Name,
Value = item.ID.ToString(),
Selected = (item.Name == (artists[0].Name) ? true : false)
}
);
}
return artistList;
}
}
}
Genre Model:
public class Genre
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Music> Musics { get; set; }
}
HTML:
<div class="form-group">
#Html.LabelFor(model => model.Genre, htmlAttributes: new { #class = "control-label col-md-2"
})
<div class="col-md-10">
#Html.DropDownListFor(model => model.Genre, (List<SelectListItem>)ViewBag.genreList)
#Html.ValidationMessageFor(model => model.Genre, "", new { #class = "text-danger" })
</div>
</div>
The model you are sending in your view and the one you are waiting for in your controller doesn't match.
Your view use the model Genre
But your controller :
public ActionResult AddMusic(MusicGenreArtist musicGenreArtist)
is waiting for MusicGenreArtist
Please double check this
Controller Code:
AccountsDetailsViewModel vOwnerVM = Mapper.Map<VehicleOwner, AccountsDetailsViewModel>(vOwner);
AccountsDetailsAccountViewModel vOwnerDetailsVM = Mapper.Map<VehicleOwner, AccountsDetailsAccountViewModel>(vOwner);
ViewBag.FleetType = new SelectList(VehicleOwnerFleetTypeFactory.GetTypes().OrderBy(l => l.Type), "Id", "Type");
vOwnerVM.AccountDetails = vOwnerDetailsVM;
Main ViewModel Code:
public class AccountsDetailsViewModel
{
public AccountsDetailsAccountViewModel AccountDetails { get; set; }
}
Main View Code
#model X.Views.Accounts.ViewModels.AccountsDetailsViewModel
#Html.Partial("DetailsAccount", #Model.AccountDetails)
Partial ViewModel Code:
[DisplayName("Fleet Type")]
public int FleetType { get; set; }
Partial View Code
#model X.Views.Accounts.ViewModels.AccountsDetailsAccountViewModel
#Html.DropDownListFor(model => model.FleetType,
(IEnumerable<SelectListItem>)ViewBag.FleetType)
#Html.DisplayFor(model => model.FleetType) (FOR DEBUG)
VehicleOwnerFleetType class
public class VehicleOwnerFleetType
{
public int Id { get; set; }
public string Type { get; set; }
}
public class VehicleOwnerFleetTypeFactory
{
static readonly VehicleOwnerFleetType[] Types = new VehicleOwnerFleetType[] {
new VehicleOwnerFleetType() {Id = 0, Type = "Unknown"},
new VehicleOwnerFleetType() {Id = 1, Type = "HGV"},
new VehicleOwnerFleetType() {Id = 2, Type = "Car"},
new VehicleOwnerFleetType() {Id = 3, Type = "Van"},
new VehicleOwnerFleetType() {Id = 4, Type = "Mixed"}
};
public static VehicleOwnerFleetType[] GetTypes()
{
return Types;
}
public static VehicleOwnerFleetType GetType(int id)
{
return Types.FirstOrDefault(m => m.Id == id);
}
}
Regardless of what the database shows, the dropdown does not display the correct value from the model, only ever the top value in the list.
However if I select a value and then submit the form to save the changes to the database, it does submit the correct value.
When returning the view of the viewmodel in the controller, the values mirror the database exactly, I cannot figure out why it is doing this.
Edit: The 'Sectors' dropdown is the ONLY one that auto-selects the correct value.
The problem is likely caused by the fact that your selectlist, and your VM's member variable have the same names.
model.FleetType
and
(IEnumerable<SelectListItem>)ViewBag.FleetType
Try to rename the select list to FleetTypeList or similar
Works fine for me. Check if you pass the model to the view.
#using WebApplication2.Controllers
#model WebApplication2.Controllers.MyModel
#{
ViewBag.Title = "Home Page";
ViewBag.FleetType = new SelectList(
VehicleOwnerFleetTypeFactory.GetTypes().OrderBy(l => l.Type),
"Id",
"Type");
}
<div>
<h2>---------------------------</h2>
#Html.DropDownListFor(model => model.FleetType,
(SelectList)ViewBag.FleetType)
<h2>---------------------------</h2>
</div>
and
using System.Web.Mvc;
namespace WebApplication2.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyModel { FleetType = 2 });
}
}
public class MyModel
{
public int FleetType { get; set; }
}
public class VehicleOwnerFleetTypeFactory
{
public static FleetType[] GetTypes()
{
return new[]
{
new FleetType {Id = 1, Type = "Type 1"},
new FleetType {Id = 2, Type = "Type 2"},
new FleetType {Id = 3, Type = "Type 3"}
};
}
}
public class FleetType
{
public int Id { get; set; }
public string Type { get; set; }
}
}
HI I am stuck in getting data that i need to display in kendo UI GRID , Initially I am able to see the button and textbox and grid as well but when i enter the value in textbox and then press the button i need to show that entered values in kendo UI GRID ...
When I run this application in google chrome it was giving empty grid,after enters the value and then press the submit button but when I run this one in IE8 it was giving error like this at starting stage itself....
Unhandled exception at line 238, column 37 in Function code
0x800a138f - Microsoft JScript runtime error: 'data.EmployeeDetails.EmployeeId' is null or not an object
and this is my model
public class TextBoxGrid
{
public string EnteredValue { get; set; }
public List<EmployeeDetails> employees;
}
public class ParentViewModel
{
public EmployeeDetails EmployeeDetails { get; set; }
public TextBoxGrid TextBoxGrid { get; set; }
}
public class EmployeeDetails
{
public string EmployeeId { get; set; }
public string ManagerId { get; set; }
}
this is my controller
public class EnterValuesGridController : Controller
{
private static List<EmployeeDetails> empdtls;
public ActionResult Index( ParentViewModel model)
{
var viewmodel = new ParentViewModel
{
TextBoxGrid = new TextBoxGrid { employees = GetEmployee().ToList() }
};
return View(viewmodel);
}
[HttpPost]
public ActionResult PostValues(TextBoxGrid model)
{
TempData["enteringValue"] = model.EnteredValue;
var viewmodel = new ParentViewModel
{
TextBoxGrid = new TextBoxGrid { employees = GetEmployee().ToList() }
};
//ParentViewModel p = new ParentViewModel();
//TextBoxGrid t = new TextBoxGrid();
//t.EnteredValue = "a";
//TempData["a1"] = t.EnteredValue;
//t.employees = GetEmployee().ToList();
//p.TextBoxGrid = t;
//return View("Index", p);
return View("Index", viewmodel);
}
public IEnumerable<EmployeeDetails> GetEmployee()
{
string enteredValueId =(string) TempData["enteringValue"];
string managerId = "M" +enteredValueId;
empdtls = new List<EmployeeDetails>();
EmployeeDetails em1 = new EmployeeDetails();
em1.EmployeeId = enteredValueId;
em1.ManagerId = managerId;
empdtls.Add(em1);
return empdtls.AsEnumerable();
}
public ActionResult Orders_Read([DataSourceRequest]DataSourceRequest request)
{
return Json(GetOrders().ToDataSourceResult(request));
}
private IEnumerable<EmployeeDetails> GetOrders()
{
return GetEmployee().AsEnumerable();
}
}
and this is my view
#model KendoPratapSampleMVCApp.Models.ParentViewModel
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("PostValues", "EnterValuesGrid", FormMethod.Post))
{
#Html.TextBoxFor(m=>m.TextBoxGrid.EnteredValue)
<input type="submit" name="Submitbutton1" value="Submit1" />
#(Html.Kendo().Grid<KendoPratapSampleMVCApp.Models.ParentViewModel>()
.Name("grid")
.Columns(columns => {
columns.Bound(s=>s.EmployeeDetails.EmployeeId).Filterable(false).Width(100);
columns.Bound(s => s.EmployeeDetails.ManagerId).Filterable(false).Width(100);
})
.Filterable()
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Orders_Read", "EnterValuesGrid"))
)
)
}
I am not sure where I am doing wrong, Would you pls suggest any ideas on this one ..
Many thanks...., Do i need to do any changes in UI GRID I have tried changing the post values method ...but it didnot worked for me ...
UPDATE :
changed tempData to view Bag...
[HttpPost]
public ActionResult PostValues(ParentViewModel model)
{
ViewBag.item = model.TextBoxGrid.EnteredValue;
var viewmodel = new ParentViewModel
{
TextBoxGrid = new TextBoxGrid { employees = GetEmployee().ToList() }
};
//ParentViewModel p = new ParentViewModel();
//TextBoxGrid t = new TextBoxGrid();
//t.EnteredValue = "a";
//TempData["a1"] = t.EnteredValue;
//t.employees = GetEmployee().ToList();
//p.TextBoxGrid = t;
//return View("Index", p);
return View("Index", viewmodel);
}
public IEnumerable<EmployeeDetails> GetEmployee()
{
string enteredValueId = (string)ViewBag.item;
string managerId = "M" +enteredValueId;
empdtls = new List<EmployeeDetails>();
EmployeeDetails em1 = new EmployeeDetails();
em1.EmployeeId = enteredValueId;
em1.ManagerId = managerId;
empdtls.Add(em1);
return empdtls;
}
Hi pratap i just update your code,
Model
public class TextBoxGrid
{
public string EnteredValue { get; set; }
public List<EmployeeDetails> employees;
}
public class ParentViewModel
{
public EmployeeDetails EmployeeDetails { get; set; }
public TextBoxGrid TextBoxGrid { get; set; }
}
public class EmployeeDetails
{
public string EnteredValue { get; set; }
public string EmployeeId { get; set; }
public string ManagerId { get; set; }
}
View
#model TwoModelInSinglePageModel.EmployeeDetails
#{
ViewBag.Title = "Index";
}
<script src="~/Script/Jquery-1.8.1.min.js" type="text/javascript"></script>
<script src="~/Script/jquery-ui-1.8.20.min.js" type="text/javascript"></script>
<script src="#Url.Content("~/Script/kendo.all.min.js")" type="text/javascript"></script>
<script src="~/Script/kendo.web.min.js" type="text/javascript"></script>
<script src="~/Script/kendo.aspnetmvc.min.js" type="text/javascript"></script>
#using (Html.BeginForm("PostValues", "Test", FormMethod.Post))
{
#Html.TextBoxFor(m => m.EnteredValue)
<input type="submit" name="Submitbutton1" value="Submit1" />
#(Html.Kendo().Grid<TwoModelInSinglePageModel.EmployeeDetails>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(s => s.EmployeeId);
columns.Bound(s => s.ManagerId);
})
.Filterable()
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Orders_Read", "Test"))
)
)
}
Controller
private static List<EmployeeDetails> empdtls;
public ActionResult PostValues()
{
return View();
}
[HttpPost]
public ActionResult PostValues(EmployeeDetails model)
{
ViewBag.item = model.EnteredValue;
ParentViewModel viewmodels = new ParentViewModel
{
TextBoxGrid = new TextBoxGrid { employees = GetEmployee().ToList() }
};
ParentViewModel viewmodel = new ParentViewModel();
EmployeeDetails em1 = new EmployeeDetails();
for (int i = 0; i < viewmodels.TextBoxGrid.employees.Count(); i++)
{
em1.EmployeeId = viewmodels.TextBoxGrid.employees[i].EmployeeId;
em1.ManagerId = viewmodels.TextBoxGrid.employees[i].ManagerId;
viewmodel.EmployeeDetails = em1;
}
Session["EM1"] = em1;
return View("PostValues", em1);
}
public List<EmployeeDetails> GetEmployee()
{
string enteredValueId = (string)ViewBag.item;
string managerId = "M" + enteredValueId;
empdtls = new List<EmployeeDetails>();
EmployeeDetails em1 = new EmployeeDetails();
em1.EmployeeId = enteredValueId;
em1.ManagerId = managerId;
if (Session["EM1"] != null)
{
em1 = Session["EM1"] as EmployeeDetails;
empdtls.Add(em1);
Session["EM1"] = null;
}
else
{
empdtls.Add(em1);
}
return empdtls;
}
public ActionResult Orders_Read([DataSourceRequest]DataSourceRequest request, EmployeeDetails model)
{
return Json(GetEmployee().ToDataSourceResult(request));
}
OK, I read through your post again and you want to submit the form when click on the button actually. So, let's try to put the value in the session
Session["enteringValue"] = model.EnteredValue;
And you can retrieve it using
string enteredValueId = (string)(Session["enteringValue"]);
I have the following code:
public class OrganisationController : Controller
{
//
// GET: /Organisation/
public ActionResult Update()
{
var fisherman = new RoleType {Id = 1, Name = "Fisherman"};
var manager = new RoleType {Id = 2, Name = "Manager"};
var deckhand = new RoleType {Id = 3, Name = "Deckhand"};
var roleTypes = new List<RoleType>
{
fisherman, manager, deckhand
};
ViewBag.Roles = new SelectList(roleTypes, "Id", "Name");
return View(
new Organisation
{
Name = "Fish Co.",
People = new List<Person>
{
new Person
{
Name = "Squid",
RoleType = fisherman
},
new Person
{
Name = "Michael",
RoleType = manager
},
new Person
{
Name = "John",
RoleType = deckhand
}
}
});
}
[HttpPost]
public ActionResult Update(Organisation org)
{
return View();
}
}
public class Organisation
{
public string Name { get; set; }
public IList<Person> People { get; set; }
}
public class Person
{
public string Name { get; set; }
public RoleType RoleType { get; set; }
}
public class RoleType
{
public int Id { get; set; }
public string Name { get; set; }
}
In Update.cshtml
#model Models.Organisation
<form action="" method="post" enctype="multipart/form-data">
#Html.EditorFor(x => x.Name)
#Html.EditorFor(x => x.People)
<input type="submit"/>
</form>
In the EditorTemplates Person.cshtml:
#model Models.Person
#Html.EditorFor(x => x.Name)
#if(Model != null)
{
#Html.DropDownListFor( x => x.RoleType.Id, (SelectList)ViewBag.Roles)
}
I was expecting to be able to get to a page where I can update the organisation name, the people names and their roles. The trouble is that I can't get the selected item to be set for the dropdowns. I thought x => x.RoleType.Id would do this for me.
Does anyone know how I can get this to work?
Try this constructor: SelectList Constructor (IEnumerable, String, String, Object)
public SelectList(
IEnumerable items,
string dataValueField,
string dataTextField,
Object selectedValue
)
Something like this:
#Html.DropDownListFor( x => x.RoleType.Id, new SelectList((List<RoleType>)ViewBag.Roles, "Id", "Name", Model.RoleType.Id))
Having a hard time getting this dropDownList to Bind. This is simply a list of states. The Model.State is "TX", but my dropdownlist is showing "AK", which is the first value in the list. Any thoughts?
<%: Html.DropDownListFor(
model => model.State,
new SelectList(
muniSynd.getStatecodesDropDown(),
"Value",
"Text",
Model.State.ToString().Trim()
)
)
%>
In my muniSynd class, which is a wrapper of my dataContext.....
public IList<StateCodeViewModel> getStatecodesDropDown()
{
var states = from p in this._MuniDc.Statecodes
select new StateCodeViewModel
{
Value = p.Statecode1.ToString().Trim(),
Text = p.Statecode1.ToString().Trim()
};
return states.ToList();
}
public class StateCodeViewModel
{
public string Value{get;set;}
public string Text{get;set;}
}
Im using LinqToSQL, here is the object
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Statecodes")]
public partial class Statecode
{
private string _Statecode1;
public Statecode()
{
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="Statecode", Storage="_Statecode1", DbType="NVarChar(3)")]
public string Statecode1
{
get
{
return this._Statecode1;
}
set
{
if ((this._Statecode1 != value))
{
this._Statecode1 = value;
}
}
}
}
I've tried to replicate your problem, but my example below works fine:
public class HomeController : Controller
{
public ActionResult Index()
{
var viewModel = new IndexViewModel();
viewModel.State = "TX";
return this.View(viewModel);
}
public static IList<StateCodeViewModel> getStatecodesDropDown()
{
var stateCodes = new List<string> { "AX", "GH", "TX" };
var states = from p in stateCodes
select new StateCodeViewModel
{
Value = p,
Text = p
};
return states.ToList();
}
}
public class IndexViewModel
{
public string State { get; set; }
}
public class StateCodeViewModel
{
public string Value { get; set; }
public string Text { get; set; }
}
View
#using MVCWorkbench.Controllers
#model IndexViewModel
#{
ViewBag.Title = "title";
}
#Html.DropDownListFor(model => model.State,
new SelectList(HomeController.getStatecodesDropDown(),
"Value",
"Text",
Model.State.ToString().Trim()
)
)
Not sure what to suggest other then check that the State value is in the dropdown list. Also this could be a case-sensitivity issue perhaps?