This is probably very simple for most MVC programmers, so maybe you can help me out. I have a table called Images in the database with nine columns. On my UPDATE, I just have three I want to mess with (ImageName, ImagePath, CourseID). After I post back with UPDATE, it sets the other six columns to NULL. I'm not sure how to handle this in MVC.:
My ViewModel:
public class GalleryViewModel
{
public Image _image { get; set; }
}
My Model:
public partial class Image
{
public int ImageID { get; set; }
public string ImageName { get; set; }
public string ImagePath { get; set; }
public Nullable<int> CourseID { get; set; }
public string UserId { get; set; }
public Nullable<System.DateTime> CreateDate { get; set; }
public string ImageType { get; set; }
public string ImageSize { get; set; }
public string FriendlyName { get; set; }
public virtual Cours Cours { get; set; }
}
My Controller:
[HttpGet]
public ActionResult UploadImageEdit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var model = new GalleryViewModel
{
_image = db.Images.Find(id),
};
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UploadImageEdit(GalleryViewModel galleryViewModel)
{
if (ModelState.IsValid)
{
db.Entry(galleryViewModel._image).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("UploadImageIndex");
}
return View(galleryViewModel);
}
After reading other examples and becoming more familiar with ViewModel to controller, I got the UPDATE to work by doing the following:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UploadImageEdit(int id, GalleryViewModel galleryViewModel)
{
if (ModelState.IsValid)
{
var imageContext = db.Images.Find(id);
imageContext.FriendlyName = galleryViewModel._image.FriendlyName;
db.Entry(imageContext).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("UploadImageIndex");
}
return View(galleryViewModel);
}
I hope this helps other folks out!
Related
I am trying to create a view to display product information and its related images. I am using repository pattern,
please see the code below, I will really appreciate your help
public class ProductDetail
{
public int pro_id { get; set; }
public string pro_name { get; set; }
public string pro_model { get; set; }
public string pro_Dimensions { get; set; }
public string pro_imageTitle { get; set; }
public string pro_image { get; set; }
public string pro_desc { get; set; }
public Nullable<double> pro_price { get; set; }
public int pro_UnitsInStock { get; set; }
public Nullable<double> pro_oldprice { get; set; }
public virtual ICollection<Images> tbl_Images { get; set; }
}
public class Images
{
public int ImageID { get; set; }
public int productID { get; set; }
public string ImageTitle { get; set; }
public string ImagePath { get; set; }
}
public class ProductDetailRepository : IProductDetail
{
private readonly WebStoreEntities storeDB;
public ProductDetailRepository() { }
public ProductDetailRepository(WebStoreEntities _storeDB)
{
this.storeDB = _storeDB;
}
public ProductDetail GetProductByID(int id)
{
var prod = storeDB.tbl_Product
.Where(x => x.pro_id == id)
.Include(p => p.tbl_Images)
.FirstOrDefault();
return prod; (Here it says, cannot implicitly convert type tbl_product to productdetail (this is where i need help))
}
tbl_product is from the EDMX model.
}
now, i am stcuk in this method, all i want is to return the product info and related images to the controller and then view.
You basically just need to convert your tbl_Product that you get from the database into the ProductDetail you want to return:
public ProductDetail GetProductByID(int id)
{
var prod = storeDB.tbl_Product
.Where(x => x.pro_id == id)
.Include(p => p.tbl_Images)
.FirstOrDefault();
if (prod == null)
{
return null;
}
ProductDetail result = new ProductDetail
{
// I'm just *GUESSING* here since you haven't showed
// the tbl_product class, so I don't know what the
// properties on that class are called, really...
pro_id = prod.Id,
pro_name = prod.Name
// and so on for all the properties
}
return result;
}
I am trying to make a sample application using code first approach in MVC so I don't have any database. Now I have setup all class files and context class. In next step I have created a controller(Emplty) and want to create own Create/List/Delete functionalities. How can I do it.
Some of the codes are below
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public int DepartmentID { get; set; }//Foreign Key
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
public class Department
{
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
public class EmployeeDBContext: DbContext
{
public EmployeeDBContext()
: base("EmployeeDBContext")//EmployeeDBContext will be name of database.
{ }
public virtual DbSet<Employee> Employees { get; set; }
public virtual DbSet<Department> Departments { get; set; }
public virtual DbSet<Enrollment> Enrollments { get; set; }
}
public class EmployeeInitializer:DropCreateDatabaseIfModelChanges<EmployeeDBContext>
{
protected override void Seed(EmployeeDBContext context)
{
var employee = new List<Employee>
{
new Employee{EmployeeID=1, Name="Aman", Age=15, DepartmentID=11},
new Employee {EmployeeID=2, Name="Supriya", Age=12, DepartmentID=22},
new Employee {EmployeeID=3, Name="Rishabh", Age=10, DepartmentID=44}
};
employee.ForEach(x => context.Employees.Add(x));
context.SaveChanges();
var department = new List<Department> {
new Department{DepartmentID=11, DepartmentName="IT"},
new Department{DepartmentID=22, DepartmentName="HR"},
new Department{DepartmentID=33, DepartmentName="Mechanical"},
new Department{DepartmentID=44, DepartmentName="NGO"}
};
department.ForEach(x=>context.Departments.Add(x));
context.SaveChanges();
var enrollment = new List<Enrollment>() {
new Enrollment{EnrollmentID=111, EmployeeID=1, DepartmentID=11},
new Enrollment{EnrollmentID=222, EmployeeID=3, DepartmentID=44},
new Enrollment{EnrollmentID=333, EmployeeID=2, DepartmentID=22}
};
enrollment.ForEach(x=>context.Enrollments.Add(x));
context.SaveChanges();
}
}
I wish to add code from below controller onward
public ActionResult CreateEmployee(Employee employee)
{
//my desired code here
return View();
}
[HttpGet]
public ActionResult ListEmployee()
{
//my desired code here
return View();
}
you mean how to do something like:
[HttpGet]
public ActionResult ListEmployee()
{
//my desired code here
using(var context=new EmployeeDBContext())
{
return View(context. Employee.ToList());
}
}
[HttpPost]
[Route("api/Employee/CreateEmployee")]
public ActionResult CreateEmployee([FromBody]Employee employee)
{
//add to ef
_db.Add(employee);
_db.SaveChanges();
//my desired code here
return Ok();
}
Here I have a MainController in which I have two actions named Create and PhotoUpload. Here is the code for Create action.
// GET: Main/Create
public ActionResult Create()
{
return View();
}
// POST: Main/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 ActionResult Create([Bind(Include = "Email,Password,FirstName,LastName,Gender,Birthday,ProfileImage,AboutUser")] User user)
{
if (ModelState.IsValid)
{
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
Here is the code for PhotoUpload action.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PhotoUpload(PhotoModel model)
{
if (model.PhotoFile.ContentLength > 0)
{
var fileName = Path.GetFileName(model.PhotoFile.FileName);
var filePath = Server.MapPath("/Content/Users/Images");
string savedFileName = Path.Combine(filePath, fileName);
model.PhotoFile.SaveAs(savedFileName);
}
return View(model);
}
public ActionResult PhotoUpload()
{
return View();
}
And these are the User and Photo models. This is the User Model
public partial class User
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public User()
{
this.Friends = new HashSet<Friend>();
this.Friends1 = new HashSet<Friend>();
this.Photos = new HashSet<Photo>();
}
public int UserId { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public System.DateTime Birthday { get; set; }
public string ProfileImage { get; set; }
public string AboutUser { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Friend> Friends { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Friend> Friends1 { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Photo> Photos { get; set; }
}
This is the PhotoModel
public class PhotoModel
{
[Required]
public HttpPostedFileBase PhotoFile { get; set; }
}
And this is what I am getting as a view now. This is my /Main/Create View
And this is my /Main/PhotoUpload View
Now I want to put this PhotoUpload view instead of ProfileImage thing inside my Create View. Where do I change this and how?
You should use a ViewModel as that's the recommended practice for transferring data to and from views, in this case you can do the following as #StephenMuecke commented
ViewModel
public class UserViewModel
{
public string Email { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public System.DateTime Birthday { get; set; }
public string ProfileImage { get; set; }
public string AboutUser { get; set; }
[Required]
public HttpPostedFileBase PhotoFile { get; set; }
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(UserViewModel model)
{
if (ModelState.IsValid)
{
AddUser(model);
SavePhoto(model.PhotoFile);
return RedirectToAction("Index");
}
return View(user);
}
private void SavePhoto(HttpPostedFileBase file)
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var filePath = Server.MapPath("/Content/Users/Images");
string savedFileName = Path.Combine(filePath, fileName);
file.SaveAs(savedFileName);
}
}
private void AddUser(UserViewModel model)
{
var user = new User
{
Email = model.Email, Password = model.Password, FirstName = model.FirstName, LastName = model.LastName, Gender = model.Gender, Birthday = model.Birthday, ProfileImage = model.ProfileImage, AboutUser = model.AboutUser
};
db.Users.Add(user);
db.SaveChanges();
}
For further reading:
http://www.mikesdotnetting.com/article/188/view-model-design-and-use-in-razor-views
http://rachelappel.com/use-viewmodels-to-manage-data-amp-organize-code-in-asp-net-mvc-applications/
New to EF, MVC, and databases in general. If this is overly obvious just tell me what this is called exactly and I'd be glad to look it up on here.
I'm not able to apply information calculated from my Foreign Key to my Primary key.
In other words: I'm trying to calculate and apply a new AmountMade by a booth each time we "Sell" an Antique.
Booth Model:
public class Booth
{
public Booth()
{
Antiques = new List<Antique>();
}
[Required]
public int BoothId { get; set; }
[Required]
public string Owner { get; set; }
public double AmountMade { get; set; }
public Antique Antique {get;set;}
public virtual ICollection<Antique> Antiques{get;set;}
}
Antique Model:
public class Antique
{
[Required]
public int AntiqueId { get; set; }
[Required]
public string ItemName { get; set; }
[Required]
public double Price { get; set; }
public bool Sold { get; set; }
public int BoothId { get; set; }
[ForeignKey("BoothId")]
public virtual Booth Booth { get; set; }
}
AntiquesController:
// GET: Antiques/Sell/5
public ActionResult Sell(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Antique antique = db.Antiques.Find(id);
antique.Booth.AmountMade = antique.Booth.AmountMade + antique.Price; //Price of antique is added to Amount made
if (antique == null)
{
return HttpNotFound();
}
ViewBag.BoothId = new SelectList(db.Booths, "BoothId", "Owner", antique.BoothId);
return View(antique);
}
// POST: Antiques/Sell/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Sell([Bind(Include = "AntiqueId,ItemName,Price,BoothId")] Antique antique)
{
if (ModelState.IsValid)
{
db.Entry(antique).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
antique.Sold = true; //Mark as sold
ViewBag.BoothId = new SelectList(db.Booths, "BoothId", "Owner", antique.BoothId);
antique.Booth.AmountMade = antique.Booth.AmountMade + antique.Price; //Price of antique is added to Amount made
return View(antique);
}
This synchronization happens after Db.SaveChanges() is called, but I'm not sure can it be done before that by calling some other method.
i tried to update my database table some fields
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(MemberTasks membertaskdetails)
{
if (ModelState.IsValid)
{
MemberTasks Mtasks = db.MemberTask.Find(membertaskdetails.id);
Mtasks.Taskid = membertaskdetails.Taskid;
Mtasks.status = membertaskdetails.status;
AutoMapper.Mapper.Map(membertaskdetails,Mtasks);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(membertaskdetails);
}
ViewModel
public class MemberTasks
{
[Key]
[Display(Name = "ID")]
public int id { get; set; }
[Display(Name = "Task ID")]
public int Taskid { get; set; }
[Display(Name = "Status")]
public int status { get; set; }
[Display(Name = "Created By")]
public string createdby { get; set; }
[Display(Name = "Team Lead")]
public string TeamLead { get; set; }
[Display(Name = "Note")]
public string Note { get; set; }
[Display(Name = "Members")]
public string Membersid { get; set; }
}
Code is executed successfully but the problem is remaining fields also updated with null value i have 6 columns i want to update 2 columns only.
Any help ?
Your source and destination object used in AutoMapper are of the same type (MemberTasks). That's not how AutoMapper is supposed to be used. AutoMapper is used to map between domain models and view models.
So you must have a view model containing the properties passed from the view:
public class MemberTasksViewModel
{
public int Id { get; set; }
public int Taskid { get; set; }
public int Status { get; set; }
}
and then:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(MemberTasksViewModel viewModel)
{
if (ModelState.IsValid)
{
MemberTasks domainModel = db.MemberTask.Find(viewModel.Id);
Mapper.Map(viewModel, domainModel);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}