How to render common form elements as a partial view - asp.net-mvc

I am learning ASP.NET Core MVC and have been playing around with various concepts.
My sample project involves creating an application that allows me to raise different types of requests. These requests, however, share handful of common fields and I would want to create a partial view to render these control instead of having to duplicate the rendering in every different type of request.
I have put a sample application in my VSTS. I have created a partial view shared across different request types but, I have lost all server side validation on these common fields. I would greatly appreciate any ideas on how to achieve a common partial view without losing the validation.
Here is a few snippets of my code, starting with my ViewModels
public class ComputerRequestCreateViewModel : BaseRequestViewModel
{
public ComputerRequest Model { get; set; }
public override BaseRequestModel BaseModel => Model;
}
public class ReplacementRequestCreateViewModel : BaseRequestViewModel
{
public ReplacementRequest Model { get; set; }
public override BaseRequestModel BaseModel => Model;
}
public class BaseRequestViewModel
{
public virtual BaseRequestModel BaseModel { get; }
//Common Lookups
}
my models:
public class ReplacementRequest : BaseRequestModel
{
[Required]
[MaxLength(15)]
public string AssetId { get; set; }
[Required]
[MaxLength(200)]
public string Reason { get; set; }
}
public class ReplacementRequest : BaseRequestModel
{
[Required]
[MaxLength(15)]
public string AssetId { get; set; }
[Required]
[MaxLength(200)]
public string Reason { get; set; }
}
public class ComputerRequest : BaseRequestModel
{
[Required]
[MaxLength(20)]
public string OS { get; set; }
[Required]
public string Memory { get; set; }
}
One of my Create View
#model SampleRepro.ViewModels.ComputerRequestCreateViewModel
<h1>Request a Computer</h1>
<form asp-route="savecomputerrequest">
#{ await Html.RenderPartialAsync("_RequestFormPartial", Model);}
<div class="row">
<div class="form-group col-md-6">
<label asp-for="Model.Memory" class="control-label"></label>
<span style="color:red"> *</span>
<input type="text" asp-for="Model.Memory" class="form-control" />
<span asp-validation-for="Model.Memory" class="text-danger"></span>
</div>
<div class="form-group col-md-6">
<label asp-for="Model.OS" class="control-label"></label>
<span style="color:red"> *</span>
<input type="text" asp-for="Model.OS" class="form-control" />
<span asp-validation-for="Model.OS" class="text-danger"></span>
</div>
</div>
<div class="row">
<div class="form-group">
<input type="submit" value="Save" class="btn btn-secondary mx-3" />
<a asp-page="/Index">Back to Home</a>
</div>
</div>
</form>
and my common partial view looks something like this:-
#model SampleRepro.ViewModels.BaseRequestViewModel
<div class="row">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group col-md-6">
<label asp-for="BaseModel.RequestOwner" class="control-label"></label>
<span style="color:red"> *</span>
<input asp-for="BaseModel.RequestOwner" readonly class="form-control" />
<span asp-validation-for="BaseModel.RequestOwner"></span>
</div>
<div class="form-group col-md-6">
<label asp-for="BaseModel.DueDate" class="control-label"></label>
<span style="color:red"> *</span>
<input asp-for="BaseModel.DueDate" class="form-control" id="DueDate" placeholder="dd/mm/yyyy" readonly />
<span asp-validation-for="BaseModel.DueDate"></span>
</div>
</div>

Related

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

How Can I Get ViewData in PartialView in Razor Pages

I'm Using Razor Pages For my App, in one part of my app I've used a partial view here is my codes;
public class Permission
{
[Key]
public int PermissionId { get; set; }
public string PermissionTitle { get; set; }
public int? ParentID { get; set; }
}
public class IndexModel : PageModel
{
public PartialViewResult OnGetCreateRole()
{
var ListPermission = permissionService.AllPermission();
return new PartialViewResult()
{
ViewName = "_PCreateRole", // partial's name
ViewData = new ViewDataDictionary<List<Permission>>(ViewData,
ListPermission)
};
}
}
ViewData is a List of Permission class and i've sent ViewData to partial but i dont know how to get ViewData, also my partial use another model, below is my partial:
#model ToMVC.DataLayer.Entities.User.Role
<div class="row">
<div class="col-md-12">
<form asp-page="CreateRole" method="post">
<div class="form-group">
<label class="control-label">Title</label>
<input asp-for="RoleTitle" class="form-control"/>
<p><span class="text-danger" asp-validation-for="RoleTitle"></span></p>
</div>
<div class="form-group">
<input type="submit" value="submit" class="btn btn-primary" />
</div>
//this part needs ViewData
#foreach (var item in ViewData)
{
}
</form>
</div>
</div>
I want to use ViewData in Foreach loop.
A better solution than ViewData would be to simply make a new ViewModel class containing all the information you need for a view.
public class UserRoleAndPermissions{
public UserRoleAndPermissions(){
Permissions = new List<Permissions>();
}
public List<Permission> Permissions {get;set;}
public ToMVC.DataLayer.Entities.User.Role Role {get;set;}
}
And your view
//check your namespace here - this is just an example
#model ToMVC.DataLayer.UserRoleAndPermissions
<div class="row">
<div class="col-md-12">
<form asp-page="CreateRole" method="post">
<div class="form-group">
<label class="control-label">Title</label>
<input asp-for="RoleTitle" class="form-control"/>
<p><span class="text-danger" asp-validation-for="RoleTitle"></span></p>
</div>
<div class="form-group">
<input type="submit" value="submit" class="btn btn-primary" />
</div>
#foreach (var item in Model.Permissions)
{
}
</form>
</div>
</div>

Asp validation decimal not binded correctly

I have a problem with the asp-validation.
I have a decimal field which I want to be between 0.00 and 1.00.
Here is my model :
public class Intent
{
public Guid Id { get; set; }
public Language Language_ { get; set; }
public Boolean Active { get; set; }
[Range(0.00, 1.00)]
public decimal Tolerance { get; set; }
public LuisApp LuisAppFr_ { get; set; }
public LuisApp LuisAppEn_ { get; set; }
public LuisApp LuisAppNl_ { get; set; }
public string UrlImage { get; set; }
}
Here is the signature of my post method:
public async Task<IActionResult> Create([Bind("Id,Active,Tolerance,UrlImage,Language_,Language_.TextEn,Language_.TextFr,Language_.TextNl")] Intent intent)
Here is a part of my Create View:
<form asp-action="Create">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<div class="checkbox">
<label>
<input asp-for="Active" /> #Html.DisplayNameFor(model => model.Active)
</label>
</div>
</div>
<div class="form-group">
<label asp-for="Tolerance" class="control-label"></label>
<input asp-for="#Model.Tolerance" class="form-control"/>
<span asp-validation-for="Tolerance" class="text-danger"></span>
</div>
...
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
Here is an image showing the value of my Tolerance field when it gets to the controller
And here is an image of my network request
Error Message I get
The binding seems to be good on the frontend but isn't in the backend.
Has anyone an idea of what my error could be ?
Thanks forward for your answer.
Sorry if it's a repost.
I solved my problem by adding this in my startup.cs :
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("en-US")
});

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.

Insert 1 parent row and many child rows 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>();
}
}

Resources