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
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
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"]
*</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"]
*</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
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>
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.
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>