Reputation: 576
I added a new Controller then I selected the following options:
I got a folder of views which includes by default: Index, Creat, Edit, Detailes, and Delete.
Everything is working fine to here.
My problem that I'm trying to merge the codes of Create view with the codes of Index view(Two views in one).
The Error which i get:
Compiler Error Message: CS1061: 'System.Collections.Generic.IEnumerable' does not contain a definition for 'Title' and no extension method 'Title' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found (are you missing a using directive or an assembly reference?)
Here is my Merged View (Index.cshtml):
@model IEnumerable<ReMvc.Models.Movie>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Movie</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.LabelFor(model => model.ReleaseDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ReleaseDate)
@Html.ValidationMessageFor(model => model.ReleaseDate)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Genre)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Genre)
@Html.ValidationMessageFor(model => model.Genre)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
</tr>
}
</table>
Here is my controller: I renamed 'Create' ActionResult to Index
namespace ReMvc.Controllers
{
public class MoviesController : Controller
{
private MovieDbContext db = new MovieDbContext();
//
// GET: /Movies/
public ActionResult Index()
{
return View(db.Movies.ToList());
}
[HttpPost]
public ActionResult Index(Movie movie)
{
if (ModelState.IsValid)
{
db.Movies.Add(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
}
And here is my Model: using System; using System.Data.Entity;
namespace ReMvc.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
public class MovieDbContext : DbContext
{
public DbSet<Movie> Movies { get; set; }
}
}
I'm beginner with MVC and i stuck here for more than 4 days.. please help.
Upvotes: 1
Views: 3777
Reputation: 8183
Well to start your model
is a type of IEnumerable<ReMvc.Models.Movie>
.
So it's complaining that IEnumerable<T>
does not have a method or property called Title
:
@Html.LabelFor(model => model.Title)
'System.Collections.Generic.IEnumerable' does not contain a definition for 'Title' and no extension method 'Title' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found
If you didn't mean to use an IEnumerable<T>
for the Model so change it to:
@model ReMvc.Models.Movie
If you did mean to use a type of IEnumerable<T>
then you will need to loop over your items to access them:
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
@foreach(var movie in Model)
{
<fieldset>
<legend>Movie</legend>
<div class="editor-label">
@Html.Label(movie.Title)
</div>
<div class="editor-field">
@Html.Editor(movie.Title)
@Html.ValidationMessage(movie.Title)
</div>
}
I would also recommend that you do not have the data access in your presentation layer (your controller). Look at separating out your data access from your UI.
If you want to use a type of IEnumerable<T>
and a type of ReMvc.Models.Movie
in the same view? You will have to do something similar to the following.
You could create a new type and use this:
public class MovieViewModel()
{
public ReMvc.Models.Movie Movie { get; set; }
public IEnumerable<ReMvc.Models.Movie> MovieCollection { get; set; }
}
Then you can pass that into your view
@model MovieViewModel
In your controller you just do this:
public ActionResult Index()
{
var model = new MovieViewModel()
{
MovieCollection = db.Movies.ToList(),
};
return View(model);
}
[HttpPost]
public ActionResult Index(Movie movie)
{
if (ModelState.IsValid)
{
db.Movies.Add(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
var model = new MovieViewModel()
{
Movie = movie,
};
return View(movie);
}
The downside to this is in your view you will now need to check if one is null (Because with your code, one property will always be null either Movie
or MovieCollection
). I would recommend splitting out your views and use a different Action Method name e.g. Details.
Upvotes: 4