mvc razor post to 2 models - c#

I have a Razor view that has form data. When I submit the form I want to enter one column(ID) in the "Form" model and also pass the entire form data to the "Init" model.
View:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Id, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Id, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Id, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.name, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
Model 1 : Init
public partial class Init
{
public int Id { get; set; }
public string name{ get; set; }
}
Model 2 : Form
public partial class Form
{
public int Id { get; set; }
public int field2 { get; set; }
public int field3 { get; set; }
}
Controller:
public ActionResult Create([Bind(Include = "Id,Name")] Init init)
{
if (ModelState.IsValid)
{
db.Init.Add(init);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(init);
}

Just create one input tag with an unique name for each of your models' items and let the model binder do its job.
In the example bellow the Id property is passed to modelA and modelB.
View Model
public class TestViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
Models
public class TestModelA
{
public int Id { get; set; }
public string Name { get; set; }
}
public class TestModelB
{
public int Id { get; set; }
public string Foo { get; set; }
public string Bar { get; set; }
}
Controller
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(TestModelA modelA, TestModelB modelB)
{
return View();
}
View
#using (Html.BeginForm("Receive")) {
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(Model => Model.Id, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Id, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Id, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<label for="foo" class="control-label col-md-2">Foo</label>
<div class="col-md-10">
<input type="text" name="foo" id="foo" class="form-control text-box single-line" />
</div>
</div>
<div class="form-group">
<label for="bar" class="control-label col-md-2">Bar</label>
<div class="col-md-10">
<input type="text" name="bar" id="bar" class="form-control text-box single-line" />
</div>
</div>
<input type="submit" />
</div>
}

I am thinking you want to save details into "Init" First. once it is saved pass the ID value of "Init" and save it into "Form" Model
First create the relationship between "Init" model and "Form" model
Add the following property in "Form" model
public int initID
I didn't test this one but I think it should help
Init Initobj = new Init
{
Id = Id ,
DocId= DocId,
SupplierText=SupplierText
//other properties
};
db.Init.Add(Initobj);
db.SaveChanges();
Form formobj = new Form
{
initID= Initobj.Id,
};
db.forms.Add(formobj);
db.SaveChanges();
You can check this link for reference
Link for reference

You should just continue:
public ActionResult Create([Bind(Include = "Id, name")] Init init,
[Bind(Include = "Id")] Form form)
{
if (ModelState.IsValid)
{
db.Init.Add(init);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(init);
}

Related

Entity Framework 6: entities and relationships

I am a solo and very beginner learner. I am trying to create a simple code first app with a database using EF6. I cannot understand how to insert the data of a entity inside another by the frontend.
I have two entities:
public class Movie
{
[Key]
public int Id { get; set; }
public string Title{ get; set; }
public int ActorId { get; set; }
public ICollection<Actor> Actors { get; set; }
}
public class Actor
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("MovieId")]
public ICollection<Movie> Movies { get; set; }
}
The controller.
public ActionResult AddMovie()
{
var actorsList = (from Name in ctx.Attors select Name).ToList();
ViewBag.Actors = new SelectList(actorsList, "Name", "Name");
return View(new Film());
}
[HttpPost]
public ActionResult PerformAddMovie(Movie m)
{
try
{
ctx.Movies.Add(m);
ctx.SaveChanges();
return RedirectToAction("Index", "Home");
}
catch(Exception ex)
{
ModelState.AddModelError("", ex.Message);
}
return RedirectToAction("Index", "Home");
}
#model Cinema.Models.Movie
#{
ViewBag.Title = "AddMovie";
}
<h2>AddFilm</h2>
#{
var list = ViewBag.Actors as SelectList;
}
#using (Html.BeginForm("PerformAddMovie", "Movie", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Film</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ActorId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ActorId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ActorId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Actors, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.Actors, list, "---Select---", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Actors, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
After adding some movies into the database by the frontend web page, in the addmovie web page I can select one of them by the dropdown list, but when I save the movie nothing happens inside the third table created with movieid and actorid, it is always empty.
What am I doing wrong?
The Model is wrong
public class Movie
{
[Key]
public int Id { get; set; }
public string Title{ get; set; }
public int ActorId { get; set; }
public virtual Actor Actor { get; set; } // It should be one to one relationship
}
public class Actor
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
//[ForeignKey("MovieId")] This is unneccessary
public ICollection<Movie> Movies { get; set; }
}
Then u can select the Actor Id as key while display actor name in the select list
ViewBag.Actors = new SelectList((from s in db.Actor
select new {Id = s.Id, Name = s.Name }),
"Id", "Name");
Remove this under your html as the Id is attached to the dropdown list
<div class="form-group">
#Html.LabelFor(model => model.ActorId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ActorId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ActorId, "", new { #class = "text-danger" })
</div>
</div>
change the dropdownlist to this
<div class="form-group">
#Html.LabelFor(model => model.ActorId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.ActorId, (Selectlist)ViewBag.Actor, "---Select---", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ActorId, "", new { #class = "text-danger" })
</div>
</div>

