entity framework couldn't deletet edit and details - c#

I build alittke website using c# razor.
I have a model class named "clientModel".
I used crud operation using entity framework.
at first, evrything worked fine .
But when I changed the primary key of the clientModel class from "tracingNumber" to "emailAdress" I can't delete and edit the db from the website.
when I try to do this I get HTTP Error 404.0 - Not Found.
any idea??
controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using VicoProject___NewVersion.Models;
namespace Project___NewVersion.Controllers
{
public class ClientController : Controller
{
private ClientModelsDBContext db = new ClientModelsDBContext();
//
// GET: /Model/
public ActionResult Index()
{
return View(db.Clients.ToList());
}
//
// GET: /Model/Details/5
public ActionResult Details(int id = 0)
{
ClientModels clientmodels = db.Clients.Find(id);
if (clientmodels == null)
{
return HttpNotFound();
}
return View(clientmodels);
}
//
// GET: /Model/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Model/Create
[HttpPost]
public ActionResult Create(ClientModels clientmodels)
{
if (ModelState.IsValid)
{
db.Clients.Add(clientmodels);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
return View(clientmodels);
}
//
// GET: /Model/Edit/5
public ActionResult Edit(int id = 0)
{
ClientModels clientmodels = db.Clients.Find(id);
if (clientmodels == null)
{
return HttpNotFound();
}
return View(clientmodels);
}
//
// POST: /Model/Edit/5
[HttpPost]
public ActionResult Edit(ClientModels clientmodels)
{
if (ModelState.IsValid)
{
db.Entry(clientmodels).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(clientmodels);
}
//
// GET: /Model/Delete/5
public ActionResult Delete(int id = 0)
{
ClientModels clientmodels = db.Clients.Find(id);
if (clientmodels == null)
{
return HttpNotFound();
}
return View(clientmodels);
}
//
// POST: /Model/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
ClientModels clientmodels = db.Clients.Find(id);
db.Clients.Remove(clientmodels);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
public ActionResult Search(string search)
{
var r = db.Clients.Where(t => t.emailAdress.Contains(search) || t.name.Contains(search)).ToList();
Console.Write(r);
return RedirectToAction("Search");
}
}
}
client model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
namespace Project___NewVersion.Models
{
public class ClientModels
{
[Required]
public string name { get; set;}
[Required]
[MaxLength(10, ErrorMessage = "Phone Number must be 10 numbers") , MinLength(10, ErrorMessage = "Phone Number must be 10 numbers")]
[DataType(DataType.PhoneNumber, ErrorMessage = "Invalid Phone Number")]
public String phoneNumber { get; set; }
[Key]
[Required]
[DataType(DataType.EmailAddress, ErrorMessage = "Invalid Email Address")]
public string emailAdress { get; set; }
}
public class ClientModelsDBContext : DbContext
{
static ClientModelsDBContext()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<ClientModelsDBContext>());
}
public DbSet<ClientModels> Clients { get; set; }
}
}
the client/index view:
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.name)
</th>
<th>
#Html.DisplayNameFor(model => model.phoneNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.emailAdress)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.phoneNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.emailAdress)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.emailAdress }) |
#Html.ActionLink("Details", "Details", new { id=item.emailAdress }) |
#Html.ActionLink("Delete", "Delete", new { id=item.emailAdress})
</td>
</tr>
}
</table>

The function with the signature
public ActionResult Delete(int id = 0)
needs to be called. The parameter to this is an int. I assume since changing it the id is now a string - so the framework doesn't know which method to call.

Related

ASP.NET MVC Problem accessing data from third table

