How to correctly save to database? I have the following but not working. I am using a custom ModelMetadata (ORDERMetadata) and setting it equal to the .edmx / order.cs model and trying to save it.
The key field in Order.cs model is [OrderID], but I am passing [model.Order_Number] which is unique value. I am currently, not passing [OrderID] in ORDERMetadata model. Is this required?
Order.cs:
public partial class ORDER
{
public int OrderID { get; set; }
public int Order_Number { get; set; }
public string Order_Type { get; set; }
}
ORDERMetadata model:
[MetadataType(typeof(ORDERMetadata))]
public partial class ORDER
{
// Blank. It's just here to add the class-level attribute.
}
public class ORDERMetadata
{
[Display(Name = "Order Number")]
public int Order_Number { get; set; }
[Display(Name = "Order Type")]
public string Order_Type { get; set; }
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ORDERMetadata model)
{
if (!ModelState.IsValid)
{
return View(model);
}
try
{
// update order
ORDER order = new ORDER();
order.Order_Number = model.Order_Number;
order.Order_Type = model.Order_Type;
db.Entry(order).State = EntityState.Modified;
db.SaveChanges();
ViewBag.UpdateResult = "Order updated!";
return View();
}
}
Change to:
ORDER order = db.ORDERS.SingleOrDefault(p => p.Order_Number == model.Order_Number);
Related
I have a LINQ query in my controller that has a join which selects all records. I'm then passing the ReportCompletionStatus.AsEnumerable() model to my view. But I keep getting the fowlling exceptions..
The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery`1
but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1
I'm setting the model AsEnumerable() and my view is expecting #model IEnumerable so i'm still not sure why it's complaning...
Controller
var ReportCompletionStatus = from r in db.Report_Completion_Status
join rc in db.Report_Category
on r.Report_Category equals rc.ReportCategoryID
select new
{
r.Report_Num,
rc.ReportCategory,
r.Report_Sub_Category,
r.Report_Name,
r.Report_Owner,
r.Report_Link,
r.Report_Description,
r.Last_Published,
r.Previous_Published,
r.Published_By,
r.Previous_Published_By,
r.Last_Edited,
r.Edited_By
};
return View(ReportCompletionStatus.AsEnumerable());
Model
#model IEnumerable<WebReportingTool.Report_Completion_Status>
With your select new, you project to an anonymous type, not to an IEnumerable<WebReportingTool.Report_Completion_Status>
You need to create a ViewModel class (as your projection has data from both Report_Completion_Status and Report_Category) and use it for projection and for your View's model.
class
public class SomeViewModel {
public int ReportNum {get;set;}
public string ReportCategory {get;set;
//etc.
}
projection
select new SomeViewModel
{
ReportNum = r.Report_Num,
ReportCategory = rc.ReportCategory,
//etc.
};
view
#model IEnumerable<SomeViewModel>
By the way, the AsEnumerable is not necessary.
Here's how I got it to work.
Model
public class ReportCategoryListModel
{
public int Report_Num { get; set; }
public string ReportCategory { get; set; }
public string Report_Sub_Category { get; set; }
public string Report_Name { get; set; }
public string Report_Owner { get; set; }
public string Report_Link { get; set; }
public string Report_Description { get; set; }
public Nullable<System.DateTime> Last_Published { get; set; }
public Nullable<System.DateTime> Previous_Published { get; set; }
public Nullable<int> Published_By { get; set; }
public Nullable<int> Previous_Published_By { get; set; }
public Nullable<System.DateTime> Last_Edited { get; set; }
public Nullable<int> Edited_By { get; set; }
}
Controller
var ReportCompletionStatus = from r in db.Report_Completion_Status
join rc in db.Report_Category
on r.Report_Category equals rc.ReportCategoryID
select new ReportCategoryListModel
{
Report_Num = r.Report_Num,
ReportCategory = rc.ReportCategory,
Report_Sub_Category = r.Report_Sub_Category,
Report_Name = r.Report_Name,
Report_Owner = r.Report_Owner,
Report_Link = r.Report_Link,
Report_Description = r.Report_Description,
Last_Published = r.Last_Published,
Previous_Published= r.Previous_Published,
Published_By = r.Published_By,
Previous_Published_By = r.Previous_Published_By,
Last_Edited = r.Last_Edited,
Edited_By = r.Edited_By
};
return View(ReportCompletionStatus);
View
#model IEnumerable<WebReportingTool.Models.ReportCategoryListModel>
I'm new to MVC and are having a hard time figuring some "basic" things out.
I have a ViewModel shaped as follows:
public class ProjectViewModel
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
public DateTime CreatedDate { get; set; }
[Required]
[Display(Name = "Final due date")]
public DateTime FinalDueDate { get; set; }
[Required]
[Display(Name = "Attached equipment")]
public Equipment AttachedEquipment { get; set; }
}
In my Create view I would like to be able to select the value for AttachedEquipment from a dropdownlist. I have a table in my database with all the available Equipments.
I know there is an #Html helper #Html.DropDownListFor which serves this very purpose. However I fail to see how I get the values from the database and spit them out into my view.
My ProjectController looks like this:
private AdventureWorks db = new AdventureWorks();
// GET: Project
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult Create()
{
// I'm guessing this is where I need to do some magic
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ProjectViewModel model)
{
if (ModelState.IsValid)
{
var project = new Project
{
Title = model.Title,
Description = model.Description,
CreatedDate = DateTime.Now,
FinalDueDate = model.FinalDueDate,
Equipment = model.Equipment
};
db.Projects.Add(project);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
How do I load the Equipment values from my DB into a dropdownlist in my Create view?
Since you cant bind a dropdownlist to the complex object AttachedEquipment, I would change the view model to include properties for the selected equipment and a SelectList for the options
public class ProjectViewModel
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
public DateTime CreatedDate { get; set; }
[Required]
[Display(Name = "Final due date")]
public DateTime FinalDueDate { get; set; }
[Required(ErrorMessage="Please select equipment)]
public int? SelectedEquipment { get; set; }
public SelectList EquipmentList { get; set; }
}
Controller
public ActionResult Create()
{
ProjectViewModel model = new ProjectViewModel();
// Assumes your Equipments class has properties ID and Name
model.EquipmentList = new SelectList(db.Equipments, "ID", "Name");
return View(model);
}
View
#model ProjectViewModel
#using(Html.BeginForm())
{
....
#Html.DropDownListFor(m => m.SelectedEquipment, Model.EquipmentList, "--Please select--")
....
}
Alternatively you can bind to m => m.AttachedEquipment.ID (assuming Equipment contains property ID)
I Have two simple model Model1, Model2 as below:
public class Model1
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class Model2
{
public int Id { get; set; }
[Required]
public string Code { get; set; }
}
I Have a BigModel contains two other model as:
public class BigModel
{
public BigModel()
{
Model1 = new Model1 ();
Model2 = new Model2();
}
public Model1 Model1 { get; set; }
public Model2 Model2 { get; set; }
}
and in my Controller:
public ActionResult Register(BigModel bigModel)
{
if (ModelState.IsValid)
{
//do somthing
return RedirectToAction("Index");
}
return View(bigModel);
}
my question is Why ModelState.IsValid is always true? though data annotations are set. and How can I validate two models in one action?
Please don't use above way.Always try to use ViewModel with your views.Put all your data annotations on that ViewModel and check that inside the action method.
Plese check below mentioned sample ViewModel as an example.
public class ProductViewModel
{
public Guid Id { get; set; }
[Required(ErrorMessage = "required")]
public string ProductName { get; set; }
public int SelectedValue { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
[DisplayName("Product Category")]
public virtual ICollection<ProductCategory> ProductCategories { get; set; }
}
Inside the Action Method:
[HttpPost]
public ActionResult AddProduct(ProductViewModel productViewModel) //save entered data
{
//get product category for selected drop down list value
var prodcutCategory = Repository.GetProductCategory(productViewModel.SelectedValue);
//for get all product categories
var prodcutCategories = Repository.GetAllProductCategories();
//for fill the drop down list when validation fails
productViewModel.ProductCategories = prodcutCategories;
//for initialize Product domain model
var productObj = new Product
{
ProductName = productViewModel.ProductName,
ProductCategory = prodcutCategory,
};
if (ModelState.IsValid) //check for any validation errors
{
//save recived data into database
Repository.AddProduct(productObj);
return RedirectToAction("AddProduct");
}
else
{
//when validation failed return viewmodel back to UI (View)
return View(productViewModel);
}
}
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);
}
Customers.cs
public partial class Customers
{
public int sno { get; set; }
public string CustomerName { get; set; }
public string CustomerNo { get; set; }
...
// 20 more attribute too...
}
Cities.cs
public partial class Cities
{
public int sno { get; set; }
public string CityName { get; set; }
public string CityPlate { get; set; }
public string CityPhoneCode { get; set; }
}
AddCustomerViewModel.cs
public class AddCustomerViewModel
{
[Required(ErrorMessage = "Şehir seçiniz.")]
[Display(Name = "Şehir")]
public Nullable<int> CityId { get; set; }
// same with Customers.cs
public int sno { get; set; }
[Required(ErrorMessage = "Müşteri adını giriniz!")]
[Display(Name = "Müşteri Adı")]
public string CustomerName { get; set; }
[Required(ErrorMessage = "Müşteri numarası giriniz!")]
[Display(Name = "Müşteri Numarası")]
public string CustomerNo { get; set; }
...
// 20 more attribute too...
}
Controller
[Authorize(Roles = "Administrator")]
public ActionResult AddCustomer()
{
AddCustomerViewModel addCustomerViewModel = new AddCustomerViewModel();
addCustomerViewModel.Cities = entity.Cities;
return View(addCustomerViewModel);
}
[HttpPost]
[Authorize(Roles = "Administrator")]
public ActionResult AddCustomer(AddCustomerViewModel addCustomerViewModel)
{
entity.Customers.Add(GetCustomerFromViewModel(addCustomerViewModel));
entity.SaveChanges();
return View(addCustomerViewModel);
}
I m using a function that is called GetCustomerFromViewModel to convert addCustomerViewModel to Customer like below:
GetCustomerFromViewModel()
private Customers GetCustomerFromViewModel(AddCustomerViewModel addCustomerViewModel)
{
Customers customer = new Customers();
customer.CityId = addCustomerViewModel.CityId;
customer.CreatorUserId = (Guid)System.Web.Security.Membership.GetUser().ProviderUserKey;
customer.CustomerName = addCustomerViewModel.CustomerName;
customer.CustomerNo = addCustomerViewModel.CustomerNo;
customer.Description = addCustomerViewModel.Description;
...
// 20 more attribute too...
return customer;
}
But Customers class have too many variable (customerNo, CustomerName, ...) , So this is the not good way.
When I use DbContextGenerator and Add classes to dataAnnotations and then When I udated the model, dataAnnotations is deleted. (Because DbContext classes are updated, too)
How Can I use ViewModels with DataAnnotations. And effective insert operation to Db? Article, Tutorial, example or advice?
I hope I can explain.
Thanks a lot...
You may take a look at AutoMapper which will simplify the mapping logic between your domain models and view models so that you don't need to manually map each property. Other than that there's nothing wrong with your code. You are already using a view model and have a mapping layer. So your GetCustomerFromViewModel function might become:
private Customers GetCustomerFromViewModel(AddCustomerViewModel addCustomerViewModel)
{
return Mapper.Map<AddCustomerViewModel, Customers>(addCustomerViewModel);
}
or completely get rid of it and directly use the AutoMapper call in your controller action because this function no longer brings much value:
[HttpPost]
[Authorize(Roles = "Administrator")]
public ActionResult AddCustomer(AddCustomerViewModel addCustomerViewModel)
{
var customer = Mapper.Map<AddCustomerViewModel, Customers>(addCustomerViewModel);
entity.Customers.Add(customer);
entity.SaveChanges();
return View(addCustomerViewModel);
}