How to transfer model to editpage from Data Base? - c#

My input model consists of NewForm in which many fields
public class NewForm
{
[Key]
public int Id { get; set; }
public string HeadForm { get; set; }
public List<Field> Fields { get; set; }
}
public class Field
{
public int Id { get; set; }
public bool Check { get; set; }
public string HeadField { get; set; }
}
I want to take values from the base and edit them, but Model.Fields.Count throw exception. Although the string "HeadForm" is displayed. Lists are not displayed.
EditPage:
#model EditFormApplication.Models.NewForm
#using (Html.BeginForm("Edit", "Home", FormMethod.Post))
{
#Html.TextBoxFor(model => model.HeadForm)
<h5>Fields:</h5><br>
#for ( var i = 0; i< Model.Fields.Count; i++) {
#Html.TextBoxFor(model => model.Fields[i].HeadField)
#Html.CheckBoxFor(model => model.Fields[i].Check)
}
<input type="button" value="Add Field" onclick="addField(this);">
<input type="submit"value="Save">
}
For example, I am typing data by ID = 3.
Controller:
public ActionResult CreateForm(NewForm model)
{
using (NewFormContext db = new NewFormContext())
{
db.NewForms.Add(model);
db.SaveChanges();
return RedirectToAction("Edit");
}
}
public ActionResult Edit()
{
using (NewFormContext db = new NewFormContext()) {
var model = db.NewForms.Find(3);
return this.View(model);
}
}
used Code First and one to many

Sounds like Model.Fields property still contain null when db.NewForms.Find() is executed to assign the model you want to return into view, indicating that EF doesn't create dependent collection yet. As far as I know you should add collection instance definition inside parameterless constructor of entity class:
public class NewForm
{
public NewForm()
{
// instantiate list here
Fields = new List<Field>();
}
[Key]
public int Id { get; set; }
public string HeadForm { get; set; }
public List<Field> Fields { get; set; }
}
Or if you're using lazy loading, mark the property as virtual to let EF instantiate the collection while necessary:
public virtual List<Field> Fields { get; set; }
Related issue:
EF codefirst : Should I initialize navigation properties?

Related

Cannot insert explicit value for identity column in table <Entity> when IDENTITY_INSERT is set to OFF.