I have a problem to show data from table "Building_Address" in view of "Lease_Status" - it shows no records - only column names as on the pic
The diagram of tables and relations is:
the code of cshtml:
#model IEnumerable<test_ent_frame.Models.Lease_Status>
#{
ViewBag.Title = "Index"; }
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create") </p> <table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Room_Details.number)
</th>
<th>
#Html.DisplayNameFor(model => model.Building_Address.City)
</th>
<th></th>
</tr>
#foreach (var item in Model) { <tr>
<td>
#Html.DisplayFor(modelItem => item.Room_Details.number)
</td>
<td>
#Html.DisplayFor(modelItem => item.Building_Address.City)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id_Lease }) |
#Html.ActionLink("Details", "Details", new { id = item.Id_Lease }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id_Lease })
</td> </tr> }
</table>
The code of controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using test_ent_frame.Models;
namespace test_ent_frame.Controllers
{
public class Lease_StatusController : Controller
{
private testEntities db = new testEntities();
// GET: Lease_Status
public ActionResult Index()
{
var lease_Status = db.Lease_Status.Include(l => l.Room_Details);
return View(lease_Status.ToList());
}
// GET: Lease_Status/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Lease_Status lease_Status = db.Lease_Status.Find(id);
if (lease_Status == null)
{
return HttpNotFound();
}
return View(lease_Status);
}
// GET: Lease_Status/Create
public ActionResult Create()
{
ViewBag.Id_Room = new SelectList(db.Room_Details, "Id_Room", "Id_Room");
return View();
}
// POST: Lease_Status/Create
// Aby zapewnić ochronę przed atakami polegającymi na przesyłaniu dodatkowych danych, włącz określone właściwości, z którymi chcesz utworzyć powiązania.
// Aby uzyskać więcej szczegółów, zobacz https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id_Lease,Id_Room")] Lease_Status lease_Status)
{
if (ModelState.IsValid)
{
db.Lease_Status.Add(lease_Status);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.Id_Room = new SelectList(db.Room_Details, "Id_Room", "Id_Room", lease_Status.Id_Room);
return View(lease_Status);
}
// GET: Lease_Status/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Lease_Status lease_Status = db.Lease_Status.Find(id);
if (lease_Status == null)
{
return HttpNotFound();
}
ViewBag.Id_Room = new SelectList(db.Room_Details, "Id_Room", "Id_Room", lease_Status.Id_Room);
return View(lease_Status);
}
// POST: Lease_Status/Edit/5
// Aby zapewnić ochronę przed atakami polegającymi na przesyłaniu dodatkowych danych, włącz określone właściwości, z którymi chcesz utworzyć powiązania.
// Aby uzyskać więcej szczegółów, zobacz https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id_Lease,Id_Room")] Lease_Status lease_Status)
{
if (ModelState.IsValid)
{
db.Entry(lease_Status).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.Id_Room = new SelectList(db.Room_Details, "Id_Room", "Id_Room", lease_Status.Id_Room);
return View(lease_Status);
}
// GET: Lease_Status/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Lease_Status lease_Status = db.Lease_Status.Find(id);
if (lease_Status == null)
{
return HttpNotFound();
}
return View(lease_Status);
}
// POST: Lease_Status/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Lease_Status lease_Status = db.Lease_Status.Find(id);
db.Lease_Status.Remove(lease_Status);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
These are standard scaffolded files in visual studio
How to make it possible to show these records?
Debug:

Creating a form on ASP.NET using two seperate models

I am using Visual Studio 2017 with everything up to the most recent updates.
I'm trying to enter in a form with some normal text box answer questions as well as a checkbox answer question, and have all answers be recorded in the same database. Part of my issue is how do I get two separate models asking separate questions using separate databases as references for those questions into one single controller and a view with a list of all of the question answers in one database record? Perhaps I am going about this the wrong way, as I am new to ASP.NET this is highly likely. Any input to this issue would be greatly appreciated…
Below is the code for my two models:
Model I:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace TessituraForm
{
public class TessituraFormContext : DbContext
{
public TessituraFormContext(DbContextOptions<TessituraFormContext> options) : base(options)
{
}
public DbSet<Models.Roles> Roles { get; set; }
}
}
Model II:
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;
namespace TessituraForm.Models
{
public class Applicant
{
public int ID { get; set; }
[Display(Name = "Full Name:")]
[DataType(DataType.Text)]
[Required]
public string FullName { get; set; }
[Display(Name = "SI User Name:")]
[StringLength(10)]
[DataType(DataType.Text)]
[Required]
public string SIUserName { get; set; }
[Display(Name = "Supervisor:")]
[Required]
public string Supervisor { get; set; }
[Display(Name = "Badge Number:")]
[StringLength(8)]
[DataType(DataType.Text)]
[Required]
public string BadgeNumber { get; set; }
[Display(Name = "Badge Expiration Date:")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
[Required]
public DateTime BadgeExpirationDate { get; set; }
[Display(Name = "Applicant is a(n):")]
[DataType(DataType.Text)]
[Required]
public string ApplicantIsAn { get; set; }
}
public class Roles
{
[Key]
public int ID { get; set; }
public string AdvancementFundraising { get; set; }
public string CustomerService { get; set; }
public string DiscoveryTheater { get; set; }
public string BusinessOffice { get; set; }
public string CustomerServiceSupport { get; set; }
public string ExecutiveStaff { get; set; }
public string Marketing { get; set; }
public string Programming { get; set; }
public string VolunteerCoordinator { get; set; }
public bool CheckboxAnswer { get; set; }
}
}
Controller Code:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;
using TessituraForm.Models;
namespace Applicant.Controllers
{
public class ApplicantController : Controller
{
private readonly TessituraFormContext _context;
public ApplicantController(TessituraFormContext context)
{
_context = context;
}
// GET: Applicants
public async Task<IActionResult> Index()
{
return View(await _context.Applicant.ToListAsync());
}
// GET: Applicants/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var applicant = await _context.Applicant
.SingleOrDefaultAsync(m => m.ID == id);
if (applicant == null)
{
return NotFound();
}
return View(applicant);
}
// GET: Applicants/Create
public IActionResult Create()
{
return View();
}
// POST: Applicants/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,FullName,SIUserName,Supervisor,BadgeNumber,BadgeExpirationDate,ApplicantIsAn,Roles")] Applicant applicant)
{
if (ModelState.IsValid)
{
_context.Add(applicant);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(applicant);
}
// GET: Applicants/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var applicant = await _context.Applicant.SingleOrDefaultAsync(m => m.ID == id);
if (applicant == null)
{
return NotFound();
}
return View(applicant);
}
// POST: Applicants/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,FullName,SIUserName,Supervisor,BadgeNumber,BadgeExpirationDate,ApplicantIsAn,Roles")] Applicant applicant)
{
if (id != applicant.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(applicant);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ApplicantExists(applicant.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(applicant);
}
// GET: Applicants/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var applicant = await _context.Applicant
.SingleOrDefaultAsync(m => m.ID == id);
if (applicant == null)
{
return NotFound();
}
return View(applicant);
}
// POST: Applicants/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var applicant = await _context.Applicant.SingleOrDefaultAsync(m => m.ID == id);
_context.Applicant.Remove(applicant);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
private bool ApplicantExists(int id)
{
return _context.Applicant.Any(e => e.ID == id);
}
}
}
namespace DatabaseContext.Controllers
{
public class DatabaseContextController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Roles()
{
Applicant objApplicant = newApplicant();
}
}
}
And View Index Code:
#model IEnumerable<TessituraForm.Models.Applicant>
#{
ViewData["Title"] = "Index";
}
<style>
body {
background-color: lightgray;
}
h2 {
color: black;
margin-left: 5px;
}
</style>
<img src="~/Images/TSA.jpg" alt="TSA" style="position:absolute;left:1372px;top:57px;width:150px;height:75px;" />
<h2>Index</h2>
<p>
<a asp-action="Create" style="margin-left:20px;">Create New</a>
</p>
<table class="table" border="1">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.FullName)
</th>
<th>
#Html.DisplayNameFor(model => model.SIUserName)
</th>
<th>
#Html.DisplayNameFor(model => model.Supervisor)
</th>
<th>
#Html.DisplayNameFor(model => model.BadgeNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.BadgeExpirationDate)
</th>
<th>
#Html.DisplayNameFor(model => model.ApplicantIsAn)
</th>
<th>
#Html.DisplayNameFor(model => model.Roles)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FullName)
</td>
<td>
#Html.DisplayFor(modelItem => item.SIUserName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Supervisor)
</td>
<td>
#Html.DisplayFor(modelItem => item.BadgeNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.BadgeExpirationDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.ApplicantIsAn)
</td>
<td>
#Html.DisplayFor(modelItem => item.Roles)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="#item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="#item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Again, my goal is simply to have a form on the web page that has a section with normal text box answers and a checkbox section as well. Any help is much appreciated.
What you can do is to create a new Model and then place the other two in that one like below:
public class YourNewModel
{
public Applicant Applicant {get;set;} //note you can declare it here as a List or any how you want
public Roles Roles {get;set;}
}
Note
This is just to give you an idea and start you have of, it will also mean changing the methods in your Controller suit the approach.
You will also have to pass this Model to your view, this way you can have both models at the same place like you wanted.
I hope this helps

