this is first time i am doing this, when i want to add new item to the db it fails.
How shall set property of ArticleCategoryId in article class to reference the article category in article as at the moment it is null and does not contain any value? My classes is as follows:
Class for articles:
[Table(Name="Articles")]
public class Article
{
[HiddenInput(DisplayValue=false)]
[Column(IsPrimaryKey=true, IsDbGenerated=true,AutoSync=AutoSync.OnInsert)]
public int ArticleId { get; set; }
[Column(Name="ArticleCategoryId", AutoSync = AutoSync.Never)]
[Mapping.Association(IsForeignKey = true, Name = "FK_Articles_ArticleCategorys")]
public ArticleCategories ArticleCategory{get;set;}
[Column]
public string Label { get; set; }
[DataType(DataType.MultilineText)]
[Column]
public string Text { get; set; }
[DataType(DataType.DateTime)]
[Column]
public DateTime Created { get; set; }
}
Class for categories:
[Table(Name = "ArticleCategorys")]
public class ArticleCategories
{
[HiddenInput(DisplayValue = false)]
[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert, Name="ArticleCategoryId")]
public int ArticleCategoryId { get; set; }
[Column]
public string Name { get; set; }
[Column]
public string Description { get; set; }
[DataType(DataType.DateTime)]
[Column] public DateTime Created { get; set; }
}
My error:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "ArticleId")] Article article)
{
try
{
ArticleCategories category = articleCategoriesRepository.ArticleCategories.FirstOrDefault(x => x.ArticleCategoryId == article.ArticleCategory.ArticleCategoryId);
article.ArticleCategory = category;
article.Created = DateTime.Now;
articlesRepository.SaveArticle(article);
ViewData["Message"] = NudaJeFuc.WebUI.Properties.Resources.text_ArticleSaved;
return RedirectToAction("Index");
}
catch
{
return view();
}
}
I ran into an issue with Linq2SQL mapping, where it does not update when you add new columns to the database, and therefore will fail.
So I would have to delete the .edmx file and re-add it anytime I made changes to the database.
This doesn't happen with ADO.NET Entity Framework, so try that if you can.
found solution, thanks to Steven Sanderson
[Table(Name="Articles")]
public class Article
{
[HiddenInput(DisplayValue=false)]
[Column(IsPrimaryKey=true, IsDbGenerated=true,AutoSync=AutoSync.OnInsert)]
public int ArticleId { get; set; }
[Column]
internal int ArticleCategoryId { get; set; }
internal EntityRef<ArticleCategories> _ArticleCategoryId;
//[Column(AutoSync = AutoSync.OnInsert, Name = "ArticleCategoryId")]
[Association(ThisKey="ArticleCategoryId", Storage="_ArticleCategoryId")]
public ArticleCategories ArticleCategory
{
get
{
return _ArticleCategoryId.Entity;
}
set
{
ArticleCategoryId = value.ArticleCategoryId;
_ArticleCategoryId.Entity = value;
}
}
[Column]
public string Label { get; set; }
[DataType(DataType.MultilineText)]
[Column]
public string Text { get; set; }
[Required(ErrorMessage = "Musíte vybrat kategorii článku.")]
[DataType(DataType.DateTime)]
[Column]
public DateTime Created { get; set; }
}
Related
I will try to keep this one short. Any help is welcome and appreciated!
I have 2 classes that have a many-to-many relationship and their composite key class. When I'm creating a new "appointment" I want to pick "dental procedures" that are in the system.
All works fine until I reach the AppointmentRepository where I try to save the newly created appointment. The error is as stated.
I tried to add the
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
or
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]
annotations above the DentalProcedureId property in the DentalProcedure class, but nothing works. Saved the changes and dropped tables, deleted all of the migrations etc.
DentalProcedure class:
public class DentalProcedure
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int DentalProcedureId { get; set; }
[Required(ErrorMessage = "The name of the procedure must be specified")]
public string ProcedureName { get; set; }
[Required(ErrorMessage = "The price of the procedure must be specified")]
public decimal ProcedurePrice { get; set; }
public bool isEnabled { get; set; }
public List<CustomerProcedure> CustomerProcedures { get; set; }
public List<AppointmentProcedure> AppointmentProcedures { get; set; }
}
Appointment class:
public class Appointment
{
[Key]
public int AppointmentId { get; set; }
[Required]
public DateTime AppointmentStart { get; set; }
[Required]
public DateTime AppointmentEnd { get; set; }
[Required]
public string Title { get; set; }
public string ProcedureDescription { get; set; }
public int CustomerId { get; set; }
public Customer Customer { get; set; }
public int WorkDaysId { get; set; }
public WorkDays WorkDays { get; set; }
public List<AppointmentProcedure> AppointmentProcedures { get; set; }
}
AppointmentProcedure class:
public class AppointmentProcedure
{
public int AppointmentId { get; set; }
public Appointment Appointment { get; set; }
public int DentalProcedureId { get; set; }
public DentalProcedure DentalProcedure { get; set; }
public bool ProcedureAppointmentCanceled { get; set; }
}
Home controller:
Appointment appointment = new Appointment
{
AppointmentStart = model.AppointmentStart,
AppointmentEnd = model.AppointmentEnd,
Title = model.Title,
ProcedureDescription = model.ProcedureDescription,
CustomerId = Id,
WorkDaysId = workkWeek.WorkDaysId,
};
foreach (var proc in model.DentalProcedures)
{
if (proc.isEnabled)
{
appointment.AppointmentProcedures = new List<AppointmentProcedure>
{
new AppointmentProcedure
{
Appointment = appointment,
DentalProcedure = proc,
ProcedureAppointmentCanceled = false
}
};
}
}
_appointment.CreateAppointment(appointment);
And the error :
Thanks once more in advance.
PS: I'm still learning so if I forgot to mention something, I apologize in advance!
Entity Framework needs to track the object in the database so you need to either attach or (what I usually prefer to do) load it from the database. Here's the changed code:
foreach (var proc in model.DentalProcedures)
{
if (proc.isEnabled)
{
//assuming the DBSet is called Procedures
var dbProc = await db.Procedures.FirstOrDefaultAsync(p => p.DentalProcedureId == id));
appointment.AppointmentProcedures = new List<AppointmentProcedure>
{
new AppointmentProcedure
{
Appointment = appointment,
DentalProcedure = dbProc, //now set the loaded entity
ProcedureAppointmentCanceled = false
}
};
}
}
For some reason, i have two tables(they are called differently) in my database and both are fully the same.
Also, each of them has too many attributes.
So image i have two ORM Models,like this one:
[Table(Name = "DataHelper")]
class MySameTable1
{
[Column(IsPrimaryKey = true)]
public int Id { get; set; }
[Column]
public string Name { get; set; }
[Column]
public string Surname { get;set; }
[Column]
public string Country { get;set; }
//etc. too much properties
}
and the second one
[Table(Name = "DataSource")]
class MySameTable2
{
[Column(IsPrimaryKey = true)]
public int Id { get; set; }
[Column]
public string Name { get; set; }
[Column]
public string Surname { get;set; }
[Column]
public string Country { get;set; }
//etc. too much properties
}
So when i'm doing the job with table's:
DataContext _DataContext = new DataContext("connectionstring");
var MySameORM_Model1 = _DataContext.GetTable<MySameTable1>();
var MySameORM_Model2 = _DataContext.GetTable<MySameTable2>();
the main problem occurs,when i need to populate second table(MySameORM_Model2) via data that contains in table MySameTable1(not sometimes it will be directly insert,but sometimes not)
So to not foreach all entries from MySameTable1 , I have tried this steps:
1.Abstract class that contains all properties:
public abstract class BaseSameTable
{
[Column(IsPrimaryKey = true)]
public int Id { get; set; }
[Column]
public string Name { get; set; }
[Column]
public string Surname { get;set; }
[Column]
public string Country { get;set; }
//etc. too much properties
}
//inheritance
[Table(Name = "DataHelper")]
class MySameTable1 : BaseSameTable
{ }
//same
[Table(Name = "DataSource")]
class MySameTable2 : BaseSameTable
{ }
And it didn't work, I got strange exceptions with hierarchy submission
After this, i have changed abstract class to interface abstraction, but unfortenuly it didn't make the trick.
public interface IBaseEntity
{
int Id { get; set; }
string Name { get; set; }
string Surname { get;set; }
string Country { get;set; }
//etc. too much properties
}
[Table(Name = "DataHelper")]
class MySameTable1 : IBaseEntity
{
[Column(IsPrimaryKey = true)]
public int Id { get; set; }
[Column]
public string Name { get; set; }
[Column]
public string Surname { get;set; }
[Column]
public string Country { get;set; }
//etc. too much properties
}
[Table(Name = "DataSource")]
class MySameTable2 : IBaseEntity
{
[Column(IsPrimaryKey = true)]
public int Id { get; set; }
[Column]
public string Name { get; set; }
[Column]
public string Surname { get;set; }
[Column]
public string Country { get;set; }
//etc. too much properties
}
So what is the right approach for my case and what can I do to achieve my goal?
Maybe it needs additional mappings, but google didn't help me.
If your data is going from one table to another table, why get your host machine involve at all? Wite a stored procedure to handle it, so the data never has to leave the dataserver.
Currently I am working on changing the values within a table row, which includes the following variables:
public int ID { get; set; }
public string Item_Name { get; set; }
[DisplayFormat(DataFormatString = "{0:0.##}")]
public decimal Price { get; set; }
public int TimeSlot { get; set; }
public bool Food_AddOns { get; set; }
public bool Drink_AddOns { get; set; }
public virtual Item_Description Item_Description { get; set; }
public virtual Item_Status Item_Status { get; set; }
public virtual Dinner Dinner { get; set; }
public string Ingredients { get; set; }
My View passes the values that are given from the user to this model:
public class Edit_AddItemModel
{
[Display(Name = "ID")]
public int ID { get; set; }
[Display(Name = "Item Name:")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 1)]
public string New_ItemName { get; set; }
[DisplayFormat(DataFormatString = "{0:0.##}", ApplyFormatInEditMode = true)]
[Display(Name = "Price:")]
public decimal New_Price { get; set; }
[Display(Name = "Time Slot:")]
public int New_TimeSlot { get; set; }
[Display(Name = "Lunch Special?:")]
public bool New_Food_AddOns { get; set; }
[Display(Name = "Free Drink?:")]
public bool Drink_AddOns { get; set; }
[Display(Name = "Item Description:")]
public string New_Item_Description { get; set; }
public bool New_spicy { get; set; }
public bool New_gluten { get; set; }
public bool New_vegetarian { get; set; }
[Display(Name = "Dinner:")]
public string New_Dinner { get; set; }
[Display(Name = "Ingredients:")]
[StringLength(140, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 0)]
public string New_Ingredients { get; set; }
}
My values are passed correctly to the controller as illustrated in the image below, and is passed to a function called Edit_CheckAllValues. This is what the Edit_CheckAllValues looks like, which basically creates an ItemsModel Object with the what has been passed from the View:
private ItemsModel Edit_CheckAllValues(ItemsModel NewItem, Edit_AddItemModel model)
{
int CurrentItem_ItemStatus;
NewItem.ID = model.ID;
NewItem.Item_Name = model.New_ItemName;
NewItem.Price = model.New_Price;
NewItem.TimeSlot = model.New_TimeSlot;
NewItem.Food_AddOns = model.New_Food_AddOns;
NewItem.Drink_AddOns = model.Drink_AddOns;
NewItem.Item_Description = convertToForeignKey_ItemDescription(Convert.ToInt32(model.New_Item_Description));
//Get Current Item Status.
CurrentItem_ItemStatus = get_ItemStatus(model.New_spicy, model.New_gluten, model.New_vegetarian);
NewItem.Item_Status = convertToForeignKey_ItemStatus(CurrentItem_ItemStatus);
NewItem.Dinner = convertToForeignKey_Dinner(Convert.ToInt32(model.New_Dinner));
NewItem.Ingredients = model.New_Ingredients;
return NewItem;
}
An Example of what is returned, what the new ItemModel looks like, which contains the ID of the item I want to edit: The Return Value:
An Example of one of the foreign keys being changed from ID: 20 to ID: 2 Item Description Foreign Key Change:
The New Object is then passed back to the original ActionResult EditItem, which it is changing the state of the item selected, which works correctly when changing variables that are not foreign keys such as price, Item Name, TimeSlot, etc:
public ActionResult EditItem(EditItemModel model)
{
if (ModelState.IsValid)
{
ItemsModel newItem = new ItemsModel();
newItem = Edit_CheckAllValues(newItem, model.edit_AddItemModel);
ApplicationDbContext db = new ApplicationDbContext();
db.Items.Attach(newItem); //Tired both with Attach and Without Attach
db.Entry(newItem).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("ChangeItems", "Employee");
}
I'm not sure where in my code I need to make edits, but my guess is I need to grab the row first within my Edit_CheckAllValues instead of passing the values into a new Object and sending it to the database using EntityState.Modified.
Any help would be appreciated, for I have been stuck on this question for 3 days now.
Based off the reference to this page (ASP.Net MVC 4 Update value linked to a foreign key column)
I was able to figure out the problem. The portions I needed to update were my ItemsModel:
public class ItemsModel
{
public int ID { get; set; }
public string Item_Name { get; set; }
[DisplayFormat(DataFormatString = "{0:0.##}")]
public decimal Price { get; set; }
public int TimeSlot { get; set; }
public bool Food_AddOns { get; set; }
public bool Drink_AddOns { get; set; }
[ForeignKey("Item_Description")]
public virtual int Item_Description_ID { get; set; }
public virtual Item_Description Item_Description { get; set; }
[ForeignKey("Item_Status")]
public virtual int Item_Status_ID { get; set; }
public virtual Item_Status Item_Status { get; set; }
[ForeignKey("Dinner")]
public virtual int Dinner_ID { get; set; }
public virtual Dinner Dinner { get; set; }
public string Ingredients { get; set; }
}
Adding the [ForeignKey] from the API: using System.ComponentModel.DataAnnotations.Schema;
and update my Edit_CheckAllValues function:
private ItemsModel Edit_CheckAllValues(ItemsModel NewItem, Edit_AddItemModel model)
{
int CurrentItem_ItemStatus;
NewItem.ID = model.ID;
NewItem.Item_Name = model.New_ItemName;
NewItem.Price = model.New_Price;
NewItem.TimeSlot = model.New_TimeSlot;
NewItem.Food_AddOns = model.New_Food_AddOns;
NewItem.Drink_AddOns = model.Drink_AddOns;
//NewItem.Item_Description = convertToForeignKey_ItemDescription(Convert.ToInt32(model.New_Item_Description));
NewItem.Item_Description_ID = Convert.ToInt32(model.New_Item_Description);
//Get Current Item Status.
CurrentItem_ItemStatus = get_ItemStatus(model.New_spicy, model.New_gluten, model.New_vegetarian);
NewItem.Item_Status_ID = CurrentItem_ItemStatus;
// NewItem.Item_Status = convertToForeignKey_ItemStatus(CurrentItem_ItemStatus);
NewItem.Dinner_ID = 163; //Ignore this is my empty default Dinner.
// NewItem.Dinner = convertToForeignKey_Dinner(Convert.ToInt32(model.New_Dinner));
// CurrentItem.Item_Description = convertToForeignKey_ItemDescription(Convert.ToInt32(model.New_Item_Description));
NewItem.Ingredients = model.New_Ingredients;
return NewItem;
}
The entity-modified will finally register the changes to the foreign keys.
Is there any way to somehow combine the data from two models and THEN map them both to the same viewModel in the context of an edit action?
I have never had to update several tables at once in an edit action in ASP.NET MVC with Entity Framework 6.1.3. This is the layout:
I have a DB table called "Address" which has fields for StreetNumber, StreetName, City, State, ZipCode. It has a one-to-one relationship with another table called Bars. As in, a bar can only have one address and one address can only have one bar.
Because I am storing this data in two separate tables, I am having a very difficult time trying to successfully implement an Edit action which takes data from one form (BarForm) and should update both the Bar and Address database tables. See my code:
BarController
public ActionResult Edit(int id)
{
var bar = _context.Bars.SingleOrDefault(m => m.Id == id);
var address = _context.Addresses.SingleOrDefault(a => a.BarId == id);
//Make sure that the id actually exists:
if (bar == null)
{
return HttpNotFound();
}
var viewModel = Mapper.Map<Bar, BarFormViewModel>(bar, new BarFormViewModel());
if (address == null)
{
address = new Address();
}
Mapper.Map<Address, BarFormViewModel>(address, viewModel);
viewModel.IsNew = false;
return View("BarForm", viewModel);
}
[ValidateAntiForgeryToken]
public ActionResult Save(BarFormViewModel bar)
{
if (!ModelState.IsValid)
{
var viewModel = Mapper.Map<BarFormViewModel, BarFormViewModel>(bar, new BarFormViewModel());
viewModel.IsNew = false;
return View("BarForm", viewModel);
}
if (bar.Id == 0)
{
var newbar = Mapper.Map<BarFormViewModel, Bar>(bar);
newbar.LastUpdated = DateTime.UtcNow;
_context.Bars.Add(newbar);
var addressToAdd = Mapper.Map<BarFormViewModel, Address>(bar);
_context.Addresses.Add(addressToAdd);
}
else
{
var barInDb = _context.Bars.Single(b => b.Id == bar.Id);
var addressInDb = _context.Addresses.Single(a => a.BarId == bar.Id);
Mapper.Map<BarFormViewModel, Bar>(bar, barInDb);
Mapper.Map<BarFormViewModel, Address>(bar, addressInDb);
}
_context.SaveChanges();
return RedirectToAction("Index", "Bar");
}
Domain Models:
public class Bar
{
public int Id { get; set; }
public string Name { get; set; }
[Required]
public string GooglePlaceId { get; set; }
public string SundayDiscounts { get; set; }
public string MondayDiscounts { get; set; }
public string TuesdayDiscounts { get; set; }
public string WednesdayDiscounts { get; set; }
public string ThursdayDiscounts { get; set; }
public string FridayDiscounts { get; set; }
public string SaturdayDiscounts { get; set; }
[Display(Name = "Last Updated")]
public DateTime LastUpdated { get; set; }
}
public class Address
{
public int Id { get; set; }
public int? Number { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
public string State { get; set; }
[Required]
public int ZipCode { get; set; }
public Bar Bar { get; set; }
public int BarId { get; set; }
}
View Model which includes both Address and Bar properties:
{
public class BarFormViewModel
{
public int? Id { get; set; }
public string Name { get; set; }
[Required]
[Display(Name = "Google Place ID")]
public string GooglePlaceId { get; set; }
[Display(Name = "Sunday Happy Hour Info:")]
public string SundayDiscounts { get; set; }
[Display(Name = "Monday Happy Hour Info:")]
public string MondayDiscounts { get; set; }
[Display(Name = "Tuesday Happy Hour Info:")]
public string TuesdayDiscounts { get; set; }
[Display(Name = "Wednesday Happy Hour Info:")]
public string WednesdayDiscounts { get; set; }
[Display(Name = "Thursday Happy Hour Info:")]
public string ThursdayDiscounts { get; set; }
[Display(Name = "Friday Happy Hour Info:")]
public string FridayDiscounts { get; set; }
[Display(Name = "Saturday Happy Hour Info:")]
public string SaturdayDiscounts { get; set; }
[Display(Name = "Last Updated")]
public DateTime? LastUpdated { get; set; }
//Address Model Info
public Address Address { get; set; }
public int? AddressId { get; set; }
[RegularExpression("([1-9][0-9]*)", ErrorMessage = "Must be a number")]
public int? Number { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
public string State { get; set; }
[Required]
public int? ZipCode { get; set; }
public bool IsNew { get; set; }
}
The problem here is that I am getting an empty AddressId with this setup, which is causing an exception when the Save action gets run. This is because the BarForm view is getting passed a ViewModel which has been mapped from a Bar object and the Bar domain model actually has no Address information in it, since it is not the Address model/table.
Is there any way to somehow combine the data from both the Address and Bar models and THEN map them both to the same viewModel?
I keep getting a Sequence Contains no Elements error for this line in the Save action:
var addressInDb = _context.Addresses.Single(a => a.Id == bar.AddressId);
I also tried:
var addressInDb = _context.Addresses.Single(a => a.BarId == bar.Id);
Neither work. I understand what the error is saying and have also checked the actual HTML for my hidden Addressid field and it is blank... See code in my BarForm View:
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.AddressId)
#Html.AntiForgeryToken()
Remove the new BarFormViewModel() as the second parameter in your mapping calls as it is not necessary.
In your post action, inside your if statement that checks if the ModelState is valid and if bar.Id == 0, bar is already a view model, so no need to mapping.
And when you create your AutoMapper mapping, you must create a custom property mapping because the Address.Id property will not map automatically to the AddressId property as the name is not the same.
AutoMapper.Mapper.CreateMap<Address, BarFormViewModel>()
.ForMember(dest => dest.AddressId, o => o.MapFrom(source => source.Id));
And then do the same for the inverse mapping.
I have two models, a code model and a tag model which are linked by a many to many relationship. I am trying to add a code entry that includes a possible selection of many tags using a view model (using check boxes for the tags in my view). I am getting the error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List'1[StoRed.Models.Code]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[StoRed.Models.CodeTagViewModel]'.
It feels like I need to somehow convert my data to the acceptable format before trying to save it into the table but I'm new to MVC and I am having trouble finding any useful information on the internet about my specific problem. Any help would be greatly appreciated.
The code model
public class Code
{
[Key]
public int CodeID { get; set; }
[Required]
[StringLength(30)]
public string Title { get; set; }
[Required]
[StringLength(150)]
public string Description { get; set; }
public DateTime DateAdded { get; set; }
public DateTime LastUpdated { get; set; }
[Required]
[StringLength(30)]
public string Project { get; set; }
[Required]
[StringLength(30)]
public string CMS { get; set; }
public int DotNetVersion { get; set; }
[Required]
[StringLength(150)]
public string Dependencies { get; set; }
[StringLength(30)]
public string Author { get; set; }
public string CodeFile { get; set; }
[Required]
[StringLength(100)]
public string TFSLocation { get; set; }
////Creates a relationship in the DB with Tag
//[ForeignKey("TagID")]
public virtual ICollection<Tag> Tags { get; set; }
////Purely for API
//[Required]
public int TagID { get; set; }
}
The Tag model
public class Tag
{
[Key]
public int TagID { get; set; }
[Required]
[StringLength(30)]
public string TagName { get; set; }
public virtual ICollection<Code> Code { get; set; }
}
The context
public class Context : DbContext
{
public DbSet<Code> Code { get; set; }
public DbSet<Tag> Tags { get; set; }
}
The view model
public class CodeTagViewModel
{
public Tag Tag { get; set; }
public Tag TagID { get; set; }
public List<Tag> Tags { get; set; }
public int CodeID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime DateAdded { get; set; }
public DateTime LastUpdated { get; set; }
public string Project { get; set; }
public string CMS { get; set; }
public int DotNetVersion { get; set; }
public string Dependencies { get; set; }
public string Author { get; set; }
public string CodeFile { get; set; }
public string TFSLocation { get; set; }
}
Relevant part of the code controller
[HttpPost]
public ActionResult Create(CodeTagViewModel codeTagViewModel)
{
if (ModelState.IsValid)
{
Code code = new Code();
Tag tag = new Tag();
var codeTag = new CodeTagViewModel();
code.Title = codeTagViewModel.Title;
code.Description = codeTagViewModel.Description;
code.DateAdded = codeTagViewModel.DateAdded;
code.LastUpdated = codeTagViewModel.LastUpdated;
code.Project = codeTagViewModel.Project;
code.CMS = codeTagViewModel.CMS;
code.DotNetVersion = codeTagViewModel.DotNetVersion;
code.Dependencies = codeTagViewModel.Dependencies;
code.Author = codeTagViewModel.Author;
code.CodeFile = codeTagViewModel.CodeFile;
code.TFSLocation = codeTagViewModel.TFSLocation;
code.Tags = codeTagViewModel.Tags;
db.Code.Add(code);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(codeTagViewModel);
}
Your best bet is to create some kind of provider/manager/service/factory/handler - choose a name that makes most sense in terms of the job it is doing within the flow of data through your system - that is responsible for taking the ViewModel and mapping the properties of the ViewModel into an instance of the domain model before persisting the domain model to the data store, either itself or by passing the hydrated domain model to a repository layer. You can either do this manually or by using something like AutoMapper. Here's a quick manual example:
Create a CommandHandlers folder in your web project with the interface and dependant handler:
public interface ICodeCommandHandler
{
int Save(CodeTagViewModel input);
}
public class CodeCommandHandler : ICodeCommandHandler
{
private IRepository<Code> repository;
public CodeCommandHandler(IRepository<Code> repository)
{
this.repository = repository;
}
public int Save(CodeTagViewModel input)
{
Code code = new Code();
Tag tag = new Tag();
code.Title = input.Title;
code.Description = input.Description;
code.DateAdded = input.DateAdded;
code.LastUpdated = input.LastUpdated;
code.Project = input.Project;
code.CMS = input.CMS;
code.DotNetVersion = input.DotNetVersion;
code.Dependencies = input.Dependencies;
code.Author = input.Author;
code.CodeFile = input.CodeFile;
code.TFSLocation = input.TFSLocation;
code.Tags.Add(tag);
return repository.Save(code);
}
}
Then in your controller, inject the ICodeCommandHandler in via constructor injection, the same as you do with the repository in the CodeCommandHandler:
private readonly ICodeCommandHandler commandHandler;
public CodeController(ICodeCommandHandler commandHandler)
{
this.commandHandler = commandHandler;
}
[HttpPost]
public ActionResult Create(CodeTagViewModel codeTagViewModel)
{
if (!ModelState.IsValid)
{
return View(codeTagViewModel);
}
var id = codeCommandHandler.Save(codeTagViewModel);
// maybe do something useful with the document id after save
return RedirectToAction("Index");
}
To keep the Repository nice and simple, here's how that could look:
public interface IRepository<T>
{
int Save(T entity);
}
public class CodeRepository : IRepository<Code>
{
public int Save(Code entity)
{
using (var context = new Context())
{
context.Code.Add(entity);
context.SaveChanges();
}
}
}
I've not gone into detail about the dependency injection side of things as that wasn't part of the question but this should give you an idea of where to start