Insert a combobox inside view in .NET Core - c#

I have a view page to insert some data.
here is the model:
#model BookListMVC.Models.Book
I need to insert a combobox linked to another table "Categories".
The compiler does not allow me to insert multiple models because that is probably not the right way.
How I can insert a combobox linked to "Categories" that point to book "IdCategory" ?
Here the actual code full inside:
#model BookListMVC.Models.Book
<br />
<h2 class="text-info">#(Model.Id!=0 ? "Edit" : "Create") Book</h2>
<br />
<div class="border container" style="padding:30px;">
<form method="post">
#if (Model.Id != 0)
{
<input type="hidden" asp-for="Id" />}
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<div class="form-group row">
<div class="col-3">
<label asp-for="Name"></label>
</div>
<div class="col-6">
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<div class="col-3">
<label asp-for="Author"></label>
</div>
<div class="col-6">
<input asp-for="Author" class="form-control" />
<span asp-validation-for="Author" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<div class="col-3">
<label asp-for="ISBN"></label>
</div>
<div class="col-6">
<input asp-for="ISBN" class="form-control" />
<span asp-validation-for="ISBN" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<div class="col-3">
<label asp-for="ISBN"></label>
</div>
<div class="col-6">
<input asp-for="ISBN" class="form-control" />
<span asp-validation-for="ISBN" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<div class="col-3 offset-3">
<button type="submit" class="btn btn-primary form-control">
#(Model.Id != 0 ? "Update" : "Create")
</button>
</div>
<div class="col-3">
<a asp-action="Index" class="btn btn-success form-control">Back to List</a>
</div>
</div>
</form>
</div>

You can insert the combobox model through ViewBag or ViewData. For example.
public IActionResult Index()
{
//The data can be obtained from database.
ViewBag.Categories = new List<SelectListItem>
{
new SelectListItem{ Text="history", Value="1"},
new SelectListItem{ Text="literature", Value="2"},
};
var model = new Book { Id = 2, Author="author", ISBN="isbn", Name="bookname" };
return View(model);
}
This is the simple combobox in the view.
<div class="form-group row">
<div class="col-3">
<label asp-for="categories"></label>
</div>
<div class="col-6">
<select asp-for="categories" name="CategoryId" asp-items="ViewBag.Categories">
<option>-- select the category --</option>
</select>
<span asp-validation-for="categories" class="text-danger"></span>
</div>
</div>
Model (Categories)
public class Categories
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
Result
You can add a property CategoryId in model Book, even add a property Categories.
public class Book
{
public int CategoryId { get; set; }
public Categories categories { get; set; }
}
If you want to pass the object Categories to the bakend, you can add a hidden input box and relative javascript.
Add hidden box.
<div class="form-group row">
<div class="col-3">
<label asp-for="categories"></label>
</div>
<div class="col-6">
<select onchange="changeName()" asp-for="categories" name="categories.CategoryId" asp-items="ViewBag.Categories">
<option>-- select the category --</option>
</select>
<input type="hidden" name="categories.CategoryName" value="" id="categoryName"/>
<span asp-validation-for="categories" class="text-danger"></span>
</div>
</div>
Add javascript.
#section Scripts{
<script>
function changeName() {
var index = document.getElementById("categories").selectedIndex;
var text = document.getElementById("categories").options[index].text;
document.getElementById("categoryName").value=text
}
</script>
}
Then you can get all data include Categories and can handling Categories table.

Related

Foreign Key asp.net core with postgress

