Form error message not displaying (ASP.NET CORE) - c#

I've tried and played around a lot, but I can't seem to get my form authentication working.
Before I add functionality to actually create a review, I need to get this working.
The site simply submits the form, regardless of what is in the review text element. It should be catching and displaying an error message if it is blank.
Model:
public class CreatedReview
{
public int Id { get; set; }
[StringLength(60, MinimumLength = 3)]
[Required]
public string Review1 { get; set; }
public int? RestaurantId { get; set; }
public int? UserId { get; set; }
[Required]
public int? Stars { get; set; }
public CreatedReview(string review, int stars)
{
this.Review1 = review;
this.Stars = stars;
}
}
Index.cshtml
#model CreatedReview
#{
}
<h1>Leave a review!</h1>
<form method="post" asp-action="LeaveReview">
<p>Restaurant</p>
<input type="text" name="name" />
<p>Zipcode</p>
<input type="number" name="zipcode" />
<p>Review</p>
<input type="text" name="review" />
<span asp-validation-for="Review1" class="text-danger"></span>
<p>Star Rating</p>
<input type="number" name="stars" />
<input type="submit" />
</form>
Controller:
public IActionResult LeaveReview(string name, int zipcode, string review, int stars)
{
if (!ModelState.IsValid)
{
return View("Index");
}
// create review blah blah blah (need to accept all of the parameters later)
var newReview = new CreatedReview(review, stars);
return View("Index");
}

Related

Model passed to Controller become null when receive too much passing field

