How to add comment to mvc application - asp.net-mvc

I have a list of comments under my detail page in MVC. I want the user to be able to add comments in the same page and save to the database. How do I pass data to the controller action and save this using dbcontext that holds my comment class.
I have this follow code in my CommentController:
public ActionResult Create(int MovieId)
{
var moviecomment = _db.Moviecomment.Where(r => r.MovieID == MovieId);
return View(moviecomment);
}
[HttpPost]
public ActionResult Create(MovieComment Moviecomment)
{
var MovieComment = _db.Moviecomment.Add(Moviecomment);
_db.SaveChanges();
return RedirectToAction("Details");
}
And has a partial View:
#model MvcMovie.Models.MovieComment
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<div class="addcommentbox">
<h2> Add Comment </h2>
#Html.TextAreaFor(model => model.comment)
<div class="ErrorMessage">
#Html.ValidationMessageFor(model => model.comment)
</div>
<input id="addComment" type="button" onclick="" value="Add" />
</div>
}
and in my Detail page i have this:
#model MvcMovie.Models.Movie
#{
ViewBag.Title = "Details";
}
<h2>Details</h2>
Movie
Title
#Html.DisplayFor(model => model.Title)
Genre
#Html.DisplayFor(model => model.Genre)
PostDate
#Html.DisplayFor(model => model.PostDate)
Staring
#Html.DisplayFor(model => model.Staring)
Description
#Html.DisplayFor(model => model.Description)
Trailer
#Html.DisplayFor(model => model.Trailer)
<fieldset>
#Html.Partial("Comments",Model.MovieComment)
</fieldset>
<p>
</p>
<p>
#Html.ActionLink("Edit", "Edit", new { id=Model.MovieID }) |
#Html.ActionLink("Back to List", "Index")
</p>
#Html.RenderAction("Create","Comment" new { id = Model.MovieID })
i want user to able to add comment when they are in detail page: other thing seem to been fine but this line
#Html.RenderAction("Create","Comment" new { id = Model.MovieID })
give me the following error. cannot implicitly convert type void to object. Please any help will be appreciated.
The model code:
public class Movie
{
public int MovieID { get; set; }
public string Title { get; set; }
public String Genre { get; set; }
public DateTime PostDate { get; set; }
public string Staring { get; set; }
public string Description { get; set; }
public string Picture { get; set; }
public string Trailer { get; set; }
public virtual ICollection< MovieComment> MovieComment { get; set; }
}
For comment
public class MovieComment
{
// public MovieComment()
//{
// Movie = new HashSet<Movie>();
//}
public int MovieCommentID { get; set; }
public string comment_title { get; set; }
public String comment { get; set; }
public int MovieID { get; set; }
// [ForeignKey("ID")]
public virtual Movie Movie { get; set; }
//[ForeignKey("ProfileID")]
public virtual Profile Profile { get; set; }
public String ProfileID { get; set; }
//public string MovieUserID { get; set; }
}

Not sure if this is your only error, but the syntax is wrong for the line that's giving you an error. You are missing a comma. Try:
#Html.RenderAction("Create","Comment", new { id = Model.MovieID })
If this doesn't fix your problem, can you also post the code for your model?

Related

Unable to populate checkbox from database data in mvc 4