I have this file upload form
#model FileUploadViewModel
#{
ViewData["Title"] = "Index";
}
<h4>Start Uploading Files Here</h4>
<hr />
#if (ViewBag.Message != null)
{
<div class="alert alert-success alert-dismissible" style="margin-top:20px">
#ViewBag.Message
</div>
}
<form enctype="multipart/form-data" asp-controller="files" asp-action="UploadToFileSystem" method="post">
<div class="form-group row">
<label asp-for="Name" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Name" class="form-control" placeholder="name" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="Author" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Author" class="form-control" placeholder="Author" />
<span asp-validation-for="Author" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="Genre" class="col-sm-2 col-form-label"> </label>
<div class="col-sm-10">
<select asp-for="Genre" class="custom-select mr-sm-2" asp-items="Html.GetEnumSelectList<Genres>()" ></select>
</div>
</div>
<div class="form-group row">
<label asp-for="Description" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Description" class="form-control" placeholder="Description" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
</div>
<div class="form-group row " >
<label asp-for="PublishedOn" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input type="date" asp-for="PublishedOn" class="form-control" placeholder="Publishing Date" />
<span asp-validation-for="PublishedOn" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="Files" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<div class="custom-file">
<input asp-for="Files" multiple type="file" class="form-control custom-file-input" placeholder="file" />
<label class="custom-file-label">Chose File...</label>
<span asp-validation-for="Files" class="text-danger"></span>
</div>
</div>
</div>
<button class="btn btn-success" type="submit" asp-action="UploadToFileSystem" asp-controller="Files">Upload</button>
</form>
#section Scripts{
<script>
$(document).ready(function () {
$('.custom-file-input').on("change", function () {
var fileLabel = $(this).next('.custom-file-label');
var files = $(this)[0].files;
if (files.length > 1) {
fileLabel.html(files.length + 'files selected');
}
else if (files.length == 1) {
fileLabel.html(files[0].name);
}
});
});
</script>
}
I want to make dropdown list with this table from postgresql database
FileTypes table in pgadmin
And i have this table for genres in database
Genres table in pgadmin
So if i pick FileType with ID=1 in first dropdown,in the second dropdown i want to show only genres with with FileTypeID=1,I try to fill the genres table manualy but i have error(will be posted below).Any help for this way,or other way to filter genres dropdown depends on file type selected in first dropdown.Error trying to fill rows in Genre table
Based on that error, you didn't create a foreign key but a unique index on that column in the Genre table. They prefix IX for index and FK for foreign keys by default I believe. Check your table relationships and check IX_genres_FileTypesID and I am pretty sure you will see the relationship isn't there.

Disable other form inputs in ASP.NET Core MVC (C#)

I'm using ASP.NET Core MVC and don't know how validate my form properly.
I want to disable my other form inputs if one gets filled. If the user decides to delete his input all elements should be enabled again.
Here's my code:
<form enctype="multipart/form-data" asp-controller="certificate" asp-action="index" method="post" class="mt-3">
<div class="form-group row">
<label asp-for="Hostname" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Hostname" class="form-control" placeholder="Hostname">
<span asp-validation-for="Hostname" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="Content" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<textarea asp-for="Content" class="form-control" placeholder="Copy your File-Content here" id="content"></textarea>
<span asp-validation-for="Content" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="FileDirectory" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<div class="custom-file">
<input asp-for="FileDirectory" accept=".pem, .der" class="form-control custom-file-input">
<label class="custom-file-label">Choose File...</label>
</div>
</div>
</div>
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group row">
<div class="col-sm-12">
<input type="submit" class=" float-right" value="Next"/>
</div>
</div>
</form>
Please let me know if you have any solution.
Do you mean you want to disable other inputs when the input you filled is not valid?If so,here is a demo:
Model:
public class ValidationModel1
{
[Required]
public string Hostname { get; set; }
[Required]
public string Content { get; set; }
public IFormFile FileDirectory { get; set; }
}
View:
<form enctype="multipart/form-data" method="post" class="mt-3" id="myform">
<div class="form-group row">
<label asp-for="Hostname" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Hostname" class="form-control" placeholder="Hostname" onblur="check(this)">
<span asp-validation-for="Hostname" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="Content" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<textarea asp-for="Content" class="form-control" placeholder="Copy your File-Content here" id="content" onblur="check(this)"></textarea>
<span asp-validation-for="Content" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="FileDirectory" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<div class="custom-file">
<input asp-for="FileDirectory" accept=".pem, .der" class="form-control custom-file-input">
<label class="custom-file-label">Choose File...</label>
</div>
</div>
</div>
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group row">
<div class="col-sm-12">
<input type="submit" class=" float-right" value="Next" />
</div>
</div>
</form>
js($("#myform").valid() will validate the form.):
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script>
function check(t) {
var id = $(t).attr("Id");
$("#myform").valid()
if (document.getElementById(id).classList.contains("input-validation-error")) {
$(".form-control").each(function () {
if ($(this).attr("Id") != id) {
$(this).attr("disabled", "disabled");
}
})
} else {
$(".form-control").each(function () {
$(this).removeAttr("disabled");
})
}
}
</script>
result:
Update:
js:
function check(t) {
var id = $(t).attr("Id");
//$("#myform").valid()
if ($(t).val() != "") {
$(".form-control").each(function () {
if ($(this).attr("Id") != id) {
$(this).attr("disabled", "disabled");
}
})
} else {
$(".form-control").each(function () {
$(this).removeAttr("disabled");
})
}
}
result:

DateTime default value ASP.net core

For a student project, I want to add default value - in the date field(ReleaseDate) but still have a calendar and the option of choosing a date.
My code in Models/Post.cs:
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode =true, DataFormatString = "{0: yyyy-MM-dd}")]
public System.DateTime ReleaseDate { get; set; }
And in View/Posts/Create.cshtml:
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
I try timur but
Controllers/PostController.cs
Is see only one define of index:
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
And your code:
public IActionResult Index()
{
var model = new Post()
{
ReleaseDate = DateTime.Today
};
return View("View", model);
}
I try to put like that
But there is an error (on https://localhost:numbers/Posts
Views/Posts/Create.cshtml
#model Portal.Models.Post
#{
ViewData["Title"] = "Create -";
}
<h1>Create</h1>
<h4>Post</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
And Views/Posts/Index.cshtml
#model IEnumerable<Portal.Models.Post>
#{
ViewData["Title"] = "Job Rice -";
}
<!-- Image -->
<section>
<div class="container">
<div class="full-width-image">
<img src="img/background.jpg" alt="">
</div>
</div>
</section>
<div class="text-center">
<h1><a asp-action="Create">Create new offer</a></h1>
</div>
#foreach (var item in Model)
{
<section>
<div class="container">
<!-- Heading -->
<div class="my-5"> </div>
<!-- Grid row -->
<div class="row">
<!-- Grid column -->
<div class="col-sm-12 sm-12">
<!-- Card -->
<div class="card">
<div class="card-header text-center colores">
<h4> <i class="fas fa-poll-h"></i> <a asp-action="Details" asp-route-id="#item.Id"> #Html.DisplayFor(modelItem => item.Title) </a></h4>
</div>
<!-- Card content -->
<form class="card-body">
<div class="row">
<div class="col-sm-12">
<div class="text-center"> #Html.DisplayFor(modelItem => item.Description)</div>
<div class="float-right"> #Html.DisplayFor(modelItem => item.ReleaseDate)</div>
</div>
<div>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a>
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
}
As Tieson T. points in his comment, you have to add the "value" attribute to the "input" tag in your razor page:
<input asp-for="ReleaseDate" class="form-control" value="#DateTime.Today.ToString("yyyy-MM-dd")" />
Of course, you can replace "DateTime.Today" with something else.
It doesn't matter that your browser shows the date in different format, you have to use this one inside the value attribute. I just tested it in an ASP.NET Core 3.1 Razor app and it works.
This should instantiate a default value:
public System.DateTime ReleaseDate { get; set; } = System.DateTime.Today;
alternatively if you need time as well
public System.DateTime ReleaseDate { get; set; } = System.DateTime.Now;
Since Razor views still allow you write html, you could try to define yours as
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" value="#Model.ReleaseDate.ToString("yyyy-MM-dd")" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
it should render the current model value as starting point for your input, of course you need to define one before passing it down onto a view:
public IActionResult Index()
{
var model = new Post()
{
ReleaseDate = DateTime.Today
};
return View("View", model);
}
You can use the following Razor syntax for this purpose.
<input type="date" asp-for="ReleaseDate" class="form-control" value=#DateTime.Today.ToString("yyyy-MM-dd") />
You just have to put type=date.