I have a model that combine default data when generate Razor pages and new input data. Both of them will be passing to Controller to handle. I have done it with multiple Razor pages, with a base model that contain common field but in this new Page, I have stumble upon this error which I don't know how to dealt with it. In the deepest floor of the Model, it would only accept one field. If I try to pass more than one, my entire model in Controller become a null value.
#for (int i = 0; i < Model.layThongTinBangThuocCongTyThanhViens.Count; i++)
{
//Value for Model
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].CttvId" />
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].CttvThuocBangId" />
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].CauHinhBangId" />
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDong" />
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].CongThucDong" />
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].DichCongThuc" />
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].listId" />
var dataTarget = "#collapse" + i.ToString();
var tempid = "collapse" + i.ToString();
var danhmuc = Model.layThongTinBangThuocCongTyThanhViens.ElementAt(i);
for (int x = 0; x < danhmuc.TenDongThuocCongTies.Count; x++)
{
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].CauHinhBangId" />
//If I un-comment even one of the line below, the model become null.
//Each of them field is not special. I can comment the one above and choose whichever field I want to uncomment
//but in order to the model normal, only field is allowed to exist.
#*<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].CttvThuocBangId" />
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].CongThucDong" />
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].CauHinhBang_Cha" />
<input type="hidden" asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].TenDong" />*#
}
My TenDongThuocCongTies Model as request:
public class TenDongThuocVeCongTyModel
{
public int CttvThuocBangId { get; set; }
public int CauHinhBangId { get; set; }
public string CongThucDong { get; set; }
public string TenDong { get; set; }
public int CauHinhBang_Cha { get; set; }
[NotMapped]
public string inputValue { get; set; }
}
My Model:
[HttpPost]
[Route("post-item")]
public IActionResult PostHoaCheLuyen(TongHopItemHoaCheLuyenModel model)
{
}
Edit: The data passing back to Controller is not wrong. It just turn everything to null if I pass more than one field. It doesn't return any kind of error so I don't know how to fix it. I am hoping to see anyone who used to meet the same situation as me can solve it for me.
I use the following code,and it can work.Maybe you need to check if your model properties' names and types are right.Or have you added other properties to the model which are not existed in TongHopItemHoaCheLuyenModel.
Models:
public class TongHopItemHoaCheLuyenModel {
public List<LayThongTinBangThuocCongTyThanhViens> layThongTinBangThuocCongTyThanhViens { get; set; }
}
public class LayThongTinBangThuocCongTyThanhViens {
public List<TenDongThuocVeCongTyModel> TenDongThuocCongTies { get; set; }
public int CttvId { get; set; }
public int CttvThuocBangId { get; set; }
public int CauHinhBangId { get; set; }
public string TenDong { get; set; }
public string CongThucDong { get; set; }
public string DichCongThuc { get; set; }
public int listId { get; set; }
}
public class TenDongThuocVeCongTyModel
{
public int CttvThuocBangId { get; set; }
public int CauHinhBangId { get; set; }
public string CongThucDong { get; set; }
public string TenDong { get; set; }
public int CauHinhBang_Cha { get; set; }
[NotMapped]
public string inputValue { get; set; }
}
Actions:
public IActionResult TestBindList()
{
TongHopItemHoaCheLuyenModel t = new TongHopItemHoaCheLuyenModel()
{
layThongTinBangThuocCongTyThanhViens = new List<LayThongTinBangThuocCongTyThanhViens> {
new LayThongTinBangThuocCongTyThanhViens(){
CauHinhBangId=1,
CttvId=1,
CttvThuocBangId=1,
listId=1,
CongThucDong="ctd1",
DichCongThuc="dct1",
TenDong="td1",
TenDongThuocCongTies=new List<TenDongThuocVeCongTyModel>(){
new TenDongThuocVeCongTyModel(){
CauHinhBangId=1,
CttvThuocBangId=1,
CauHinhBang_Cha=1,
CongThucDong="ctd1",
TenDong="td1",
inputValue="value1"
},
new TenDongThuocVeCongTyModel(){
CauHinhBangId=1,
CttvThuocBangId=1,
CauHinhBang_Cha=1,
CongThucDong="ctd1",
TenDong="td1",
inputValue="value2"
}
}
},
new LayThongTinBangThuocCongTyThanhViens(){
CauHinhBangId=2,
CttvId=2,
CttvThuocBangId=2,
listId=2,
CongThucDong="ctd2",
DichCongThuc="dct2",
TenDong="td2",
TenDongThuocCongTies=new List<TenDongThuocVeCongTyModel>(){
new TenDongThuocVeCongTyModel(){
CauHinhBangId=2,
CttvThuocBangId=2,
CauHinhBang_Cha=2,
CongThucDong="ctd2",
TenDong="td2",
inputValue="value01"
},
new TenDongThuocVeCongTyModel(){
CauHinhBangId=2,
CttvThuocBangId=2,
CauHinhBang_Cha=2,
CongThucDong="ctd2",
TenDong="td2",
inputValue="value02"
}
}
}
}
};
return View(t);
}
[HttpPost]
public IActionResult PostHoaCheLuyen(TongHopItemHoaCheLuyenModel model)
{
return Ok();
}
View:
#model xxx.xxx.TongHopItemHoaCheLuyenModel
<form method="post" asp-action="PostHoaCheLuyen">
#for (int i = 0; i < Model.layThongTinBangThuocCongTyThanhViens.Count; i++)
{
//Value for Model
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].CttvId" />
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].CttvThuocBangId" />
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].CauHinhBangId" />
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDong" />
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].CongThucDong" />
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].DichCongThuc" />
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].listId" />
var dataTarget = "#collapse" + i.ToString();
var tempid = "collapse" + i.ToString();
var danhmuc = Model.layThongTinBangThuocCongTyThanhViens.ElementAt(i);
for (int x = 0; x < danhmuc.TenDongThuocCongTies.Count; x++)
{
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].CauHinhBangId" />
//If I un-comment even one of the line below, the model become null.
//Each of them field is not special. I can comment the one above and choose whichever field I want to uncomment
//but in order to the model normal, only field is allowed to exist.
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].CttvThuocBangId" />
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].CongThucDong" />
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].CauHinhBang_Cha" />
<input asp-for="layThongTinBangThuocCongTyThanhViens[i].TenDongThuocCongTies[x].TenDong" />
}
}
<input type="submit" value="submit" />
</form>
result:

Entity Framework | Error: InvalidCastException: The field of type System.Int32 must be a string, array or ICollection type