Get and average from user input to a database?

I am totally new to programming so my question maybe confusing but I will try to explain as best as I can.
So I build a app that take in ratings between 1-5. The result is stored in the data base. But I do not understand how to put some logic in my model class where it can retrieve that number and out output the number the users input and the overall average of the rating it was given.
This is my Model class:
public class MovieReview : IValidatableObject
{
public int Id { get; set; }
[Range(1,10)]
[Required]
public double Rating { get; set; }
[Required]
[StringLength(1024)]
public string Comment { get; set; }
[Display(Name="User Name")]
[DisplayFormat(NullDisplayText="anonymous")]
//[MaxWord(5)]
public string ReviewerName { get; set; }
public int MovieId { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if(Rating < 2 && ReviewerName.ToLower().StartsWith("keith"))
{
yield return new ValidationResult("Scorry, Keith uou can't do this");
}
//throw new NotImplementedException();
}
}
public partial class MovieReview : IValidatableObject
{
public ICollection<AverageRating>
public int Id { get; set; }
public int AverageRating { get _AverageRating(c => c.AverageRating; set; }
}
}
This is my controller:
namespace YayOrNay.Controllers
{
public class ReviewsController : Controller
{
YayOrNayDb _db = new YayOrNayDb();
// GET: Reviews
public ActionResult Index([Bind(Prefix = "id")]int movieId)
{
var movie = _db.Movies.Find(movieId);
if(movie !=null)
{
return View(movie);
}
return HttpNotFound();
}
[HttpGet]
public ActionResult Create (int movieId)
{
return View();
}
[HttpPost]
public ActionResult Create(MovieReview review)
{
if(ModelState.IsValid)
{
_db.Reviews.Add(review);
_db.SaveChanges();
return RedirectToAction("Index", new { id = review.MovieId });
}
return View(review);
}
[HttpGet]
public ActionResult Edit (int id)
{
var model = _db.Reviews.Find(id);
return View(model);
}
//[Bind(Exclude = "ReviewerName")]
[HttpPost]
public ActionResult Edit (MovieReview review)
{
if (ModelState.IsValid)
{
_db.Entry(review).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index", new { id = review.MovieId });
}
return View(review);
}
protected override void Dispose(bool disposing)
{
_db.Dispose();
base.Dispose(disposing);
}
}
}
And this is my view:
#model IEnumerable<YayOrNay.Models.MovieReview>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Rating)
</th>
<th>
#Html.DisplayNameFor(model => model.Comment)
</th>
<th>
#Html.DisplayNameFor(model => model.ReviewerName)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
#Html.DisplayFor(modelItem => item.Comment)
</td>
<td>
#Html.DisplayFor(modelItem => item.ReviewerName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
</td>
</tr>
}
</table>
I hope this is enough information for you to understand what I am trying to do.