Error in form POST: Model bound complex types must not be abstract or value types and must have a parameterless constructor

I'm getting an error while running my project and sending a POST through my Register.cshtml View. See the error below:
InvalidOperationException: Could not create an instance of type 'AdoteRJ.Models.Adotante'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the 'model' parameter a non-null default value.
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext bindingContext)
This error started happenning after I refactored MyEntity class (Adotante), adding some complex types, in order to make it a rich domain. For some reason I have not discovered yet, this error started and the POST gets an error 500, although the Form Data is successfully filled (I checked it on dev tools' headers)
I'm using .NET Core 2.1
Also, I found this question below, with the same problem, but it's answer does not resolve it - if you add an empty constructor, the error disappears, but the form is sent empty...
Model bound complex types must not be abstract or value types and must have a parameterless constructor
My code:
public class Adotante : Entity
{
public Adotante(
Email email,
string senha,
NomeCompleto nomeCompleto,
string foto,
Lar lar
)
{
Email = email;
Senha = senha;
NomeCompleto = nomeCompleto;
Foto = foto;
Lar = lar;
}
public Email Email { get; private set; }
[DataType(DataType.Password)]
[StringLength(100, MinimumLength = 6)]
public string Senha { get; private set; }
public NomeCompleto NomeCompleto { get; private set; }
public string Foto { get; private set; }
public Lar Lar { get; private set; }
#region Adotante Métodos
public void SetEmail(Email email)
{
email = this.Email;
}
#endregion
}
An example of one of my ValueObject classes:
public class Email : ValueObject
{
public Email() { }
public Email(string enderecoEmail)
{
EnderecoEmail = enderecoEmail;
}
[Display(Name = "E-Mail")]
[Required(ErrorMessage = "Por favor, insira o e-mail do usuário/adotante")]
[EmailAddress]
public string EnderecoEmail { get; private set; }
}
}
The form on my Register.cshtml class:
<div class="row">
<form asp-controller="Account" asp-action="Register" asp-route-returnurl="#ViewData["ReturnUrl"]" method="post" class="form-horizontal">
<div class="col-md-1">
<!-- Gap between columns -->
</div>
<div class="col-md-4">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">email</i></span>
<div class="form-line">
<input asp-for="Email.EnderecoEmail" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="Senha" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">lock</i></span>
<div class="form-line">
<input asp-for="Senha" class="form-control" />
<span asp-validation-for="Senha" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="NomeCompleto" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">person</i></span>
<div class="form-line">
<input asp-for="NomeCompleto.Nome" class="form-control" />
<span asp-validation-for="NomeCompleto" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="Foto" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">insert_photo</i></span>
<div class="form-line">
<input asp-for="Foto" class="form-control" />
<span asp-validation-for="Foto" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="Lar.RendaMensal" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">attach_money</i></span>
<div class="form-line">
<input asp-for="Lar.RendaMensal" class="form-control date" />
<span asp-validation-for="Lar.RendaMensal" class="text-danger"></span>
</div>
<span class="input-group-addon">,00</span>
</div>
</div>
<div class="form-group">
<input type="submit" value="Finalizar Cadastro" class="btn btn-primary btn-lg" />
</div>
</div>
<div class="col-md-1">
<!-- Gap between columns -->
</div>
<div class="col-md-4">
<div class="form-group">
<label asp-for="Lar.PessoasNaCasa" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">home</i></span>
<div class="form-line">
<input asp-for="Lar.PessoasNaCasa" class="form-control" />
<span asp-validation-for="Lar.PessoasNaCasa" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="Lar.MetragemCasa" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">home</i></span>
<div class="form-line">
<input asp-for="Lar.MetragemCasa" class="form-control" />
<span asp-validation-for="Lar.MetragemCasa" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="Lar.TipoLar" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">home</i></span>
<div class="form-line">
<select asp-for="Lar.TipoLar" asp-items="Html.GetEnumSelectList<TipoLar>()">
<option value="" selected disabled hidden>Selecione</option>
</select>
<span asp-validation-for="Lar.TipoLar" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="Lar.CasaComTela" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">home</i></span>
<div class="form-line">
<select asp-for="Lar.CasaComTela" asp-items="Html.GetEnumSelectList<CasaComTela>()">
<option value="" selected disabled hidden>Selecione</option>
</select>
<span asp-validation-for="Lar.CasaComTela" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="Lar.TemCriancas" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">home</i></span>
<div class="form-line">
<select asp-for="Lar.TemCriancas" asp-items="Html.GetEnumSelectList<TemCriancas>()">
<option value="" selected disabled hidden>Selecione</option>
</select>
<span asp-validation-for="Lar.TemCriancas" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="Lar.TemAnimais" class="control-label"></label>
<div class="input-group">
<span class="input-group-addon"><i class="material-icons">home</i></span>
<div class="form-line">
<select asp-for="Lar.TemAnimais" asp-items="Html.GetEnumSelectList<TemAnimais>()">
<option value="" selected disabled hidden>Selecione</option>
</select>
<span asp-validation-for="Lar.TemAnimais" class="text-danger"></span>
</div>
</div>
</div>
</div>
</form>
</div>
Using [FromBody] attribute for the incoming request model parameter in the action method might help. Something like this:
[HttpPost]
public void Post([FromBody] Adotante incomingRequest)
{
\\posting logic here
}