Issue
I'm receiving the following error when I submit (or post) a request to my Home Controller, for a method called NewsletterSignup. The error is prompted after my newsletter form is submitted and prior to when this method is called and the object, capturing form data, is created, creating a situation where it's difficult to troubleshoot, and identify where this exact issue is propagating.
Error
An unhandled exception occurred while processing the request.
InvalidCastException: The field of type System.Int32 must be a string, array or ICollection type.
... System.ComponentModel.DataAnnotations.MaxLengthAttribute.IsValid(object value)
... System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(object value, ValidationContext validationContext)
... System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(object value, ValidationContext validationContext)
Files
AppDbContext.cs
Application Database Context
namespace KingsEye.Data
{
public class AppDbContext : IdentityDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Home> Home { get; set; }
public DbSet<Pages> Pages { get; set; }
public DbSet<Newsletter> Newsletter { get; set; }
}
}
CollectionModel.cs
View Model used on index.cshtml and shared newsletter.cshtml view
namespace KingsEye.Models
{
public class CollectionModel
{
public Home Home { get; set; }
public Pages Pages { get; set; }
public Newsletter Newsletter { get; set; }
}
}
Newsletter.cs
Newsletter View Model
namespace KingsEye.Models
{
public class Newsletter
{
#region Newsletter
[Display(Name = "Newsletter ID: ")]
[Required(ErrorMessage = "Newsletter ID Required!")]
public int Id { get; set; }
[Display(Name = "Full Name: ")]
[DataType(DataType.Text)]
public string Fname { get; set; }
[Display(Name = "E-Mail Address: ")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Display(Name = "Phone Number: ")]
[DataType(DataType.PhoneNumber)]
public int Phone { get; set; }
[Display(Name = "Active: ")]
[MaxLength(1)]
public int Active { get; set; }
[Display(Name = "GUID: ")]
[MaxLength(37)]
public string GUID { get; set; }
[Display(Name = "Created: ")]
[DataType(DataType.DateTime)]
public DateTime Create { get; set; }
[Display(Name = "Updated: ")]
[DataType(DataType.DateTime)]
public DateTime Update { get; set; }
#endregion
}
}
HomeController.cs
Home Controller
[HttpPost]
public async Task<IActionResult> NewsletterSignup(CollectionModel model)
{
<= Error: is prompting prior to the body of this method being called,
and the parameter object being populated with post data!!!
var newsletter = new Newsletter
{
Id = 0,
Fname = model.Newsletter.Fname,
Email = model.Newsletter.Email,
Phone = model.Newsletter.Phone,
Active = 0,
GUID = Guid.NewGuid().ToString(),
Create = DateTime.Now,
Update = DateTime.Now
};
...
}
_Newsletter.cshtml
Shared view for the newsletter form
#model CollectionModel
<div id="newsletter">
#if (User.Identity.IsAuthenticated)
{
<header>
<i class="far fa-envelope-open"></i>
<div class="text">Newsletter</div>
<i class="far fa-envelope-open"></i>
</header>
<main>Subscribe to our newsletter</main>
<footer>
<form asp-controller="Home" asp-action="NewsletterSignup" method="post" id="newsletter-form" class="text-danger input-form">
<div asp-validation-summary="ModelOnly"></div>
<div class="form-group">
<input asp-for="#Model.Newsletter.Id" type="hidden" value="0" />
</div>
<div class="form-group">
<input asp-for="#Model.Newsletter.Fname" id="email-signed" class="form-control" placeholder="Your Name" />
<span asp-validation-for="#Model.Newsletter.Fname"></span>
</div>
<div class="form-group">
<input asp-for="#Model.Newsletter.Email" type="hidden" value="place#holder.com" />
</div>
<div class="form-group">
<input asp-for="#Model.Newsletter.Phone" id="email-signed" class="form-control" placeholder="(000) 000-0000" />
<span asp-validation-for="#Model.Newsletter.Phone"></span>
</div>
<div class="form-group input-submit">
<input id="newsletter-subscribe" type="submit" value="Subscribe" class="btn material-button" />
</div>
<div class="form-group">
<input asp-for="#Model.Newsletter.Active" type="hidden" value="0" />
</div>
<div class="form-group">
<input asp-for="#Model.Newsletter.GUID" type="hidden" value="0" />
</div>
<div class="form-group">
<input asp-for="#Model.Newsletter.Create" type="hidden" value="0" />
</div>
<div class="form-group">
<input asp-for="#Model.Newsletter.Update" type="hidden" value="0" />
</div>
</form>
</footer>
}
else
{
<main>
Please <a asp-controller="Auth" asp-action="Register">Sign-Up</a> to Subscribe for a Newsletter!
</main>
}
</div>
Goal
Would like to identify where this error is propagating from so that the exception in question can be debugged accordingly. Any advice or direction would surely be appreciated.
Thanks and cheers in advance.
MaxLenght attribute is for a string
[Display(Name = "Active: ")]
[MaxLength(1)] // this will fail
public int Active { get; set; }
[Display(Name = "GUID: ")]
[MaxLength(37)] //this is okay
public string GUID { get; set; }
https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.maxlengthattribute?view=netframework-4.8
Gets the maximum allowable length of the array or string data.
Maxlengh property is causing trouble in your code.You may dont face any issue while post,delete or get but while updating or editing error will pop out.just get
rid of that property add migration and update database.

