Insert 1 parent row and many child rows Asp.net MVC - asp.net-mvc

So I am creating a system where you can create forms and store them in the database which will be displayed for specific types of reports.
On a report you will be entering 1 row into the Report table with the default report data like report owner, submission date, status etc
On this same create page I would like to have all of the values from the created form that's stored in the DB, so far I have managed to get the displayed form to show correctly with the report.
Each input for the form in the DB will be 1 entry into the ReportValues table.
Currently I can get the Report from the Create View but the entries for ReportValue are not being returned to the Create Iaction.
Please help :/
Models:
public class Report
{
public Report()
{
//Set default Submission Date to the current date.
this.SubmissionDate = DateTime.Now;
this.Status = "New";
}
public int ID { get; set; }
[ForeignKey("Form")]
public int formID { get; set; }
[StringLength(5, MinimumLength = 3)]
public String Abreviation { get; set; }
[Display(Name = "Submitted By")]
public String Owner { get; set; }
[RegularExpression(#"^[A-Z]+[a-zA-Z''-'\s]*$")]
public String Category { get; set; }
public String Status { get; set; }
[DataType(DataType.Date), Display(Name = "Submit Date")]
public DateTime SubmissionDate { get; set; }
}
}
public class ReportValues
{
public int ID { get; set; }
[ForeignKey("Report")]
public int reportId { get; set; }
public String title { get; set; }
public String value { get; set; }
}
}
public class FormReportViewModel
{
public Report Report { get; set; }
public int reportID { get; set; }
public String formCode { get; set; }
public String abv { get; set; }
public String category { get; set; }
public IEnumerable<ReportValues> ReportValues { get; set; }
}
}
Create Iaction:
// POST: Reports/Create
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(FormReportViewModel formReportViewModel)
{
Report r = formReportViewModel.Report;
if (ModelState.IsValid)
{
_context.Report.Add(r);
_context.SaveChanges();
foreach (var item in formReportViewModel.ReportValues)
{
ReportValues rv = new ReportValues { reportId = r.ID, title = item.title, value = item.value };
_context.ReportValues.Add(rv);
_context.SaveChanges();
}
return RedirectToAction("Index");
}
return View(formReportViewModel);
}
View:
model IEnumerable<FormReportViewModel>
#using System.Security.Claims;
#{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<form asp-action="Create">
<div class="form-horizontal">
<h4>Report</h4>
<hr />
<div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="#Model.First().Report.Abreviation" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="#Model.First().Report.Abreviation" class="form-control" value="#Model.First().abv" readonly="readonly"/>
<span asp-validation-for="#Model.First().Report.Abreviation" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="#Model.First().Report.Category" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="#Model.First().Report.Category" class="form-control" value="#Model.First().category" readonly="readonly"/>
<span asp-validation-for="#Model.First().Report.Category" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="#Model.First().Report.Owner" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="#Model.First().Report.Owner" class="form-control" value=#User.GetUserName() readonly="readonly"/>
<span asp-validation-for="#Model.First().Report.Owner" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="#Model.First().Report.Status" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="#Model.First().Report.Status" class="form-control" value="New" readonly="readonly"/>
<span asp-validation-for="#Model.First().Report.Status" class="text-danger" />
</div>
</div>
#*Html.Raw(Model.First().formCode)*#
#*
The code below is from the Create ReportValues page
*#
<div class="form-group">
<label class="col-md-2 control-label" for="title">title</label>
<div class="col-md-10">
<input class="form-control" type="text" id="title" name="title" value="Animal Name" />
<span class="text-danger field-validation-valid" data-valmsg-for="title" data-valmsg-replace="true" />
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="value">value</label>
<div class="col-md-10">
<input class="form-control" type="text" id="value" name="value" value="" />
<span class="text-danger field-validation-valid" data-valmsg-for="value" data-valmsg-replace="true" />
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="title">title</label>
<div class="col-md-10">
<input class="form-control" type="text" id="title" name="title" value="Animal Weight" />
<span class="text-danger field-validation-valid" data-valmsg-for="title" data-valmsg-replace="true" />
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="value">value</label>
<div class="col-md-10">
<input class="form-control" type="text" id="value" name="value" value="" />
<span class="text-danger field-validation-valid" data-valmsg-for="value" data-valmsg-replace="true" />
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="title">title</label>
<div class="col-md-10">
<input class="form-control" type="text" id="title" name="title" value="Animal Colour" />
<span class="text-danger field-validation-valid" data-valmsg-for="title" data-valmsg-replace="true" />
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="value">value</label>
<div class="col-md-10">
<input class="form-control" type="text" id="value" name="value" value="" />
<span class="text-danger field-validation-valid" data-valmsg-for="value" data-valmsg-replace="true" />
</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>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>

