I have a current invoice list model that I want to bind to a select list
public class InvoiceList
{
public string InvoicerReference { get; set; }
public Invoice SelectedInvoice{ get; set; }
public List<Invoice> Invoices { get; set; }
}
And here is the drop down in the view
#using (Html.BeginForm("Invoice", "Billing", FormMethod.Post))
{
#Html.DropDownListFor(m => m.SelectedInvoice, new SelectList(Model.Invoices, "invoiceReference", "InvoiceDisplay"))
<input type="submit" id="btnSelectInvoice" />
}
However when I post to my controller the model is null
public ActionResult Invoice(InvoiceList invoiceReference)
{
....
return View(invoiceList);
}
Can anyone see what I'm doing incorrectly?
Your problem is here:
public Invoice SelectedInvoice{ get; set; }
#Html.DropDownListFor(m => m.SelectedInvoice
The Html.DropDownListFor expects that the first parameter be of the type of the value of the options.
So, if your invoiceReference, is, for example, an int, you would do this:
public class InvoiceList
{
public string InvoicerReference { get; set; }
public int SelectedInvoice{ get; set; }
public List<Invoice> Invoices { get; set; }
}
Related
I have a class for which has a 1 to many relationship with another class. for this I will use class Car and class Gears. I need to create a form, which registers a car and the user needs to specify a choice of gears.
public class Car
{
public int id { get; set; }
public string desc { get; set; }
public List<Gear> Gears { get; set; }
}
public class Gear
{
public int gid { get; set; }
public int gname { get; set; }
}
using asp.net MVC 5, I have a create form, which I have scaffolded to the Car model, and within the form, I wish to have a checkboxlist of gears,
I also have a ViewModel that I have provided for my checkboxlist which is as below:
public class GearsViewModel
{
public Gear _gear {get; set; }
public bool _isChecked {get; set;}
}
Controller looks like:
Gears fetched from db context will be
"GearR","Gear1","Gear2","Gear3","Gear4","Gear5","Gear6","Gear7"
public action Create()
{
ViewBag.Gears = new SelectList(db.Gears, "gid","gname");
List<GearViewModel> _gears= new List<GearViewModel>();
foreach(Gear G in ViewBag.Gears)
{
_gears.Add(new GearViewModel(G, false));
}
ViewBag.GearsCheckList = _gears.ToList();
return View();
}
Now, this is the part I'm getting stuck at, is how to display and capture details in the CreateView.
I need assistance on how to design the Create form and how I will capture the info.
Firstly, view models should not contain data models when editing. You view models should be (add validation and display attributes as appropriate)
public class CarVM
{
public int? ID { get; set; }
public string Description { get; set; }
public List<GearVM> Gears { get; set; }
}
public class GearVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
and the GET method will be
public ActionResult Create()
{
var gears = db.Gears;
CarVM model = new CarVM
{
Gears = gears.Select(x => new GearVM
{
ID = x.gid,
Name = x.gname
}).ToList()
};
return View(model);
}
and the view will then be
#model CarVM
....
#using (Html.BeginForm())
{
..... // elements for editing ID and Description properties of CarVM
#for (int i = ; i < Model.Gears.Count; i++)
{
<div>
#Html.HiddenFor(m => m.Gears[i].ID)
#Html.HiddenFor(m => m.Gears[i].Name) // include if your want to get this in the POST method as well
#Html.CheckboxFor(m => m.Gears[i].IsSelected)
#Html.LabelFor(m => m.Gears.IsSelected, Model.Gears[i].Name)
</div>
}
<input type="submit" .... />
}
Then in the POST method
public ActionResult Create(CarVM model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// To get the ID's of the selected gears
IEnumerable<int> selected = model.Gears.Where(x => x.IsSelected).Select(x => x.ID);
// Initialize your data models, save and redirect
}
Hi everyone so I am trying to create an application using asp.net mvc with a code first database that allows the users to be able to create a blog post with as many images as they wish.I have the data stored in the database but I I am currently trying to have the the head, body and images displaying in the display view this is what I would like it to look like : http://imgur.com/a/IR19r but I am not sure how to accomplish this. I am able to display the head and body but cannot get the images from the image table here is the database diagram: http://imgur.com/a/lvwti
Currently this is the error I get when i add this to the view #Html.DisplayFor(modelItem => item.Images)
An exception of type 'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: An error occurred while executing the command definition. See the inner exception for details.
Model
public partial class PostModel
{
public PostModel()
{
Images = new List<ImageModel>();
}
[Key]
[HiddenInput(DisplayValue = false)]
public int ID { get; set; }
[Required(ErrorMessage = "Heading is Required")]
[Display(Name = "Heading")]
public string Heading { get; set; }
[Required(ErrorMessage = "Body is Required")]
[DataType(DataType.MultilineText)]
[Display(Name = "Body")]
public string Body { get; set; }
public virtual ICollection<ImageModel> Images { get; set; }
public IEnumerable<HttpPostedFileBase> File { get; set; }
}
public class ImageModel
{
[Key]
public int ID { get; set; }
public string Path { get; set; }
public virtual PostModel Post { get; set; }
public string DisplayName { get; set; }
}
public class ImageVM
{
public int? ID { get; set; }
public string Path { get; set; }
public string DisplayName { get; set; }
public bool IsDeleted { get; set; }
}
public partial class PostVM
{
public PostVM()
{
Images = new List<ImageVM>();
}
public int? ID { get; set; }
public string Heading { get; set; }
public string Body { get; set; }
public IEnumerable<HttpPostedFileBase> Files { get; set; }
public List<ImageVM> Images { get; set; }
}
DbContext
public class EFDbContext : DbContext
{
public DbSet<PostModel> Posts { get; set; }
public DbSet<PostVM> PostVMs { get; set; }
public DbSet<ImageModel> Images { get; set; }
public DbSet<ImageVM> ImageVMs { get; set; }
}
Controller
public ViewResult Display()
{
return View(repository.Posts)
}
View
#model IEnumerable<Crud.Models.PostModel>
#{
ViewBag.Title = "Index";
}
#foreach (var item in Model)
{
<div>
#Html.DisplayFor(modelItem => item.Heading)
</div>
<div>
#Html.DisplayFor(modelItem => item.Body)
</div>
<div>
#Html.DisplayFor(modelItem => item.Images)
#*<img class="img-thumbnail" width="150" height="150" src="/Img/#item.Images" />*#
</div>
}
Here is alternative controller I tried but am not using as I got this error when i tried let Images = i.Path and wasn't really sure if this was meant to be how it was done
Cannot implicity convert typeCrud 'string' to 'System.Collections.Generic.List Crud.Models.ImageVm '
public ViewResult Display()
{
IEnumerable<PostVM> model = null;
model = (from p in db.Posts
join i in db.Images on p.ID equals i.Post
select new PostVM
{
ID = p.ID,
Heading = p.Heading,
Body = p.Body,
Images = i.Path
});
return View(model);
}
item.Images is a collection. So loop through that and display the images.
<div>
#foreach(var image in item.Images)
{
<img src="#image.Path" />
}
</div>
You need to make changes to the src property depending on what value you store in the Path property of image.
You can correct your other action method like this
public ViewResult Display()
{
var posts = db.Posts.Select(d => new PostVM()
{
ID = d.ID ,
Heading = d.Heading,
Body = d.Body,
Images = d.Images.Select(i => new ImageVM() { Path = i.Path,
DisplayName = i.DisplayName }
).ToList()
}).ToList();
return View(posts);
}
Now since you are returning a list of PostVM, make sure your Display view is strongly typed to that.
#model List<PostVM>
<h1>Posts</h1>
#foreach(var p in Model)
{
<h3>#p.Heading</h3>
<p>#p.Body</p>
#foreach(var image in item.Images)
{
<img src="#image.Path" />
}
}
Also, there is no point in keeping the view model classes on your db context. Keep only your entity models. View models are only for the use of UI layer.
public class EFDbContext : DbContext
{
public DbSet<PostModel> Posts { get; set; }
public DbSet<ImageModel> Images { get; set; }
}
How can I fetch and insert data at a specific time in one view in mvc razor view? I mean to fill a dropdown list from the database in create view.
I want to fill the following when I add the subject and cheater models.
department list
semester list
standard list
stream list
cheater model:
namespace firstapp.Models
{
public class chepter
{
[ForeignKey("dip_id")]
public int dipart_id { get; set; }
public int chep_id { get; set; }
public string subject { get; set; }
public string chepter { get; set; }
public List<dipartment> dipartlist { get; set; }
public List<dipartment> stdlist { get; set; }
public List<dipartment> semlist { get; set; }
public List<dipartment> stremlist { get; set; }
}
}
department model:
namespace firstapp.Models
{
public class dipartment
{
public int dip_id { get; set; }
public string dipart { get; set; }
public string std { get; set; }
public string sem { get; set; }
public string strem { get; set; }
}
}
#Html.DropDownListFor(model => model.dipart_id, new SelectList(Model.dipartlist.Select(s => new SelectListItem() { Value = s.dip_id, Selected = false, Text = s.dipart })), "Select")
Change your model so the list property is a selectlist:
public SelectList<dipartment> dipartlist { get; set; }
Then, when you populate the model call a service class method(you might not have a service layer, I just prefer to not have database calls in the controller)
dipartlist = _departmentService.GetAsSelectList();
The GetAsSelectList service method looks like this:
public SelectList GetAsSelectList()
{
return (from d in _context.Set<department>().OrderBy(x => x.dipart)
select new
{
Id = d.dipart_id,
Name = d.dipart
}).ToList();
}
And finally your view:
#Html.DropDownListFor(model => model.dipart_id, Model.dipartlist)
This technique means you don't have linq in either the view or controller. Also as you're only creating the selectlist in one place (the service), you can cache it with MemoryCache to prevent multiple requests for the same data. And as it looks like you're populating 4 selectlists, this might be useful.
I feel a bit stupid.
I'm trying to get a hang of MVC 4, using boxing as a functional example.
I have WeightCategories in the database (Heavyweights, etc), and Boxers.
Seem simple. The relation is a boxer has a current weight category, but when I edit, I want it to be able to change it with a drop down.
I understand how to do it if it's a list I've made myself in the code, but I have problem understanding how to "load" the list from the WeightCategory table and show it in the view/model of the boxer.
So, here is my code for the WeightCategory item:
[Table("WeightCategories")]
public class WeightCategory
{
[Key]
public int WeightCategoryId { get; set; }
public WEIGHT_CATEGORIES WeightCategoryType { get; set; }
[Display(Name = "Weight Category Name")]
[Required]
[MinLength(5)]
public string Name { get; set; }
[Display(Name = "Weight Limit In Pounds")]
public int? WeightLimit { get; set; }
}
Here is the code for the boxer item
[Table("Boxers")]
public class Boxer
{
[Key]
public int BoxerId { get; set; }
public WeightCategory CurrentWeightCategory { get; set; }
[Required]
public string Name { get; set; }
public int Wins { get; set; }
public int Losses { get; set; }
public int Draws { get; set; }
public int Kayos { get; set; }
}
In the view, I'm really not sure how to tackle that, I'm pretty sure it's not automatic and I need to load the table somewhere in the controller maybe... I'm looking for best practice or something.
Something like that in the view at the end:
#Html.DropDownListFor(model => model.CurrentWeightCategory.WeightCategoryId,
new SelectList(Model.WeightCategories, "WeightCategoryId", "Name",
Model.WeightCategories.First().WeightCategoryId))
You could design a view model:
public class MyViewModel
{
public Boxer Boxer { get; set; }
public IEnumerable<SelectListItem> WeightCategories { get; set; }
}
and then have your controller action populate and pass this view model to the view:
public ActionResult Edit(int id)
{
var model = new MyViewModel();
using (var db = new SomeDataContext())
{
// Get the boxer you would like to edit from the database
model.Boxer = db.Boxers.Single(x => x.BoxerId == id);
// Here you are selecting all the available weight categroies
// from the database and projecting them to the IEnumerable<SelectListItem>
model.WeightCategories = db.WeightCategories.ToList().Select(x => new SelectListItem
{
Value = x.WeightCategoryId.ToString(),
Text = x.Name
})
}
return View(model);
}
and now your view becomes strongly typed to the view model:
#model MyViewModel
#Html.DropDownListFor(
x => model.Boxer.CurrentWeightCategory.WeightCategoryId,
Model.WeightCategories
)
I apologize in advance for a wall of text below. I hope to provide all the info at once that may be needed to understand what I'm doing.
I've got a page where I'm collecting some basic user info (name, email, etc). In another portion of the page I have a multiple choice quiz form (using radio inputs for each question). My goal is to collect the contact info, process the quiz answers, and store a score with the contact info in a QuizResults table.
This may be a case of over thinking, or over engineering.. so feel free to tell me I'm going about this all wrong.
Here's my Quiz related models:
public class QuizType {
public QuizType() {
this.QuizQuestions = new HashSet<QuizQuestion>();
this.QuizResults = new HashSet<QuizResult>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<QuizQuestion> QuizQuestions { get; set; }
public virtual ICollection<QuizResult> QuizResults { get; set; }
}
public class QuizQuestion {
public QuizQuestion() {
this.QuizAnswers = new HashSet<QuizAnswer>();
}
public int Id { get; set; }
public string Question { get; set; }
public int Order { get; set; }
public int QuizTypeId { get; set; }
public virtual ICollection<QuizAnswer> QuizAnswers { get; set; }
public virtual QuizType QuizType { get; set; }
}
public class QuizResult {
public int Id { get; set; }
public string TesterName { get; set; }
public string TesterEmail { get; set; }
public string TesterCompany { get; set; }
public string TesterPhone { get; set; }
public string ApproverName { get; set; }
public string ApproverEmail { get; set; }
public bool HasCompanyIssuedIdBadge { get; set; }
public int Score { get; set; }
public virtual QuizType QuizType { get; set; }
}
public class QuizAnswer {
public QuizAnswer() {
}
public int Id { get; set; }
public bool isCorrectAnswer { get; set; }
public string Answer { get; set; }
public int QuizQuestionId { get; set; }
public virtual QuizQuestion QuizQuestion { get; set; }
}
So basically I can create a Quiz Type, then for each type I can create multiple questions, each question can have multiple answers. I'm not trying to post back any data for QuizType, QuizQuestion, or QuizAnswer. Those are just there to help build my page[s].
This is where I start scratching my head. I need to be able to iterate through QuizQuestions and QuizAnswers to create the multiple choice form. But I also need to bind part of that form to QuizResults for posting back.... here's what I've got now in order to display the form (but not work correctly).
First, I've created a ViewModel:
public class QuizViewModel {
public IQueryable<QuizQuestion> QuizQuestions { get; set; }
public QuizResult QuizResults { get; set; }
}
Then in my controller:
public ViewResult Index() {
var questions =
from q in unitOfWork.QuizQuestionRepository.Get()
where q.QuizType.Name.Equals("QuizTypeOne")
select q;
var qvm = new QuizViewModel {
QuizQuestions = questions
};
return View(qvm);
}
I won't post my entire razor view, but I think these are the pertinent parts:
#model QuizViewModel
#* *** MISC STYLE, JS, ETC LEFT OUT FOR BREVITY *** *#
#using (Html.BeginForm()) {
#Html.LabelFor(model => model.QuizResults.TesterName)<br />
#Html.EditorFor(model => model.QuizResults.TesterName)
#* *** OTHER FORM FIELDS LEFT OUT FOR BREVITY *** *#
foreach (var item in Model.QuizQuestions) {
<div class="wizard-step">
<h3>#item.Question</h3>
#{
// I've been tinkering with this trying to find a way to get it
// so that the input would have the right id to be picked up and
// dropped into my post object correctly
var inputId = "SelectedAnsers[" + item.Id + "]";
}
#foreach (var answer in item.QuizAnswers) {
<input type="radio" id="#inputId" name="#inputId" value="#answer.Id" /> #answer.Answer #:(#answer.isCorrectAnswer)
<br />
}
</div>
}
}
Back in my controller I have a method setup to handle the post, but it's not doing anything at the moment. I'm just running in debug and looking at the values posted when I submit the form.
[HttpPost]
public ViewResult DukeDrive(QuizViewModel quizViewModel) {
// I have a breakpoint set so that I can inspect quizViewModel
return View();
}
In my head I want to be able to process the quiz form values, calculate the score, then create a new QuizResult object based on the contact info filled out and the newly calc'd score. I'll be darned if I can find the right way to do it though.
Any pointers?
You could add another parameter of type FormCollection which contains all posted values.
[HttpPost]
public ViewResult DukeDrive(QuizViewModel quizViewModel, FormCollection formData) {
// I have a breakpoint set so that I can inspect quizViewModel
return View();
}