Asp dot net MVC Pass Radiobutton Value to Model (or int)

I want to pass the value from my radiobutton to a model, or an integer. The value could be 5 for example.
If I add an input type as text and fill it in, it does pass that value but the value of the radio button will not work.
So my problem is that the id from Adresregelmodel is null
I tried it with an int and with a model but both does not work.
So my code from the view is :
#{
ViewData["Title"] = "Order";
}
<div class="container">
Vorige stap
<h2>Verzending en Betaling</h2>
#using (Html.BeginForm("Order", "Winkelwagen", FormMethod.Post))
{
<label for="des">Adres: </label><br />
foreach (var adresregel in ViewBag.adresregelViewbag)
{
<div class="form-group">
<label><input type="radio" name="Id" id="#adresregel.Id"> #adresregel.Adres, #adresregel.Postcode, #adresregel.Woonplaats</label>
</div>
}
<input type="text" name="Adres" />
<input type="submit" class="btn btn-success" value="Bevesting en bestel" />
}
</div>
This is my controller
[HttpPost]
public IActionResult Order(AdresregelModel adresregel, int Id)
{
// Gebruiker email ophalen
string cookie = Request.Cookies["klantemail"];
// id gebruiker ophalen
GebruikerModel gebruikermodel =
gebruiker.GetGebruikerByMail(cookie);
// Weten welke radio button is geselecteerd
// bestellingmodel maken en vullen
return View();
}
This is my Model :
public class AdresregelModel
{
public int Id { get; set; }
public int GebruikerId { get; set; }
public string Adres { get; set; }
public string Postcode { get; set; }
public string Woonplaats { get; set; }
}
You need to set a value="" attribute on your radio button for that value to be passed
Like:
<input type="radio" name="Id" value="#adresregel.Id">
Then the Id property on your model will be populated with whatever #adresregel.Id contains...
You also probably want to take the
, int Id) off your action method:

ASP.NET Core - Bind IEnumerable<T> to a ViewModel field on POST