I've read every article that stack overflow recommended to me and have not yet solved my problem. This is my first post and I apologize if it is an easy fix, but no matter what I save first (AfterCooler, F1046, or BasicInfo, I get the exception for explicitly inserting AfterCooler's identity. BasicInfo saves fine on it's own, but when adding F1046, saving it, or adding AfterCooler and saving it, I get this exception. AfterCooler and F1046 should have a 1 to 1, and F1046 and BasicInfo should have a one to many relationship.
Entities:
[MetadataType(typeof(F1046MetaDataSource))]
public partial class F1046
{
public int F1046Id { get; set; }
public virtual AfterCooler AfterCooler { get; set; }
public int BasicInfoId { get; set; }
public virtual BasicInfo BasicInfo { get; set; }
}
class F1046MetaDataSource
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int F1046Id { get; set; }
[ForeignKey("BasicInfo")]
public int BasicInfoId { get; set; }
}
[MetadataType(typeof(AfterCoolerMetaDataSource))]
public partial class AfterCooler : IComparer<AfterCooler>
{
public string AfCoolReasonChange { get; set; }
public string VendorAF { get; set; }
public int F1046Id { get; set; }
public virtual F1046 F1046 { get; set; }
}
class AfterCoolerMetaDataSource
{
[Key,ForeignKey("F1046")]
public int F1046Id { get; set; }
}
[MetadataType(typeof(BasicInfoMetaDataSource))]
public partial class BasicInfo
{
public int BasicInfoId { get; set; }
public DateTime? DateBasicInfo { get; set; }
...
public virtual ICollection<F1046> F1046 { get; set; }
public BasicInfo()
{
F1046 = new List<F1046>();
}
}
class BasicInfoMetaDataSource
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int BasicInfoId { get; set; }
}
Repository methods:
public void SaveAfterCooler(AfterCooler afterCooler)
{
if (afterCooler.F1046Id == 0)
{
context.AfterCooler_.Add(afterCooler);
}
else
{
context.Entry(afterCooler).State = EntityState.Modified;
}
context.SaveChanges();
}
(this looks the same for essentially every entity, just swapping the contexts/id's..)
I have a view which has elements of the BasicInfo (but not the id's) and of the F1046 (but not the id's), the members of the F1046 (AfterCooler, its properties, etc..) like this:
<div class="form-group">
#Html.Label("After Cooler Reason")
#Html.EditorFor(x => Model.F1046.AfterCooler.AfCoolReasonChange, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => Model.F1046.AfterCooler.AfCoolReasonChange, "", new { #class = "text-danger" })
</div>
and it gets submitted to a controller method which I shortened to something like this..
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateF1046(F1046_CreateViewModel fm)
{
if (ModelState.IsValid)
{
BasicInfo bi = fm.BasicInfo;
F1046 f1 = fm.F1046;
_f1046Repository.SaveF10461(f1);
bi.F1046.Add(f1);
return RedirectToAction("Summary", bi);
}
I've tried everything in every order or at least it feels that way.. I'm sorry if this doesn't make much sense, the program takes a lot of fields in and I tried to leave out the irrelevant ones. The ViewModel mentioned above for the controller method contains a BasicInfo object and an F1046 object for relevance.
Thank you.

ICollection object edit cshtml

I want create or edit in collection object. But collection object in return null controller .
ViewModel:
public class ViewModelEditManuscript
{
public int Id { get; set; }
public string ArchiveNumber { get; set; }
public ICollection<ViewModelEditManuscriptAuthor> Authors { get; set;
}
public class ViewModelEditManuscriptAuthor
{
public ViewModelEditPerson Author { get; set; }
}
public class ViewModelEditPerson
{
public int Id { get; set; }
public string TRName { get; set; }
}
Controller:
public ActionResult Edit(ViewModelEdit viewModelEdit)
{
problem this.viewModel.Authors = null;
}
Cshtml:
foreach (var item in #Model.Entity.Authors)
{
#Html.TextBoxFor(m => item.Author.Id)
}
When you use #Html.TextBoxFor(m => item.Author.Id) inside your loop, For all textboxes inside the loop, It is going to generate textbox markup with name property as
name="item.Author.Id"
When the form is submitted the Modelbinder cannot map this form data to an object of the ViewModelEditManuscript class.
For the model binding to work, you need to make sure that you are generating the proper field names which matches with your view model property hierarchy.
Since our ViewModelEditManuscript class has a collection property called Authors and each item of that again has an Author property which again has an Id property, We should tell razor to generate name value for our inputs like
name="Authors[0].Author.Id"
name="Authors[1].Author.Id"
We can do Html.TextBox helper method to do that. The first parameter is the value for the name property of the input.
#model ViewModelEditManuscript
#using (Html.BeginForm())
{
var i = 0;
foreach (var item in #Model.Authors)
{
#Html.TextBox("Authors[" + i+ "].Author.Id",item.Author.Id)
i++;
}
<input type="submit"/>
}
This will work assuming your HttpPost action method's argument is of type ViewModelEditManuscript
[HttpPost]
public ActionResult WhateverYourActionMethodNameIs(ViewModelEditManuscript model)
{
// do something with model and redirect/return something
}
I wantto Authors save.
//this Domain
public class Manuscript
{
public int Id { get; set; }
public string ArchiveNumber { get; set; }
[XmlIgnore]
public virtual ICollection<ManuscriptAuthor> Authors { get; set; }
}
public class ManuscriptAuthor
{
public int ManuscriptId { get; set; }
public int AuthorId { get; set; }
}
//this controller
public ActionResult Edit(ViewModelEdit viewModelEdit)
{
Manuscript manuscript = null;
manuscript.Authors = viewModelEdit.Entity.Authors; // this error
}

How to post list of model on controller?

There is 1 form on which i will ask for Academic Details for :
Graduation
Post Graduation(Masters)
Professional Qualification.
So far any user say UserId="1" 3 entries will be created in my AcademicMaster each for bachelor,Master(Post Graduation) and Professional Qualification.
My Database AcademicMaster table fields and datamodel:
Id,Qualification(GraduationCourses),Acheievement,UserId
View Model:
public class AcademicViewModel
{
public int Id { get; set; }
public virtual Graduation Graduation{ get; set; }
public virtual PostGraduation PostGraduation{ get; set; }
public virtual ProfessionalQualification ProfessionalQualification{ get; set; }
}
public class Graduation
{
public string BachelorQualification { get; set; }
public string BachelorAchievement { get; set; }
}
public class PostGraduation
{
public string MasterQualification { get; set; }
public string MasterAchievement { get; set; }
}
public class ProfessionalQualification
{
public string ProfessionalQualifications { get; set; }
}
So my View is like this:
#model AcademicViewModel
#{
IEnumerable<SelectListItem> graduationList = ViewBag.GraduationList;
IEnumerable<SelectListItem> postGraduationList = ViewBag.PostGraduationList;
}
#using (Html.BeginForm())
{
<div class="row">
Bachelors
#Html.DropDownListFor(model => model.Graduation.Qualification, graduationList)
</div>
#Html.TextAreaFor(model => model.Graduation.Achievement)
<div class="row">
MASTERS
#Html.DropDownListFor(model => model.PostGraduation.Qualification, postGraduationList)
</div>
#Html.TextAreaFor(model => model.PostGraduation.Achievement)
<div class="row">
PROFESSIONAL QUALIFITCATION
#Html.TextAreaFor(model => model.ProfessionalQualification.ProfessionalQualifications)
</div>
<input type="submit" value="Save">
}
This is my Controller:
[HttpPost]
public ActionResult MyController(AcademicViewModel model)
{
//Actions
}
So is my View Model structure appropriate and how to create 3 entries in AcademicMaster Table??
I will start by saying that having one table may not be the best choice (what happens if later you start adding additional properties which may be applicable to Graduation that are not applicable to Professional - for example YearOfGraduation - you could end up with a huge number of fields, many of which may have null values.
However, if you want one table, then at least add another field so that you can identify if the data is related to Graduation, PostGraduation or Professional. The associated data model for the AcademicMasters table would be
public class AcademicMaster
{
public int ID { get; set; }
public string Type { get; set; } // may be an enum?
public string Qualification { get; set; }
public string Achievement { get; set; }
public int UserID { get; set; }
}
Side note: It might be better to use an enum for the Type property
public enum AcademicType
{
Graduation,
PostGraduation,
Professional
}
There does not seem to be any need to your current Graduation, PostGraduation and ProfessionalQualification models and your view model should be
public class AcademicViewModel
{
public string GraduationQualification { get; set; }
public string GraduationAchievement { get; set; }
public string PostGraduationQualification { get; set; }
public string PostGraduationAchievement { get; set; }
public string ProfessionalAchievement { get; set; }
public IEnumerable<SelectListItem> GraduationList { get; set; }
public IEnumerable<SelectListItem> PostGraduationList { get; set; }
}
Side notes: Its not clear what your current ProfessionalQualifications property is - does that get assigned to the Qualification field or the Acheievement field in the database? Since your using a view model, then it should include the SelectList's rather that using ViewBag.
Then your view will be
#model AcademicViewModel
#using (Html.BeginForm())
{
<h2>Graduation</h2>
#Html.DropDownListFor(m => m.GraduationQualification, Model.GraduationList)
#Html.TextAreaFor(m => m.GraduationAchievement)
... // repeat for PostGraduation and Professional
<input type="submit" value="Save">
}
And the POST method would be
[HttpPost]
public ActionResult MyController(AcademicViewModel model) // should be named Create?
{
var userID = ....
AcademicMaster graduation = new AcademicMaster
{
Type = AcademicType.Graduation,
Qualification = model.GraduationAchievement,
Achievement = model.GraduationAchievement,
UserId = userID;
};
db.AcademicMasters.Add(graduation);
// Repeat for PostGraduation and Professional
db.SaveChanges();
// redirect?
}

Sending Model issue ASP.net MVC 4

Controller httpGet Action :
[HttpGet]
public ActionResult CalculCom(int id)
{
CalcCom calc = new CalcCom();
ComModel com = calc.CalculCom(id, 10, 2011);
return View(com);
}
This is my View :
// Some code to show my model attribute
#using (Html.BeginForm()) {
#Html.HiddenFor(m=>m.ben)
#Html.HiddenFor(m=>m.centre)
#Html.HiddenFor(m=>m.mtn_brut)
#Html.HiddenFor(m=>m.mtn_net)
#Html.HiddenFor(m=>m.mtn_rs)
#Html.HiddenFor(m=>m.quitaList) // this is a list
#Html.HiddenFor(m=>m.val_rs)
#Html.HiddenFor(m=>m.versNum)
<input type="submit" value="Valider"/>
}
This is my controller HttpPost Action :
[HttpPost]
public ActionResult CalculCom(ComModel model)
{
//some code
foreach (ComModel.quita qi in model.quitaList)
{
var quita = db.QUITA.Find(qi.n_quita);
quita.VERSNUM = vers.VERSNUM;
db.Entry(quita).State = EntityState.Modified;
}
db.SaveChanges();
return RedirectToAction("Index");
}
ComModel :
public class ComModel
{
public int versNum { get; set; }
public decimal mtn_brut { get; set; }
public decimal mtn_net { get; set; }
public decimal mtn_rs { get; set; }
public decimal val_rs { get; set; }
public string ben { get; set; }
public int centre { get; set; }
public List<quita> quitaList = new List<quita>();
public struct quita
{
public decimal mtn_com { get; set; }
public decimal mtn_net { get; set; }
public decimal mtn_ttc { get; set; }
public decimal comp_prime { get; set; }
public decimal mtn_fq { get; set; }
public decimal mtn_tot { get; set; }
public int n_quita { get; set; }
}
}
So What I'm trying to do Is:
getting the Model (HttpGet Action)
show my model the then user will decide it to validate the model or not.
If Model is valide then I will save it to database.
The problem when user Click on submit button the model is sent but the items in quitaList was missing , After sending , in my HttpPost Controler, quitaList was empty
So how to fix it ? Also is there any other ways to do that, showing modal before saving it to database, instead using From to send model?
For get list back in model during form post you need to loop through the list like this
#using (Html.BeginForm()) {
#Html.HiddenFor(m=>m.ben)
#Html.HiddenFor(m=>m.centre)
#Html.HiddenFor(m=>m.mtn_brut)
#Html.HiddenFor(m=>m.mtn_net)
#Html.HiddenFor(m=>m.mtn_rs)
#for(int i=0;i<Model.quitaList.Count;i++)
{
#Html.HiddenFor(m=>m.quitaList[i].mtn_com)
}
#Html.HiddenFor(m=>m.val_rs)
#Html.HiddenFor(m=>m.versNum)
<input type="submit" value="Valider"/>
}
This will give list back in model, but note that it will only contain value of "mnt_com" property. if you want all property value then you need to define all same as in above code in the loop.

MVC, Saving Data into 2 or more Related models from a single Form / View .?

My Model:
(i) For Transaction
public class Transaction
{
[Key]
public int TransactionId { get; set; }
public DateTime OnWardDate { get; set; }
public DateTime ReturnDate { get; set; }
public virtual UserProfile User { get; set; }
}
(ii) For User
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
private UserDetails _details = new UserDetails();
public virtual UserDetails details
{
get { return _details; }
}
}
(ii) For UserDetails
public class UserDetails
{
[Key]
public int DetailsId { get; set; }
public string DLNum { get; set; }
}
My Controller for Create Transaction:
// GET: /Transaction/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Transaction/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Transaction transaction)
{
if (ModelState.IsValid)
{
db.Transactions.Add(transaction);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(transaction);
}
My View for Create transaction:
<div class="editor-label">
#Html.LabelFor(model => model.OnWardDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.OnWardDate)
#Html.ValidationMessageFor(model => model.OnWardDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.details.DLNum)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.User.details.DLNum)
#Html.ValidationMessageFor(model => model.User.details.DLNum)
</div>
When I Submit the form... model.OnWardDate is getting saved but model.User.details.DLNum is not saving
I hv seen about ViewModel. Is that the only option to go with it?
Thanks In Advance.
In your case, I would think it's because your setter is private for UserDetails:
public virtual UserDetails details
{
get { return _details; }
}
If you're creating the tables based on those models and therefore can't afford to modify them, I would indeed advise to make a view model, post using that and then create / update the database entry accordingly.
The main issue is that Entity Framework requires both getter and setter for the POCO properties your class UserDetails only has a getter defined for the details property.
Your models could then be:
public class Transaction
{
[Key]
public int TransactionId { get; set; }
public DateTime OnWardDate { get; set; }
public DateTime ReturnDate { get; set; }
public virtual UserProfile User { get; set; }
}
public class UserProfile
{
[Key]
public int UserId { get; set; }
public string UserName { get; set; }
public virtual UserDetails Details { get; set; }
}
public class UserDetails
{
[Key]
public int DetailsId { get; set; }
public string DLNum { get; set; }
}
2. I recommend using the pattern of instantiating the model in the Controller and passing it to the view as in:
public ActionResult Create()
{
var transaction = new Transaction
{
User = new UserProfile
{
Details = new UserDetails()
}
};
return View(transaction);
}
This ensures your model is properly constructed and allows you to initialize any properties before the view is rendered. You can often get away shortcutting this, IMHO it is better to be explicit.

Categories

Resources