ASP.NET Core 2.1 Unobtrusive Ajax Validation Not Working With Partial View Form Swap

I've spent several hours combing Stackoverflow and other sites trying everyone's solutions with no luck so far. I'm sure I've missed something, but I can't see it. Hopefully you can point me to a fix.
I have an initial form inside a partial view that is rendered into a parent view whose validation works fine. Once the form is submitted via Ajax replace, I return either a login or registration partial view with a new form in the response. This second form will not display the model validation errors when an incomplete form is submitted and the same partial view is returned.
Thanks in advance for any tips you can offer to bring an end to this insanity!
Parent View Section
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<div class="panel panel-primary" id="formData">
#await Html.PartialAsync("_UserNamePartial", new UserNameViewModel())
</div>
</div>
</div>
Working Rendered Partial View
<div class="panel-heading">
<h3 class="panel-title">Let's Start With Your E-mail Address</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
<form asp-controller="Account" asp-action="IsAccountValid" data-ajax="true" data-ajax-method="POST"
data-ajax-mode="replace" data-ajax-update="#formData">
#Html.AntiForgeryToken()
<div class="form-group">
<label for="UserName">Your Email Address</label>
<div class="input-group">
<input type="text" id="UserName" name="UserName" class="form-control" placeholder="Your email address" />
<div class="input-group-btn">
<button type="submit" id="btnGetStarted" class="btn btn-primary">Get Started</button>
</div>
</div>
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
</form>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
</div>
</div>
</div>
Initial Validation Controller Action
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public IActionResult IsAccountValid(UserNameViewModel model)
{
if (!ModelState.IsValid)
return PartialView("../Home/_UserNamePartial", model);
AccountRepository accountRepository = new AccountRepository(ConnectionConfig.InshoraDev);
AuthName match = accountRepository.GetAuthName(model.UserName);
if (match != null)
{
ModelState.Clear();
LoginViewModel loginModel = new LoginViewModel()
{
UserName = model.UserName
};
return PartialView("_UserLoginPartial", loginModel);
}
ModelState.Clear();
SignUpViewModel signupModel = new SignUpViewModel()
{
UserName = model.UserName,
};
return PartialView("_UserSignUp", signupModel);
}
Login Partial View (Validation Error Display Not Working)
#model Inshora.Models.Account.LoginViewModel
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="panel-heading">
<h3 class="panel-title">Log Into Your Account</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
<form id="login-form" asp-controller="Account" asp-action="Login" method="post" role="form" style="display: block;"
data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-update="formData" data-ajax-complete="AcctLib.Login.Events.onComplete">
#Html.AntiForgeryToken()
<div class="form-group">
<input type="text" name="UserName" id="UserName" tabindex="1" class="form-control" placeholder="Email Address" value="#Model.UserName">
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<input type="password" name="Password" id="Password" tabindex="2" class="form-control" placeholder="Password">
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group text-center">
<input type="checkbox" tabindex="3" class="" name="RememberMe" id="RememberMe">
<label for="RememberMe"> Remember Me</label>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<input type="submit" name="login-submit" id="login-submit" tabindex="4" class="form-control btn btn-primary" value="Log In">
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-lg-12">
<div class="text-center">
<a id="PasswordReset" asp-controller="Account" asp-action="PasswordReset" data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#formData" tabindex="5" class="inshora-forgot-password">Forgot Password?</a>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
AcctLib.Login.Init();
})
</script>
LoginViewModel
public class LoginViewModel
{
[Required]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
[Required]
public bool RememberMe { get; set; }
}
Client Side Initialization Code
AcctLib.Login.RebindForm = function() {
$('form').each(function (i, f) {
$form = $(f);
$form.removeData('validator');
$form.removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse($form);
});
}
AcctLib.Login.Init = function () {
AcctLib.Login.RebindForm();
$('#UserName').focus();
}
Update
I have updated the parent page (index.cshtml) to the following and it still doesn't display the messages.
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<div class="panel panel-primary" id="formData">
#await Html.PartialAsync("_UserNamePartial", new UserNameViewModel())
</div>
</div>
</div>
#section Scripts
{
#{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
The problem was that I had not used the asp-for tag helpers. Those helpers are responsible for generating the data-* attributes needed by the unobtrusive validation parser. Once I started using them it started working. Thank you to everyone who tried to help.
Corrected View
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
<form id="login-form" asp-controller="Account" asp-action="Login" method="post" role="form"
data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-update="#formData">
#Html.AntiForgeryToken()
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName"></label>
<input asp-for="UserName" class="form-control" placeholder="Email Address"/>
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" placeholder="Password"/>
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group text-center">
<input asp-for="RememberMe" />
<label asp-for="RememberMe"> Remember Me</label>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<input type="submit" name="login-submit" id="login-submit" tabindex="4" class="form-control btn btn-primary" value="Log In">
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-lg-12">
<div class="text-center">
<a id="PasswordReset" asp-controller="Account" asp-action="PasswordReset" data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#formData" tabindex="5" class="inshora-forgot-password">Forgot Password?</a>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
if (!ModelState.IsValid)
return PartialView("..\\Home\\_UserNamePartial", model);
pretty sure this violates pathing
if(!ModelState.IsValid)
return PartialView("../Home/_UserNamePartial", model);
Cut renderPartial link and paste to before #script section, like below:
#{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
#section Scripts
{
}

Categories