I have a web application for registering teams to a competition, where each team can select a number of technologies that they will use for their project. The technologies are saved in a Label class.
I am using a view model to bind the information from the form to the action.
However, when I try to submit the form, it takes all other fields, except the list of technologies.
Label.cs
public class Label
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string ColorPalette { get; set; }
}
CreateTeamViewModel.cs
public class CreateTeamViewModel
{
[Required]
public string TeamName { get; set; }
public string ProjectName { get; set; }
public string ProjectDescription { get; set; }
[Required]
public string RepositoryLink { get; set; }
public List<Label> Labels = new List<Label>();
}
TeamsController.cs
public class TeamsController
{
private readonly ApplicationDbContext context;
public IActionResult Create()
{
ViewData["Labels"] = this.context.Labels.ToList();
return View();
}
[HttpPost]
public IActionResult Create(CreateTeamViewModel team)
{
List<Label> labels = team.Labels;
int count = labels.Count; // count = 0
return LocalRedirect("/");
}
}
Create.cshtml (the list of checkboxes)
#model Competition.Data.ViewModels.CreateTeamViewModel
#{
List<Label> labels = ViewData["Labels"] as List<Label>;
}
<form asp-action="Create">
<div class="form-check">
#for(int i = 0; i < labels.Count; i++)
{
<input asp-for="#Model.Labels[i].IsSelected" type="checkbox" />
<label asp-for="#Model.Labels[i].Name">
<span class="badge badge-#labels[i].ColorPalette">#labels[i].Name</span>
</label>
<input asp-for="#Model.Labels[i].Name" type="hidden" value="#labels[i].Name" />
<input asp-for="#Model.Labels[i].ColorPalette" type="hidden" value="#labels[i].ColorPalette" />
}
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
You need to bind to a list of int instead of a list of Label on your view model. Then, you'll need to use that list of selected ids to fill your list of labels on the Team entity you're persisting:
public class CreateTeamViewModel
{
[Required]
public string TeamName { get; set; }
public string ProjectName { get; set; }
public string ProjectDescription { get; set; }
[Required]
public string RepositoryLink { get; set; }
public List<int> SelectedLabels { get; set; } = new List<int>();
}
Then, you'll need to modify your form to bind your checkboxes to this list:
#foreach (var label in labels)
{
<input asp-for="SelectedLabels" id="Label#(label.Id)" value="#label.Id" type="checkbox" />
<label id="Label#(label.Id)">
<span class="badge badge-#label.ColorPalette">#label.Name</span>
</label>
}
Notice that I removed the hidden inputs. You should never post anything that the user should not be able to modify, as even hidden inputs can be tampered with.
After posting, server-side you'll end up with a list of label ids that were selected by the user. Simply query the associated labels out of your database and then assign that to the team you're creating:
team.Labels = await _context.Set<Label>().Where(x => model.SelectedLabels.Contains(x.Id)).ToListAsync();

MVC 4 Model Binding returns null

I'm having trouble with model binding in MVC. I have a class:
public class UserSurvey
{
public int Id { get; set; }
public virtual Survey Survey { get; set; }
}
Which is the model for a view:
#model SurveyR.Model.UserSurvey
<form id="surveyForm">
<div class="container survey">
#Html.HiddenFor(x=>x.Id)
#Html.EditorFor(x => x.Survey.Steps)
</div>
<input type="button" value="Submit" id="btnSubmit"/>
</form>
And then for the submit the controller takes a class:
public class SurveyResponseViewModel
{
public int Id { get; set; }
public Survey Survey { get; set; }
}
[HttpPost]
public ActionResult Submit(SurveyResponseViewModel surveyResponse)
{
...
}
When I debug the submit the surveyResponse.Survey object is populated as it should be but the surveyResponse.Id value is 0 when it should be 1.
I can see the Id=1 being passed back in the submit but the model binding doesn't seem to hook it up.
Any help would be greatly appreciated!
Kev
EDIT: The rendered html looks like this:
<form id="surveyForm">
<div class="container survey">
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Id" name="Id" type="hidden" value="1" />
So yes the value appears there and is also passed in the submit if I look using dev tools.
EDIT 2: The Form data in dev tools definitely contains "Id:1".
Your Code seems to be fine.Try passing the id value explicitly as another parameter like below
[HttpPost]
public ActionResult Submit(SurveyResponseViewModel surveyResponse , int Id )
{
surveyResponse.Id = Id
}
I have tested. Its working fine.
public ActionResult test1()
{
var model = new UserSurvey();
model.Id = 10;
return View(model);
}
[HttpPost]
public ActionResult test1(SurveyResponseViewModel surveyResponse)
{
var x = surveyResponse.Id; // returns 10
return View(new UserSurvey());
}
public class SurveyResponseViewModel
{
public int Id { get; set; }
public Survey Survey { get; set; }
}
public class UserSurvey
{
public int Id { get; set; }
public virtual Survey Survey { get; set; }
}
public class Survey
{
public string Steps { get; set; }
}
#model TestWeb.Controllers.UserSurvey
#using (Html.BeginForm())
{
<div class="container survey">
#Html.HiddenFor(x=>x.Id)
#Html.EditorFor(x => x.Survey.Steps)
</div>
<input type="submit" value="Submit" id="btnSubmit"/>
}

Categories