From the comments: you have a NRE in FormReportViewModel, ReportValues is null.
Change IEnumerable<ReportValues> to List<ReportValues>, add a constructor in FormReportViewModel and create an instance of ReportValues
public class FormReportViewModel
{
public Report Report { get; set; }
public int reportID { get; set; }
public String formCode { get; set; }
public String abv { get; set; }
public String category { get; set; }
public List<ReportValues> ReportValues { get; set; }
public FormReportViewModel()
{
ReportValues=new List<ReportValues>();
}
}

Related

.NET 6 Kendo UI form validations using kendo-rules attribute

I am new to kendo UI. Trying to validate my form using custom rules with kendo-rules attributes. I am referring to this link https://demos.telerik.com/aspnet-core/validator . The custom rules are working but somehow the validation message is getting triggered on different controls.
I am trying to set the custom rule on my "FirstName" field. If "FirstName" field has value less than 5 characters then, validation message "First name cannot be less than 5 characters" should come, for "FirstName" field.
However, I am getting the validation messages on different controls. Refer to the snapshot below.
The expected behaviour is , first required field error should come and then if the user enters first name value less than 5 characters then this "First name cannot be less than 5 characters" error should come.
Here is my code:
Create.cshtml
#model KendoFormValidation_Demo.Models.Person
#{
ViewData["Title"] = "Create";
}
#{
var messages = new Dictionary<string, string>() { { "custom", "First name cannot be less than 5 characters" } };
var rules = new Dictionary<string, string>() { { "custom", "customFunction" } };
}
<div class="row">
<div class="col-md-4">
<form id="PersonForm" kendo-validator="true" kendo-messages="messages" kendo-rules="rules">
<div class="form-group">
<label asp-for="FirstName"></label>
<input asp-for="FirstName" class="form-control" />
<span class="text-danger k-invalid-msg" data-for="FirstName"></span>
</div>
<div class="form-group">
<label asp-for="LastName"></label>
<input asp-for="LastName" class="form-control" />
<span asp-validation-for="LastName" class="text-danger k-invalid-msg" data-for="LastName"></span>
</div>
<div class="form-group">
<label asp-for="Age"></label>
<input class="form-control" for="Age" />
<span asp-validation-for="Age" class="text-danger k-invalid-msg" data-for="Age"></span>
</div>
<div class="form-group">
<label asp-for="Address"></label>
<input asp-for="Address" class="form-control" />
<span asp-validation-for="Address" class="text-danger k-invalid-msg" data-for="Address"></span>
</div>
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger k-invalid-msg" data-for="Email"></span>
</div>
<div class="form-group">
<label asp-for="Phone"></label>
<input asp-for="Phone" class="form-control" />
<span asp-validation-for="Phone" class="text-danger k-invalid-msg" data-for="Phone"></span>
</div>
<div class="form-group">
<label asp-for="Dob"></label>
<input asp-for="Dob" class="form-control kendo-date-picker" />
<span asp-validation-for="Dob" class="text-danger k-invalid-msg" data-for="Dob"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="k-button k-button-md k-rounded-md k-button-solid-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index" class="k-button k-button-md k-rounded-md k-button-solid">Back to List</a>
</div>
<script>
function customFunction(input) {
debugger;
return input.attr('name') === "FirstName" && input.length<5;
}
$(document).ready( function () {
$(".kendo-date-picker").each(function(){
$(this).kendoDatePicker({
format: "MM/dd/yyyy",
dateInput: true,
value: $(this).val()
}).data('kendoDatePicker')._dateInput.setOptions({
messages:{
"year": "yyyy",
"month": "mm",
"day": "dd"
}
});
});
var validator = $("#PersonForm").data("kendoValidator");
$("form").submit(function(event) {
event.preventDefault();
if (validator.validate()) {
alert("Success");
} else {
alert("fail");
}
});
});
</script>
Person.cs
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
[DataType(DataType.Date)]
public DateTime Dob { get; set; }
}
I am using .Net 6 and Telerik version: ASP.NET Core R2 2022 SP1
Can anybody help me on this? Did I miss anything here.
Thank You