ASP.Net MVC 3, Using ViewModel, error that ViewModel is not IEnumerable

OK, after searching and searching here, Google and other programming sites, it's time for me to ask my first question.
I have a view, Index.cshtml, that I need two Models in, so I created a ViewModel, ImageViewModel.cs, the two children models, ImageModel.cs and ProductModel.cs and have a controller, ImageController.cs.
For the life of me I cannot get the IEnumerable to work, I should be getting a set of data, one may have one item (product) and the other will have many (images). The images are tied to the productID.
After playing with it, I am now to a point where in the view, #Html.DisplayFor(modelItem => item.imageTitle) throws an error that imageTitle does not exist.
If I revert any of the numerous IEnumerable items scattered throughout, I continue to the get ImageViewModel being passed in is not IEnumerable and the view expects it to be.
For what it is, here is the complete code listings:
Index.cshtml
#model IEnumerable<JustAdminIt.Areas.JBI.ViewModels.ImageViewModel>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Image Title
</th>
<th>
Image Excerpt
</th>
<th>
Image Description
</th>
<th>
Image
</th>
<th>
Product ID
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Image.imageTitle)
</td>
<td>
#Html.DisplayFor(modelItem => item.Image.imageExcerpt)
</td>
<td>
#Html.DisplayFor(modelItem => item.Image.imageDescription)
</td>
<td>
<img src="#Url.Content("~/Content/images/product/")#Html.DisplayFor(modelItem => item.Image.imageURL)" alt="Product Image" width="150" />
</td>
<td>
#Html.DisplayFor(modelItem => item.Product.productID)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Image.imageID }) |
#Html.ActionLink("Details", "Details", new { id = item.Image.imageID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Image.imageID })
</td>
</tr>
}
</table>
ProductModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Web.Mvc;
namespace JustAdminIt.Areas.JBI.Models
{
public class Product
{
[Key]
public int productID { get; set; }
[Required]
[DisplayName("Product Name")]
public string productName { get; set; }
[Required]
[AllowHtml]
[DisplayName("Product Excerpt")]
public string productExcerpt { get; set; }
[Required]
[AllowHtml]
[DisplayName("Product Description")]
public string productDescription { get; set; }
[DisplayName("Mark As Active")]
public bool productActive { get; set; }
[DisplayName("Product Add Date")]
public DateTime? productAddDate { get; set; }
[DisplayName("Product Inactive Date")]
public DateTime? productInactiveDate { get; set; }
}
}
ImageModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Web.Mvc;
namespace JustAdminIt.Areas.JBI.Models
{
public class Image
{
[Key]
public int imageID { get; set; }
[Required]
public string imageTitle { get; set; }
[AllowHtml]
public string imageExcerpt { get; set; }
[AllowHtml]
public string imageDescription { get; set; }
[AllowHtml]
public string imageURL { get; set; }
[Required]
public int productID { get; set; }
}
}
ImageController.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JustAdminIt.Areas.JBI.Models;
using JustAdminIt.Areas.JBI.ViewModels;
using JustAdminIt.Areas.JBI.DAL;
using System.IO;
namespace JustAdminIt.Areas.JBI.Controllers
{
public class ImageController : Controller
{
private ImageContext db = new ImageContext();
private ProductContext pb = new ProductContext();
//
// GET: /JBI/Image/
public ViewResult Index()
{
//attempt new things
int id = 1;
IEnumerable<Image> image = db.Image.TakeWhile(x => x.productID == id);
IEnumerable<Product> product = pb.Product.TakeWhile(x => x.productID == id);
ImageViewModel piViewModel = new ImageViewModel(image, product);
return View(piViewModel);
//return View(db.Image.ToList());
}
//
// GET: /JBI/Image/Details/5
public ViewResult Details(int id)
{
Image image = db.Image.Find(id);
return View(image);
}
//
// GET: /JBI/Image/Create
public ActionResult Create()
{
return View();
}
//
// POST: /JBI/Image/Create
//this simply populates the DB values, but does not handle the file upload
[HttpPost]
public ActionResult Create(Image image)
{
if (ModelState.IsValid)
{
db.Image.Add(image);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(image);
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase Filedata)
{
// Verify that the user selected a file
if (Filedata != null && Filedata.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(Filedata.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/Content/images/product/"), fileName);
Filedata.SaveAs(path);
}
// redirect back to the index action to show the form once again
return RedirectToAction("Index");
}
//
// GET: /JBI/Image/Edit/5
public ActionResult Edit(int id)
{
Image image = db.Image.Find(id);
return View(image);
}
//
// POST: /JBI/Image/Edit/5
[HttpPost]
public ActionResult Edit(Image image)
{
if (ModelState.IsValid)
{
db.Entry(image).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(image);
}
//
// GET: /JBI/Image/Delete/5
public ActionResult Delete(int id)
{
Image image = db.Image.Find(id);
return View(image);
}
//
// POST: /JBI/Image/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Image image = db.Image.Find(id);
db.Image.Remove(image);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
ImageViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Web.Mvc;
using JustAdminIt.Areas.JBI.Models;
namespace JustAdminIt.Areas.JBI.ViewModels
{
public class ImageViewModel
{
public IEnumerable<ImageViewModel> Image { get; set; }
public IEnumerable<ImageViewModel> Product { get; set; }
public ImageViewModel(IEnumerable<Image> image, IEnumerable<Product> product)
{
IEnumerable<Image> Image = image;
IEnumerable<Product> Product = product;
}
}
}
In your Index action method, you create a single new ImageViewModel() and then pass it to your view, but your view expects an IEnumerable<ImageViewModel>.
What you are doing is creating a single ImageViewModel, then passing the two collections to it. This is like using a single box to hold two groups of items, rather than having a bunch of boxes that each hold 1 of two different items.
You need to redesign your app to generate items in the proper way. I'm not sure why you have two different data contexts here, but that's going to complicate things a great deal.
So after reading numerous resource, with code "snippets" out of context, with the help of #Mystere Man & #Travis J I have the solution.
First off, I was creating a new DbContext for every model. I know, dumb. So those are all wrapped in their own context file, and my web.config is much happier.
Sample DbContext showing multiple sources in one context:
public class MyDataContext : DbContext
{
public DbSet<Bundle> Bundle { get; set; }
public DbSet<Image> Image { get; set; }
public DbSet<Product> Product { get; set; }
public DbSet<Siteconfig> Siteconfig { get; set; }
}
The updated files (only posting files that changed, if it is not listed here, it's the same as in the original question):
ImageViewModel.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Web.Mvc;
using JustAdminIt.Areas.JBI.Models;
namespace JustAdminIt.Areas.JBI.ViewModels
{
public class ImageViewModel
{
public Image Image { get; set; }
public Product Product { get; set; }
}
}
ImageController.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JustAdminIt.Areas.JBI.Models;
using JustAdminIt.Areas.JBI.ViewModels;
using JustAdminIt.Areas.JBI.DAL;
using System.IO;
namespace JustAdminIt.Areas.JBI.Controllers
{
public class ImageController : Controller
{
//private ImageContext db = new ImageContext();
//private ProductContext pb = new ProductContext();
private JustBundleItContext db = new JustBundleItContext();
//
// GET: /JBI/Image/
public ViewResult Index()
{
var model = from a in db.Product
join b in db.Image
on a.productID equals b.productID
select new ImageViewModel
{
Product = a,
Image = b
};
return View(model.ToList());
}
//
// GET: /JBI/Image/Details/5
public ViewResult Details(int id)
{
Image image = db.Image.Find(id);
return View(image);
}
//
// GET: /JBI/Image/Create
public ActionResult Create()
{
return View();
}
//
// POST: /JBI/Image/Create
//this simply populates the DB values, but does not handle the file upload
[HttpPost]
public ActionResult Create(Image image)
{
if (ModelState.IsValid)
{
db.Image.Add(image);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(image);
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase Filedata)
{
// Verify that the user selected a file
if (Filedata != null && Filedata.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(Filedata.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/Content/images/product/"), fileName);
Filedata.SaveAs(path);
}
// redirect back to the index action to show the form once again
return RedirectToAction("Index");
}
//
// GET: /JBI/Image/Edit/5
public ActionResult Edit(int id)
{
Image image = db.Image.Find(id);
return View(image);
}
//
// POST: /JBI/Image/Edit/5
[HttpPost]
public ActionResult Edit(Image image)
{
if (ModelState.IsValid)
{
db.Entry(image).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(image);
}
//
// GET: /JBI/Image/Delete/5
public ActionResult Delete(int id)
{
Image image = db.Image.Find(id);
return View(image);
}
//
// POST: /JBI/Image/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Image image = db.Image.Find(id);
db.Image.Remove(image);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
Index.cshtml
#model List<JustAdminIt.Areas.JBI.ViewModels.ImageViewModel>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Image Title
</th>
<th>
Image Excerpt
</th>
<th>
Image Description
</th>
<th>
Image
</th>
<th>
Product ID
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Image.imageTitle)
</td>
<td>
#Html.DisplayFor(modelItem => item.Image.imageExcerpt)
</td>
<td>
#Html.DisplayFor(modelItem => item.Image.imageDescription)
</td>
<td>
<img src="#Url.Content("~/Content/images/product/")#Html.DisplayFor(modelItem => item.Image.imageURL)" alt="Product Image" width="150" />
</td>
<td>
#Html.DisplayFor(modelItem => item.Product.productName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Image.imageID }) |
#Html.ActionLink("Details", "Details", new { id = item.Image.imageID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Image.imageID })
</td>
</tr>
}
</table>
Using the LINQ query in the controller allowed me to the desired join to find what product an image was associated with, while simplifying the ViewModel drastically. Now in the view I can choose from the item.Image group or the item.Products group knowing they are joined properly.
The issue could be due to your use of TakeWhile.
"Returns elements from a sequence as long as a specified condition is true, and then skips the remaining elements." -http://msdn.microsoft.com/en-us/library/system.linq.enumerable.takewhile.aspx
You may want to use Where there ( https://stackoverflow.com/a/5031771/1026459 )
db.Image.Where(x => x.productID == id).ToList();
pb.Product.Where(x => x.productID == id).ToList();
That is only part of it. You are passing in a class which contains these two IEnumerable sets. However, your view is accepting an IEnumerable of that class. You are properly passing in, but not properly receiving.
#model JustAdminIt.Areas.JBI.ViewModels.ImageViewModel
However there is another problem here. Because your products and images are not related when passed you cannot use a foreach on both at the same time
#foreach (var item in Model) {
could be
#foreach (var item in Model.Product) {
but for the reason just listed this will not mean that there are as many images. In order to make this relation, you will need to slightly refactor. It is up to you in how to accomplish that. Basically you will need to create a virtual relationship in your model, or use a class which wraps both.

Foreign Key Just showing a number which is associated with the primary key

I want a way in which I can display the value of the Foreign key rather then displaying a number. For example I have the following view to show all reviews:
#model IEnumerable<Games.Models.tblReview>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
ReviewID
</th>
<th>
Recomendation
</th>
<th>
AvoidOrBuy
</th>
<th>
Score
</th>
<th>
GameIDFK
</th>
<th>
UserName
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ReviewID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Recomendation)
</td>
<td>
#Html.DisplayFor(modelItem => item.AvoidOrBuy)
</td>
<td>
#Html.DisplayFor(modelItem => item.Score)
</td>
<td>
#Html.DisplayFor(modelItem => item.GameIDFK)
</td>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { id=item.ReviewID }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
I want a way in which the GameIDFK shows the name of the game rather then a number my controller to show this information is basic will show you here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Games.Models;
namespace Games.Controllers
{
public class ShowAllReviewsController : Controller
{
//
// GET: /ShowAllReviews/
public ActionResult Index()
{
using (var db = new gamezoneDBEntities())
{
return View(db.tblReviews.ToList());
}
}
//
// GET: /ShowAllReviews/Details/5
public ActionResult Details(int id)
{
return View();
}
//
// GET: /ShowAllReviews/Create
public ActionResult Create()
{
return View();
}
//
// POST: /ShowAllReviews/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /ShowAllReviews/Edit/5
public ActionResult Edit(int id)
{
return View();
}
//
// POST: /ShowAllReviews/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /ShowAllReviews/Delete/5
public ActionResult Delete(int id)
{
return View();
}
//
// POST: /ShowAllReviews/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
Is there a way in which i can obtain the game Foreign Key as this site is going to be used for new coming gamers and I want tos how which games are good play dont want a user clicking on a review and seeing just a number and no game name.
Can you please help
EDIT:
I used the following in my view:
#Html.DisplayFor(modelItem => item.tblGame.GameName)
But it crashses and gives the following error:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
EDIT 2:
namespace Games.Models
{
using System;
using System.Collections.Generic;
public partial class tblReview
{
public int ReviewID { get; set; }
public string Recomendation { get; set; }
public string AvoidOrBuy { get; set; }
public string Score { get; set; }
public int GameIDFK { get; set; }
public string UserName { get; set; }
public virtual tblGame tblGame { get; set; }
}
You might want to consider using ViewModel classes, but I think if you amend your controller to use something like
return View(db.tblReviews.Include("tblGame").ToList());
You would be able to use the property in your view as you have posted above.

Categories