This is my Controller code.
public ActionResult Create()
{
ViewBag.grp_id = new SelectList(db.tm_grp_group, "grp_id", "grp_name");
ViewBag.perm_id = new SelectList(db.tm_perm_level, "perm_id", "perm_levelname");
return View();
}
Below is my view code.
#model Permission.ts_grp_perm_mapping
....
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>ts_grp_perm_mapping</legend>
<div class="editor-label">
#Html.LabelFor(model => model.grp_permid)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.grp_permid)
#Html.ValidationMessageFor(model => model.grp_permid)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.grp_id, "tm_grp_group")
</div>
<div class="editor-field">
#Html.DropDownList("grp_id", String.Empty)
#Html.ValidationMessageFor(model => model.grp_id)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.perm_id, "tm_perm_level")
</div>
<div class="editor-field">
#Html.DropDownList("perm_id", String.Empty)
#Html.ValidationMessageFor(model => model.perm_id)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
In controller ViewBag.perm_id contains some values (this is foreign key). In view perm.id displays in the form of dropdownbox but I want it in the form of checkboxlist. How can I achieve this?
This is the viewmodel I created.
public class AssignUserViewModel
{
public tm_perm_level[] perms { get; set; }
public int grp_id { get; set; }
}
Now in controller how can i send values to view? This is my tm_perm_level model
public partial class tm_perm_level
{
public tm_perm_level()
{
this.ts_grp_perm_mapping = new HashSet<ts_grp_perm_mapping>();
}
public int perm_id { get; set; }
public string perm_levelname { get; set; }
public string perm_description { get; set; }
public bool perm_status { get; set; }
public virtual ICollection<ts_grp_perm_mapping> ts_grp_perm_mapping { get; set; }
}
This is ts_grp_perm_mapping model
public partial class ts_grp_perm_mapping
{
public ts_grp_perm_mapping()
{
this.ts_perm_levelmapping = new HashSet<ts_perm_levelmapping>();
}
public int grp_permid { get; set; }
public int grp_id { get; set; }
public int perm_id { get; set; }
public List<tm_perm_level> permissions { get; set; }
public virtual tm_grp_group tm_grp_group { get; set; }
public virtual tm_perm_level tm_perm_level { get; set; }
public virtual ICollection<ts_perm_levelmapping> ts_perm_levelmapping { get; set; }
}
Especially when editing, always start with view models to represent what you want to display (refer What is ViewModel in MVC?)
public class PermissionVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class GroupPermissionVM
{
public int GroupID { get; set; }
public IEnumerable<SelectListItem> GroupList { get; set; }
public IEnumerable<PermissionVM> Permissions { get; set; }
}
Then create an EditorTemplate for PermissionVM. In the /Views/Shared/EditorTemplates/PermissionVM.cshtml folder
#model PermissionVM
<div>
#Html.HiddenFor(m => m.ID)
#Html.HiddenFor(m => m.Name)
#Html.CheckBoxFor(m => m.IsSelected)
#Html.LabelFor(m => m.IsSelected, Model.Name)
</div>
and the main view will be
#model GroupPermissionVM
....
#using (Html.BeginForm())
{
// dropdownlist
#Html.LabelFor(m => m.GroupID)
#Html.DropDownListFor(m => m.GroupID, Model.GroupList, "Please select")
#Html.ValidationMessageFor(m => m.GroupID)
// checkboxlist
#Html.EditorFor(m => m.Permissions)
<input type="submit" value="Create" />
}
The controller methods would then be
public ActionResult Create()
{
var groups = db.tm_grp_group;
var permissions = db.tm_perm_level;
GroupPermissionVM model = new GroupPermissionVM
{
GroupList = new SelectList(groups, "grp_id", "grp_name"),
Permissions = permissions.Select(p => new PermissionVM
{
ID = p.perm_id,
Name = p.perm_levelname
}
};
return View(model);
}
[HttpPost]
public ActionResult Create(GroupPermissionVM model)
{
if (!ModelState.IsValid)
{
var groups = db.tm_grp_group;
model.GroupList = new SelectList(groups, "grp_id", "grp_name");
return View(model);
}
// map the view model to a new instance of your data model(s)
// note: to get the ID's of the selected permissions -
// var selectedPermissions = model.Permissions.Where(p => p.IsSelected).Select(p => p.ID);
// save and redirect
}
Side note: I strongly recommend you follow normal naming conventions
Edit
Based on OP's comment for an option using radio buttons to select only one item, the revised code would be
public class PermissionVM
{
public int ID { get; set; }
public string Name { get; set; }
}
public class GroupPermissionVM
{
public int GroupID { get; set; }
public int PermissionID { get; set; }
public IEnumerable<SelectListItem> GroupList { get; set; }
public IEnumerable<PermissionVM> Permissions { get; set; }
}
and the view would be (no separate EditorTemplate required)
#model GroupPermissionVM
....
#using (Html.BeginForm())
{
// dropdownlist as above
// radio buttons
foreach (var permission in Model.Permissions)
{
<label>
#Html.RadioButtonForm(m => m.PermissionID, permission.ID)
<span>#permission.Name</span>
</label>
}
<input type="submit" value="Create" />
}
and in the POST method, the value of model.PermissionID will contain the ID of the selected Permission.

How do I pass selected items in MVC4 EF5?

I am new to MVC and would appreciate any advice. I have several models/tables that work together. The trouble I am having is with a many-to-many relationship. What I want is to have a listbox that a user can multiselect from and pass those values to save in join table, while saving the primary entry to another table.
My models:
public class Card
{
public virtual int CardID { get; set; }
public virtual string Title { get; set; }
//A bunch of properties...
//Drop Down Lists
public int RarityID { get; set; }
public virtual Rarity Rarity { get; set; }
public int MainTypeID { get; set; }
public virtual MainType MainType { get; set; }
public int CardSetID { get; set; }
public virtual CardSet CardSet { get; set; }
public int SubTypeID { get; set; }
public virtual SubType SubType { get; set; }
public virtual string AdditionalType { get; set; }
public virtual IList<CardAbility> Abilities { get; set; }
public virtual int[] SelectedAbilities { get; set; }
}
public class Ability
{
public virtual int AbilityID { get; set; }
public virtual string Title { get; set; }
public virtual IList<CardAbility> Cards { get; set; }
}
public class CardAbility
{
public int CardAbilityID { get; set; }
public virtual Ability Ability { get; set; }
public int AbilityID { get; set; }
public virtual Card Card { get; set; }
public int CardID { get; set; }
}
My Controller:
public ActionResult Create()
{
ViewBag.RarityID = new SelectList(db.Rarities, "RarityID", "Title");
ViewBag.MainTypeID = new SelectList(db.MainTypes, "MainTypeID", "Title");
ViewBag.CardSetID = new SelectList(db.CardSets, "CardSetID", "Title");
ViewBag.SubTypeID = new SelectList(db.SubTypes, "SubTypeID", "Title");
ViewBag.Abilities = new MultiSelectList(db.Abilities, "AbilityID", "Title");
return View();
}
// POST: /Card/Create
[HttpPost]
public ActionResult Create(Card card)
//[ModelBinder(typeof(CardBinder1))]
{
if (ModelState.IsValid)
{
db.Cards.Add(card);
db.SaveChanges();
foreach (var items in card.SelectedAbilities)
{
var obj = new CardAbility() { AbilityID = items, CardID = card.CardID };
db.CardAbilities.Add(obj);
}
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.RarityID = new SelectList(db.Rarities, "RarityID", "Title", card.RarityID);
ViewBag.MainTypeID = new SelectList(db.MainTypes, "MainTypeID", "Title", card.MainTypeID);
ViewBag.CardSetID = new SelectList(db.CardSets, "CardSetID", "Title", card.CardSetID);
ViewBag.SubTypeID = new SelectList(db.SubTypes, "SubTypeID", "Title", card.SubTypeID);
ViewBag.Abilities = new MultiSelectList(db.Abilities, "AbilityID", "Title");
return View(card);
My Create View:
model MTG.Models.Card
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Card</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.Label("Abilities")
</div>
<div class="editor-field">
#Html.ListBoxFor(model => model.Abilities, (ViewBag.AbilityID as MultiSelectList))
#Html.ValidationMessageFor(model => model.Abilities)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.RarityID, "Rarity")
</div>
<div class="editor-field">
#Html.DropDownList("RarityID", String.Empty)
#Html.ValidationMessageFor(model => model.RarityID)
</div>
// A lot more fields...
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
My DBContext:
public DbSet<Ability> Abilities { get; set; }
public DbSet<Rarity> Rarities { get; set; }
public DbSet<CardSet> CardSets { get; set; }
public DbSet<MainType> MainTypes { get; set; }
public DbSet<SubType> SubTypes { get; set; }
public DbSet<Card> Cards { get; set; }
public DbSet<CardAbility> CardAbilities { get; set; }
public class AbilitiesToCardsConfiguration : EntityTypeConfiguration<CardAbility>
{
internal AbilitiesToCardsConfiguration()
{
this.HasKey(p => new { p.AbilityID, p.CardID });
this.HasRequired(p => p.Ability)
.WithMany(p => p.Cards)
.HasForeignKey(p => p.AbilityID);
this.HasRequired(p => p.Card)
.WithMany(r => r.Abilities)
.HasForeignKey(p => p.CardID);
}
}
I have been working on this for about 3 days and have done a lot of trial and error from what I have read online. At this point, the create view does display a listbox that is pulling the titles from the Abilities table. When I try to save, I get a validation error "The value "1" is invalid.", where 1 is the ID for that ability. When debugging, I see that the modelstate is invalid and the error is
{System.InvalidOperationException: The parameter conversion from type 'System.String' to type 'MTG.Models.CardAbility' failed because no type converter can convert between these types.
at System.Web.Mvc.ValueProviderResult.ConvertSimpleType(CultureInfo culture, Object value, Type destinationType)
at System.Web.Mvc.ValueProviderResult.UnwrapPossibleArrayType(CultureInfo culture, Object value, Type destinationType)
at System.Web.Mvc.ValueProviderResult.ConvertTo(Type type, CultureInfo culture)
at System.Web.Mvc.DefaultModelBinder.ConvertProviderResult(ModelStateDictionary modelState, String modelStateKey, ValueProviderResult valueProviderResult, Type destinationType)}
I know it doesn't like the types and can't convert, but if I try anything else with the listboxfor helper it won't bring in the data and usually crashes before I even get to see the create page. Sorry this is so long, I just wanted to give all the information I could. :) Thank you for any help.
Generate a listbox for SelectedAbilities instead of Abilities:
#Html.ListBoxFor(model => model.SelectedAbilities , (ViewBag.AbilityID as MultiSelectList))
By the way you need to do the same for RarityID instead of Rarity, MainTypeID instead of MainType and etc.

How to bind value from database to Dropdown List in MVC 3

I am trying to bind a dropdown list from database in mvc3.
I have two tables.
tblEmp:
EmpID (pk),
EName,
Age,
Address,
EmailID,
DeptID (fk).
tblDept
DeptID (pk),
DeptName,
DeptHead.
I am trying to bind create an Employee application with the basic details of an employee
Name, Age, Address, EmailID, and Dept Name. I am trying to bind the Dept Name dropdownlist from the other table.
This is my Model:
namespace MvcEmployeeApplication.Models
{
public class UandPcompare
{
public int EmpID { get; set; }
public string EName { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string EmailID { get; set; }
public int DeptID { get; set; }
public string DeptName { get; set; }
public string DeptHead { get; set; }
public IList<SelectListItem> Drp_DeptNames { get; set; }
}
}
This is Controller:
[HttpGet]
public ActionResult Create()
{
FillDeptName();
return View();
}
[HttpPost]
public ActionResult Create(tblEmployee tblEmp)
{
test.Entry(tblEmp).State = System.Data.EntityState.Added;
test.SaveChanges();
return RedirectToAction("Index");
}
public ActionResult FillDeptName()
{
UandPcompare filldeptNme = new UandPcompare();
filldeptNme.Drp_DeptNames = (from DptName in test.tblDepts
select new SelectListItem()
{
Text = DptName.DeptName,
Value = SqlFunctions.StringConvert((double)DptName.DeptID)
}).ToList<SelectListItem>();
return View("Create");
}
This is MyView:
#model MvcEmployeeApplication.Models.UandPcompare
#{
ViewBag.title = "Edit";
}
<h2> Create </h2>
#using (Html.BeginForm())
{
<fieldset>
<legend> Create </legend>
<div>
Employee ID: #Html.DisplayFor(model => model.EmpID)
</div>
<div>
Employee Name: #Html.EditorFor(model => model.EName)
</div>
<div>
Email-ID: #Html.EditorFor(model => model.EmailID)
</div>
<div>
Address: #Html.EditorFor(model => model.Address)
</div>
<div>
Dept Name: #Html.DropDownList("DeptName", Model.Drp_DeptNames, "Select")
</div>
<p>
<input type="submit" value="Create" />
</p>
<div>
#Html.ActionLink("Back to Index", "Index");
</div>
Not able to get what error are you getting.
You are not passing any model to your view.
public ActionResult FillDeptName()
{
UandPcompare filldeptNme = new UandPcompare();
filldeptNme.Drp_DeptNames = (from DptName in test.tblDepts
select new SelectListItem()
{
Text = DptName.DeptName,
Value = SqlFunctions.StringConvert((double)DptName.DeptID)
}).ToList<SelectListItem>();
return View("Create",filldeptNme);//pass model to view here
}

ASP.Net MVC 4 Update value linked to a foreign key column

I'm relatively new to MVC 4 and ASP.net in general. I'm trying to create a "room" with some properties, one of which queries from a list of statuses contained in another model. I have my classes set up as follows:
Room.cs
public class Room
{
[Key]
public Guid RoomId { get; set; }
[Required(ErrorMessage = "A Room Name is required")]
public string Name { get; set; }
public string Description { get; set; }
public virtual Status Status { get; set; }
[DisplayName("Created On")]
public DateTime? Created { get; set; }
[DisplayName("Last Modified")]
public DateTime? Modified { get; set; }
}
Status.cs
public class Status
{
[Key]
public int StatusId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
When I use the default scaffolding for the create action against the room, I am using the following code, which is working flawlessly, and properly applying the status of "New" to the newly created room.
// Post: /Room/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Room room)
{
if (ModelState.IsValid)
{
room.Created = DateTime.Now;
room.Status = db.Statuses.Single(s => s.Name == "New");
room.RoomId = Guid.NewGuid();
db.Rooms.Add(room);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(room);
}
When I attempt the same syntax for assigning room.Status on an edit action, in my case, automatically changing the status from "New" to "Discovery", the status values are never modified in the database. I am tracing the locals right up to the db.SaveChanges(); call, and I can see that the room.Status value is accurately reflecting the definition to the new status, but it's simply not updating on the back end. Here is my update code:
//Room/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Room room)
{
if (ModelState.IsValid)
{
room.Modified = DateTime.Now;
room.Status = db.Statuses.Single(s => s.Name == "Discovery");
db.Entry(room).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(room);
}
I'm at a loss as to how to change this value! My Edit view is as follows:
#model vwr.Cloud.Models.Room
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Room - #Html.ValueFor(model => model.Name)</legend>
#Html.HiddenFor(model => model.RoomId)
#Html.HiddenFor(model => model.Name)
#Html.HiddenFor(model => model.Created)
#Html.HiddenFor(model => model.Status.StatusId)
<div class="editor-label">
Room Status - #Html.ValueFor(model => model.Status.Name)
</div>
<div class="editor-label">
Created Date - #Html.ValueFor(model => model.Created)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
It took me WAY too long to figure this out, but I also needed to add a [ForeignKey] entry to my Room class that mapped to the Navigation Property. I can't say I yet understand HOW it works, suffice to say, it does :-).
Final room.cs
public class Room
{
[Key]
public Guid RoomId { get; set; }
[Required(ErrorMessage = "A Room Name is required")]
public string Name { get; set; }
public string Description { get; set; }
[ForeignKey("Status")]
public virtual int StatusId { get; set; }
public virtual Status Status { get; set; }
[DisplayName("Created On")]
public DateTime? Created { get; set; }
[DisplayName("Last Modified")]
public DateTime? Modified { get; set; }
}
public class Room
{
[Key]
public Guid RoomId { get; set; }
[Required(ErrorMessage = "A Room Name is required")]
public string Name { get; set; }
public string Description { get; set; }
[ForeignKey("Status")]
public virtual int StatusId { get; set; }
public virtual Status Status { get; set; }
[DisplayName("Created On")]
public DateTime? Created { get; set; }
[DisplayName("Last Modified")]
public DateTime? Mod

ASP MVC table foreign key configuration

public class Movies
{
[Key]
public int movieID { get; set; }
public String Title { get; set; }
public virtual Genres parentGenre { get; set; }
}
public class Genres
{
public Genres()
{
this.movies = new HashSet<Movies>();
}
[Key]
public int genreId { get; set; }
public String genreName { get; set; }
public ICollection<Movies> movies { get; set; }
}
I can successfully create a DropDownList on my addmovie view page by reading in the Genres table.
But when I try submit the page, it states "The value '10' is invalid." This leads me to believe that I am trying to put an Int (from the dropdownlist value) into an object (from the "Genres parentGenre").
Have I set up the "Genres parentGenre" to "genreId" foreign key relationship correctly to where it should only want a 'number' for the "parentGenre" field, or does it expect more?
added:
controller:
[HttpPost]
public ActionResult Create(Movies movies)
{
if (ModelState.IsValid)
{
db.Movies.Add(movies);
db.SaveChanges();
return RedirectToAction("Index");
}
IEnumerable<SelectListItem> items = db.Genres
.Select(c => new SelectListItem
{
Value = SqlFunctions.StringConvert((double)c.genreId).Trim(),
Text = c.genreName
});
ViewBag.genreId = items;
}
view:
<div class="editor-label">
#Html.LabelFor(model => model.parentGenre.genreName)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.parentGenre,(IEnumerable<SelectListItem>)ViewBag.genreId)
#Html.ValidationMessageFor(model => model.parentGenre)
In lieu of your comments, here's what I'd recommend:
Models:
public class Movie
{
[Key]
public int MovieID { get; set; }
public String Title { get; set; }
public int GenreId { get; set; }
public virtual Genre Genre { get; set; }
}
public class Genre
{
public Genre()
{
this.movies = new HashSet<Movies>();
}
[Key]
public int GenreId { get; set; }
public String Name { get; set; }
public ICollection<Movies> Movies { get; set; }
}
Controller:
[HttpPost]
public ActionResult Create(Movie Movie)
{
if (ModelState.IsValid)
{
db.Movies.Add(Movie);
db.SaveChanges();
return RedirectToAction("Index");
}
IEnumerable<SelectListItem> items = db.Genres
.Select(c => new SelectListItem
{
Value = SqlFunctions.StringConvert((double)c.GenreId).Trim(),
Text = c.Name
});
ViewBag.genreId = items;
}
View:
<div class="editor-label">
#Html.LabelFor(model => model.Genre.Name)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Genre.Id,(IEnumerable<SelectListItem>)ViewBag.genreId)
#Html.ValidationMessageFor(model => model.Genre)
</div>
If I'm reading what you're doing correctly, that should work. I haven't done much with EF though, so I can't be 100% certain.

Resources