validation error duplication in both forms

I've got two partial views, each contains a form. When i submit either of them, validation error appears as a duplicate in both partials. What am I missing, or probably have a double of.
I had to move each form in a separate partial view in order to give each of them its own Model.
My main view:
#inject Microsoft.Extensions.Localization.IStringLocalizer Localizer
#model LoginRegisterViewModel
#{
Layout = "_Layout_";
}
#if (Model.LoginViewModel.EnableLocalLogin)
{
<div class="loginRegister">
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header loginpage">
<main class="fullHeight">
<div class="flexValign" id="overview">
<section class="section--center mdl-grid mdl-grid--no-spacing mdl-shadow--8dp roundedWrapper">
#Html.Partial("_LoginPartial", Model.LoginViewModel)
#Html.Partial("_RegisterPartial", Model.RegisterViewModel)
</section>
</div>
</main>
</div>
</div>
}
my partials:
#inject Microsoft.Extensions.Localization.IStringLocalizer Localizer
#model RegisterViewModel
<div class="mdl-card mdl-cell mdl-cell--6-col-desktop mdl-cell--6-col-tablet mdl-cell--4-col-phone darkBckrnd">
#using (Html.BeginForm("Register", "Account", FormMethod.Post))
{
<div class="fixedHeight mdl-grid mdl-card__supporting-text mdl-typography--text-center mdl-color-text--white">
<div class="innerWrapper">
#await Html.PartialAsync("_InputValidation")
<input type="hidden" asp-for="RegisterReturnUrl" />
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input type="password" class="mdl-textfield__input" asp-for="NewPassword" autocomplete="new-password">
<label class="mdl-textfield__label mdl-color-text--white" for="Password">#Localizer["password"]
&ast;</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input type="password" autocomplete="off" class="mdl-textfield__input" asp-for="NewPasswordAgain">
<label class="mdl-textfield__label mdl-color-text--white"
for="PasswordAgain">#Localizer["repeatPassword"]
&ast;</label>
</div>
</div>
</div>
<div class="btnContainer">
<button type="submit" value="register" name="button"
class="general mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--cyan-500 mdl-shadow--8dp"
id="RegisterButton">#Localizer["createAccount"]</button>
</div>
}
the other partial:
#inject Microsoft.Extensions.Localization.IStringLocalizer Localizer
#model LoginViewModel
<div class="mdl-card mdl-cell mdl-cell--6-col-desktop mdl-cell--6-col-tablet mdl-cell--4-col-phone white">
#using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
<div
class="fixedHeight mdl-grid mdl-card__supporting-text mdl-typography--text-center mdl-color-text--blue-grey-900">
<div class="innerWrapper">
<partial name="_InputValidation" />
<input type="hidden" asp-for="ReturnUrl" />
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" asp-for="Username">
<label class="mdl-textfield__label mdl-color-text--blue-grey-600"
for="Username">#Localizer["userNameOrEmail"]</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input type="password" class="mdl-textfield__input" asp-for="Password" autocomplete="off">
<label class="mdl-textfield__label mdl-color-text--blue-grey-600"
for="Password">#Localizer["password"]</label>
</div>
</div>
</div>
<div class="btnContainer">
<button type="submit" value="login" name="button"
class="general mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--cyan-500">
#Localizer["login"]</button>
</div>
}
Models:
using System;
using System.Collections.Generic;
using System.Linq;
namespace IdentityServer4.Quickstart.UI
{
public class LoginViewModel : LoginInputModel
{
public bool AllowRememberLogin { get; set; } = true;
public bool EnableLocalLogin { get; set; } = true;
public string LoginPage { get; set; } = "Login";
public IEnumerable<ExternalProvider> ExternalProviders { get; set; } = Enumerable.Empty<ExternalProvider>();
public IEnumerable<ExternalProvider> VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName));
public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1;
public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;
}
}
second model
using IdentityServer.DTOs;
using IdentityServer.Models;
namespace IdentityServer4.Quickstart.UI
{
public class RegisterViewModel
{
public string Email { get; set; }
public string NewPassword { get; set; }
public string NewPasswordAgain { get; set; }
public string RegisterReturnUrl { get; set; }
}
then two Models united. I have united these two models to cover them both in controller.
using System;
using System.Collections.Generic;
using System.Linq;
namespace IdentityServer4.Quickstart.UI
{
public class LoginRegisterViewModel
{
public LoginViewModel LoginViewModel { get; set; }
public RegisterViewModel RegisterViewModel { get; set; }
}
}
and controller:
if (ModelState.IsValid)
{
var user = await _userManager.FindByNameAsync(model.Username);
if (await _userManager.CheckPasswordAsync(user, model.Password))
{
var performAdditionalCheck = true;
// If the user has unknown provider let him pass
if (user.Provider == UserAuthentificationProvider.Unknown) performAdditionalCheck = false;
if (context != null)
{
var client = await _clientStore.FindEnabledClientByIdAsync(context.ClientId);
if (client.Properties["forceAuthentification"] == "false") performAdditionalCheck = false;
}
if (performAdditionalCheck)
{
return await RedirectToAuth(model);
}
else
{
return await SignInUserWithModel(user, model);
}
}
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId: context?.ClientId));
ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
}
// something went wrong, show form with error
var vm = await BuildLoginRegisterViewModelAsync(model);
return View(vm.LoginViewModel.LoginPage, vm);
}
I've got two partial views, each contains a form. When i submit either of them, validation error appears as a duplicate in both partials.
You can refer to the following sample code snippet and this doc about "Client-side validation" to valid user inputs within multiple partial views.
Main View
#model LoginRegisterViewModel
#{
ViewData["Title"] = "LoginRegister";
}
<h1>LoginRegister</h1>
#await Html.PartialAsync("_LoginPartial", Model.LoginViewModel)
#await Html.PartialAsync("_RegisterPartial", Model.RegisterViewModel)
#section scripts{
<partial name="_ValidationScriptsPartial" />
}
_LoginPartial.cshtml
#model LoginViewModel
#using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Username" class="control-label"></label>
<input asp-for="Username" class="form-control" />
<span asp-validation-for="Username" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="login" class="btn btn-primary" />
</div>
}
_RegisterPartial.cshtml
#model RegisterViewModel
#using (Html.BeginForm("Register", "Account", FormMethod.Post))
{
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NewPassword" class="control-label"></label>
<input asp-for="NewPassword" class="form-control" />
<span asp-validation-for="NewPassword" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NewPasswordAgain" class="control-label"></label>
<input asp-for="NewPasswordAgain" class="form-control" />
<span asp-validation-for="NewPasswordAgain" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="CreateAccount" class="btn btn-primary" />
</div>
}
Test Model Classes
public class LoginViewModel
{
[Required]
public string Username { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
}
public class RegisterViewModel
{
[Required]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string NewPassword { get; set; }
[Compare("NewPassword")]
[DataType(DataType.Password)]
public string NewPasswordAgain { get; set; }
}
Test Result

MVC Core. Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions

I am passing in my view this model
public class BlogViewModel
{
public List<CommentModel> commentModels { get; set; }
public BlogPostLayoutModel blogPostLayoutModel { get; set; }
public CommentModel commentModel { get; set; }
public int pageNumber { get; set; }
}
CommentModel class
public class CommentModel
{
public int IDComment { get; set; }
public int IDPost { get; set; }
[Required()]
public string Username { get; set; }
[Required()]
public string Content { get; set; }
public static CommentModel CommentToCommentModel(Comment comment)
{
CommentModel commentModel = new CommentModel();
commentModel.IDComment = comment.IDComment;
commentModel.IDPost = comment.IDPost;
commentModel.Username = comment.Username;
commentModel.Content = comment.Content;
return commentModel;
}
public static List<CommentModel> CommentsToCommentModels(List<Comment> comments)
{
List<CommentModel> commentModels = new List<CommentModel>();
foreach (var comment in comments)
{
CommentModel commentModel = new CommentModel();
commentModel.IDComment = comment.IDComment;
commentModel.IDPost = comment.IDPost;
commentModel.Username = comment.Username;
commentModel.Content = comment.Content;
commentModels.Add(commentModel);
}
return commentModels;
}
}
And my view, where the error is thrown (fifth line)
<form asp-action="AddComment">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
#{ var pageNumber = Model.pageNumber;
#Html.HiddenFor(x => pageNumber)
int IDPost = Model.blogPostLayoutModel.IDPost;
#Html.HiddenFor(x => x.commentModel.IDPost == IDPost)
}
<div class="row">
<div class="form-group col-md-4">
<label asp-for="commentModel.Username" class="control-label"></label>
<input asp-for="commentModel.Username" class="form-control" />
<span asp-validation-for="commentModel.Username" class="text-danger"></span>
</div>
</div>
<div class="row">
<div class="form-group col-md-12">
<label class="control-label">Comment</label>
<textarea asp-for="commentModel.Content" class="form-control"></textarea>
<span asp-validation-for="commentModel.Content" class="text-danger"></span>
</div>
<div class="form-group col-md-4">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</form>
I have searched for the error, but seems like it's mostly people trying to return a value from a method and getting told to pass the value to a local variable and then put that local variable inside the tag helper, but that doesn't seem to be the case here.
And also blogPostLayoutModel.IDPost is defined as
public int IDPost { get; set; }
EDIT: My commentModel was null, so that was the problem.
Working form
<form asp-action="AddComment">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
#{
#Html.HiddenFor(x => Model.pageNumber)
Model.commentModel.IDPost = Model.blogPostLayoutModel.IDPost;
#Html.HiddenFor(x => x.commentModel.IDPost)
}
<div class="row">
<div class="form-group col-md-4">
<label asp-for="commentModel.Username" class="control-label"></label>
<input asp-for="commentModel.Username" class="form-control" />
<span asp-validation-for="commentModel.Username" class="text-danger"></span>
</div>
</div>
<div class="row">
<div class="form-group col-md-12">
<label class="control-label">Comment</label>
<textarea asp-for="commentModel.Content" class="form-control"></textarea>
<span asp-validation-for="commentModel.Content" class="text-danger"></span>
</div>
<div class="form-group col-md-4">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</form>