Inserting Partial View inside another Partial View Issues (Collection.cshtml ISSUE)

I have PROPERTY VM which contains List<FounderInvestmentViewModel>.I have successfully inserted the partial view of FounderInvestmentViewModel into the Main Create Property view.
FounderInvestmentViewModel in turn contains List<InstallmentDetailsViewModel>. I have created the Partial View for InstallmentDetailsViewModel as _InstallmentDetails.cshtml and all the necessary actions.
I want to insert the _InstallmentDetails.cshtml into the partial view of FounderInvestmentViewModel which is in turn inserted into the Main View.
First let us take a look at the codes that I have used so far :--
Property View Model:-
public class PropertyViewModel
{
public int? Id { get; set; }
public string PropertyTitle { get; set; }
....other attributes....
public List<FounderInvestmentViewModel> FounderInvestments { get; set; } = new List<FounderInvestmentViewModel>();
}
FounderInvestmentViewModel:-
public class FounderInvestmentViewModel
{
public int? Id { get; set; }
public int InvestorId { get; set; }
public double Investment { get; set; }
public int InstallmentPeriod { get; set; }
public IEnumerable<SelectListItem> FounderInvestorList { get; set; }
public List<InstallmentDetailsViewModel> InstallmentDetails { get; set; } = new List<InstallmentDetailsViewModel>();
}
InstallmentDetailsViewModel:-
public class InstallmentDetailsViewModel
{
public int? Id { get; set; }
[Display(Name = "Pay Date")]
public List<DateTime> PayDates { get; set; }
[Required]
public List<double> InstallmentAmounts { get; set; }
}
PartialView for InstallmentDetails (_InstallmentDetails.cshtml):-
#model propertyMgmt.ViewModel.InstallmentDetailsViewModel
<div class="installmentDetails">
#using (Html.BeginCollectionItem("InstallmentDetails"))
{
#Html.HiddenFor(m => m.Id, new { #class = "id" })
<div class="form-group">
#Html.LabelFor(m => m.InstallmentAmounts, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(m => m.InstallmentAmounts, new { htmlAttributes = new { #class = "form-control", #type = "number" } })
#Html.ValidationMessageFor(m => m.InstallmentAmounts, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.PayDates, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(m => m.PayDates, new { htmlAttributes = new { #class = "form-control", #placeholder = "01/02/2017" } })
#Html.ValidationMessageFor(m => m.PayDates, "", new { #class = "text-danger" })
</div>
</div>
}
</div>
This _InstallmentDetails.cshtml is inserted into this _FounderInvestmentDetails.cshtml which is PartialView for FounderInvestmentDetails View Model:-
#model propertyMgmt.ViewModel.FounderInvestmentViewModel
<div class="founderInvestmentDetails">
#using (Html.BeginCollectionItem("FounderInvestments"))
{
#Html.HiddenFor(m => m.Id, new { #class = "id" })
<div class="form-group">
#Html.LabelFor(m => m.InvestorId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.InvestorId, Model.FounderInvestorList, "Select Investor", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.InvestorId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Investment, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(m => m.Investment, new { htmlAttributes = new { #class = "form-control", #type = "number" } })
#Html.ValidationMessageFor(m => m.Investment, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.InstallmentPeriod, htmlAttributes: new { #class = "control-label col-md-2", #type = "number" })
<div class="col-md-10">
#Html.EditorFor(m => m.InstallmentPeriod, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(m => m.InstallmentPeriod, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group" id="installmentDetailsDiv">
#foreach (var InstallmentDetails in Model.InstallmentDetails)
{
#Html.Partial("_InstallmentDetails", InstallmentDetails)
}
</div>
<div class="form-group col-md-10">
<input type="button" class="btn btn-info btn-xs" value="Add Installment Details" onclick="addInstallmentDetails()" />
</div>
}
</div>
This is the MAIN CREATE VIEW :-
#model propertyMgmt.ViewModel.PropertyViewModel.PropertyViewModel
#{
ViewBag.Title = "Create";
}
<script src="~/Areas/Admin/themes/jquery/jquery.min.js"></script>
<h2>Property</h2>
#using (Html.BeginForm("Create", "Property", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Add Property</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.PropertyTitle, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PropertyTitle, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PropertyTitle, "", new { #class = "text-danger" })
</div>
</div>
.....Other form Groups.....
<div id="founderInvestmentDetails">
#foreach(var FounderInvestments in Model.FounderInvestments)
{
#Html.Partial("_FounderInvestmentDetails", FounderInvestments)
}
</div>
<div class="form-group col-md-10" >
<input type="button" class="btn btn-info btn-xs" value="Add Founder Investors" onclick="addFounderInvestors()" />
</div>
</div>
}
This is My JS Code in the Main View:-
function addFounderInvestors() {
var url = '#Url.Action("FounderInvestmentDetails")';
var form = $('form');
var founders = $('#founderInvestmentDetails');
$.get(url, function (response) {
founders.append(response);
// Reparse the validator for client side validation
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
};
function addInstallmentDetails() {
var url = '#Url.Action("InstallmentDetails")';
var form = $('form');
var installments = $('#installmentDetailsDiv');
$.get(url, function (response) {
installments.append(response);
// Reparse the validator for client side validation
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
};
Controller Code :-
public PartialViewResult FounderInvestmentDetails()
{
var model = new FounderInvestmentViewModel {
FounderInvestorList = _investorQueryProcessor.GetInvestorByType(1).Select(x => new SelectListItem
{
Value = x.Id.ToString(),
Text = x.InvestorName
})
};
//return PartialView(model);
return PartialView("_FounderInvestmentDetails", model);
}
public PartialViewResult InstallmentDetails()
{
return PartialView("_InstallmentDetails",new InstallmentDetailsViewModel());
}
public ActionResult Create()
{
if (Session["AdminName"] != null)
{
//ViewBag.Investors = SelectListItems;
List<FounderInvestmentViewModel> model = new List<FounderInvestmentViewModel>();
List<InstallmentDetailsViewModel> model2 = new List<InstallmentDetailsViewModel>();
return View(new PropertyViewModel());
}
else return Redirect("/Account/Login");
}
EDIT:-
Sorry this is what is throwing the exception -->> Collection.cshtml
PROCESS:- In the Main View, "Add Founder Investor Buttons" on click event adds the partial view _FounderInvestmentDetails.cshtml successfully.Now the "Add Installment Details" button is appended.Upon clicking this "Add Installment Details" button _InstallmentDetails.cshtml partial view should be appended,BUT this part is not working. When I click this button, I get the error "Object reference not set to an instance of an object" in the following code:-
#using HtmlHelpers.BeginCollectionItem
<ul>
#foreach (object item in Model)-->>ERROR CODE
{
<li>
#using (Html.BeginCollectionItem(Html.ViewData.TemplateInfo.HtmlFieldPrefix))
{
#Html.EditorFor(_ => item, null, "")
}
</li>
}
</ul>
The Paydates and Installments does not need to be <List> as it already is a PartialView and can be added multiple times.
public class InstallmentDetailsViewModel {
public int? Id { get; set; }
[Display(Name = "Pay Date")]
public List<DateTime> PayDates { get; set; }
[Required]
public List<double> InstallmentAmounts { get; set; }
}

Getting "The input is not a valid Base-64 string as it contains a non-base 64 character" when trying to upload an image

I have no idea why I am getting this exception. I am trying to implement a simple upload image functionality.
I am getting the error when I am trying to save the image along with the rest of the data.
I suspect the the problem is in the view, because I used this code from my model and action method in another project and the code worked.
Can someone help with this. I believe I am close.
Model :
public class Company
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CompanyId { get; set; }
public byte[] ImageData { get; set; }
[NotMapped]
public HttpPostedFileBase UploadImage { get; set; }
[NotMapped]
public string ImageBase64 => System.Convert.ToBase64String(ImageData);
public string CompanyName { get; set; }
public string CompanyAddress { get; set; }
public string CompanyCountry { get; set; }
public string CompanyCity { get; set; }
public string CompanyPostalCode { get; set; }
public string CompanyPhoneNumber { get; set; }
public string CAId { get; set; }
}
Controller :
public ActionResult Create([Bind(Include = "CompId,ImageData,CompanyName,CompanyAddress,CompanyCountry,CompanyCity,CompanyPostalCode,CompanyPhoneNumber,EmailCA")] Company company, HttpPostedFileBase UploadImage)
{
if (ModelState.IsValid)
{
byte[] buf = new byte[UploadImage.ContentLength];
UploadImage.InputStream.Read(buf, 0, buf.Length);
company.ImageData = buf;
db.Companies.Add(company);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(company);
}
View :
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Company</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ImageData, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="col-md-10">
#Html.TextBoxFor(model => model.ImageData, new { type = "file" })
#*<input type="file" name="ImageData" class="input-files" />*#
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CompanyName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CompanyName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CompanyName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CAId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CAId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CAId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
In your view your using #Html.TextBoxFor(model => model.ImageData, new { type = "file" }) where I think you should use #Html.TextBoxFor(model => model.UploadImage, new { type = "file" }) instead.
And in order to make that pass I think you need to add the UploadImage property to the Bind(Include) string as following:
public ActionResult Create([Bind(Include = "CompId,ImageData,CompanyName,CompanyAddress,CompanyCountry,CompanyCity,CompanyPostalCode,CompanyPhoneNumber,EmailCA,UploadImage")] Company company)

ASP.NET MVC 5 : Editing multiple records in a view and model binding (Bulk data update)

I need correction on the code below.
I have 2 classes "Employee" and "Child".
When I want to create a new Employee, I would like to be able to create in that same form the related Child (2 Children maximum).
Below are the models
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int ChildID { get; set; }
public virtual ICollection<Child> Childs { get; set; }
}
public class Child
{
public int ChildID { get; set; }
public string NameChild { get; set; }
public string SurnameChild { get; set; }
public virtual Employee Employee { get; set; }
}
The Employee controller
public class EmployeController : Controller
{
private ComideContext db = new ComideContext();
// GET: Employe/Create
public ActionResult Create()
{
List<Child> model = new List<Child>();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "EmployeID,Name,Surname,ChildID")] Employee employee)
{
if (ModelState.IsValid)
{
db.Employes.Add(employe);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(employe);
}
}
The View of the Employee form
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Employe</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Surname, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Surname, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Surname, "", new { #class = "text-danger" })
</div>
</div>
#for (int i=0; i<2; i++ )
{
<div class="form-group">
#Html.LabelFor(model => model.NameChild, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.NameChild, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.NameChild, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SurnameChild, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SurnameChild, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SurnameChild, "", new { #class = "text-danger" })
</div>
</div>
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
Any help/thoughts would be most appreciated.
Thank you.
Disclaimer: I've done this on MVC 3. I don't know if there is an easier way to do it in MVC 5.
You will need to index the children in the view code so when you submit the form the model binder knows how to construct the Employee object.
This could be done this way:
for (var i = 0 ; i < collectionSize; i++)
{
#Html.EditorFor(child => Model.Childs[i].ChildID)
#Html.ValidationMessageFor(child => Model.Childs[i].ChildID)
[....]
}
This would require your collection to be initialized when passed to the view.
Another way you can bind to collection is to programatically build the html components' name to include their index in the list.
See the example below:
<input name="Employee.Childs[0].ChildID" >
<input name="Employee.Childs[1].ChildID" >

Send Data From View to Model With ViewModel

I have this ViewModel:
public class Rapport
{
[Key]
public int RapportId { get; set; }
public RapportAnomalie rapport { get; set; }
public IEnumerable<RefAnomalie> refAnomalies { get; set; }
}
which has two models in it, RapportAnomalie :
public class RapportAnomalie
{
[Key]
public int codeRapport { get; set; }
public DateTime date { get; set; }
public String heure { get; set; }
public String etat { get; set; }
[ForeignKey("codeAgence")]
public virtual Agence agence { get; set; }
public int codeAgence { get; set; }
public IEnumerable<LigneRapportAnomalie> lignesRapport { get; set; }
}
and RefAnomalie.
However when I want to send data from view to controller from a form, I keep getting an exception.
The view :
#model InspectionBanque.Models.Rapport
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>RapportAnomalie</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.rapport.date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.rapport.date, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.rapport.heure, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.rapport.heure, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.rapport.etat, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.rapport.etat, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.rapport.codeAgence, "codeAgence", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("codeAgence", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.rapport.codeAgence, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
#for (int i = 0; i < Model.refAnomalies.Count(); i++)
{
<div class="col-md-10">
#Html.DisplayFor(model => model.refAnomalies.ElementAt(i).libele)
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
and then the controller :
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create( Rapport rapportAnomalie)
{
if (ModelState.IsValid)
{
RapportAnomalie rp = new RapportAnomalie();
db.rapportAnomalies.Add(rapportAnomalie.rapport);
db.SaveChanges();
return RedirectToAction("Index");
}
var refanomal = from r in db.refAnnomalies
select r;
Rapport rapport = new Rapport { rapport = rapportAnomalie.rapport, refAnomalies = refanomal.ToArray() };
ViewBag.codeAgence = new SelectList(db.Agences, "codeAgence", "intituleAgence", rapportAnomalie.rapport.codeAgence);
return View(rapport);
}
Any ideas what's wrong with it?
I think you are getting the problem because the lignesRapport field is not initialized in your model RapportAnomalie
Create a constructor and initialize lignesRapport . I believe the problem will go away.
public RapportAnomalie()
{
lignesRapport = new List <LigneRapportAnomalie>();
}
Good luck

Categories