MVC Url.Action causes NullReferenceException in post

I'm trying to have a button on my form page that takes me back to the previous view that requires a parameter, I'm passing a ViewModel into the view with the assigned value I'm using. If the button is un-commented the button works fine but the forms post sends a NullReferenceException, and if the button is commented the form works exactly as I want.
The button that breaks the form
<button type="button" onclick="location.href='#Url.Action("Assignments","Session", new { Model.CourseName })'">Go Back</button>
The Controller Code
public IActionResult CreateAssignment(string courseName)
{
CreateAssignmentModel assignmentModel = new CreateAssignmentModel();
assignmentModel.CourseName = courseName;
return View(assignmentModel);
}
[HttpPost]
public IActionResult CreateAssignment(CreateAssignmentModel assignment)
{
if (ModelState.IsValid)
{
ModelState.Clear();
return View(assignment.CourseName);
}
else
{
return View(assignment.CourseName);
}
}
public IActionResult Assignments(string courseName)
{
var assignments = storedProcedure.getAssignments(User.Identity.Name, courseName);
var AssignmentsView = new AssignmentsViewModel{CourseName = courseName};
foreach (var Assignment in assignments.ToList())
{
AssignmentsView.Assignments.Add(Assignment);
}
return View(AssignmentsView);
}
The Model Code
public class CreateAssignmentModel
{
public string UserName { get; set; }
public string CourseName { get; set; }
[Required]
public string AssignmentName { get; set; }
[Required]
public string AssignmentDescription { get; set; }
[Required]
public int TotalPoints { get; set; }
[Required]
public DateTime DueDate { get; set; }
}
The Form with Button
<button type="button" onclick="location.href='#Url.Action("Assignments","Session", new { Model.CourseName })'">Go Back</button>
<div class="row">
<div class="col-md-4">
<form asp-route-returnUrl="#ViewData["ReturnUrl"]" method="post">
<h4>Create an Assignment</h4>
<hr />
<div class="form-group">
<label asp-for="AssignmentName" class="control-label">Assignment Name</label>
<input asp-for="AssignmentName" class="form-control" placeholder="Assignment Name" />
<span asp-validation-for="AssignmentName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="AssignmentDescription" class=" control-label">Assignment Description</label>
<input asp-for="AssignmentDescription" class="form-control" placeholder="Assignment Description" />
<span asp-validation-for="AssignmentDescription" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TotalPoints" class=" control-label">Total Points</label>
<input asp-for="TotalPoints" class="form-control" placeholder="Points" />
<span asp-validation-for="TotalPoints" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DueDate" class=" control-label">Due Date</label>
<input asp-for="DueDate" class="form-control" placeholder="Due Date" />
<span asp-validation-for="DueDate" class="text-danger"></span>
</div>
<br />
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</div>
Sorry for the lack of brevity, I've looked at NullReferenceException solutions for my problem but none have worked.

How to add ICollection object to Create View Model MVC

My scenario is:
I have a class called "CarService" as below:
public class CarService
{
public int CarId { get; set; }
public Car Car { get; set; }
public int ServiceId { get; set; }
public Person Service { get; set; }
public DateTime ServiceEntryDate { get; set; }
public DateTime ServiceExitDate { get; set; }
public ICollection <CarServiceAction> CarServiceActions { get; set; }
}
this class has a collection "ICollection <CarServiceAction> CarServiceActions"
the CarServiceActions is as below:
public class CarServiceAction
{
public int CarServiceId { get; set; }
public CarService CarService { get; set; }
public float Value { get; set; }
}
the problem is when I create the controller with views using Entity Framework it allows me to add all fields of CarService but there is no any data entry form for collection ICollection <CarServiceAction> CarServiceActions
This is my create view generated from controller:
#model RentaCar.Models.Instances.CarService
#{
Layout = null;
ViewData["Title"] = " ";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Create</title>
</head>
<body>
<form asp-action="Create">
<div class="form-horizontal">
<h4>CarService</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="CarId" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="CarId" class="form-control" asp-items="ViewBag.CarId"></select>
</div>
</div>
<div class="form-group">
<label asp-for="ServiceId" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="ServiceId" class="form-control" asp-items="ViewBag.ServiceId"></select>
</div>
</div>
<div class="form-group">
<label asp-for="ServiceEntryDate" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ServiceEntryDate" class="form-control" />
<span asp-validation-for="ServiceEntryDate" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="ServiceExitDate" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ServiceExitDate" class="form-control" />
<span asp-validation-for="ServiceExitDate" class="text-danger"></span>
</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>
</form>
</body>
</html>
The question is how can I add details of CarServiceAction by click an "adddetail" button.
Thanks for your help.
In fact I want to be something like this:
<div class="form-group">
<label asp-for="CarService.CarServiceAction.CarServiceId" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="CarService.CarServiceAction.CarServiceId" class="form-control" />
</div>
</div>
<div class="form-group">
<label asp-for="ServiceEntryDate" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="CarService.CarServiceAction.Value" class="form-control" />
<span asp-validation-for="CarService.CarServiceAction.Value" class="text-danger"></span>
</div>
<input value="add new service action" class="btn btn-default" />
</div>

Resources