the ModelState is Invalid.I Think I pass Model Wrongly.Any Idea?
controller:
[Authorize]
[HttpPost]
public async Task<IActionResult> SendComment([Bind("CommentID,Comment,Date,AdminId")]AdminReport adminReport,int ReportID)
{
var x = _userReport.UserReports.Find(ReportID);
x.IsViewed = true;
adminReport.UserId = x.UserId;
adminReport.AdminId = _userManager.GetUserId(HttpContext.User);
if (ModelState.IsValid){
_adminReport.Add(adminReport);
await _adminReport.SaveChangesAsync();
return View(); }
return RedirectToAction("SendDoneAdmin");
}
its how I pass a Model:
<div class="card-footer">
<form asp-controller="Admin" asp-action="ُSendComment" method="post">
<input type="hidden" value="#report.ReportID" name="ReportID" />
<button type="submit" class="btn btn-primary">SendComment</button>
</form>
Model:
[Key]
public int CommentID { get; set; }
[Required]
public string Comment { get; set; }
public string AdminId { get; set; }
public string UserId { get; set; }
}`
Your quotation no clear but must know for pass data via Form tag
must all input inside Form tag
Controller
public async Task<IActionResult> SendComment()
{
// write your code....
return View(new AdminReport()); // must return new object
}
POST
Normal write again your action SendComment no any change
HTML
for pass AdminReport model must write flied inside form tag
<form asp-controller="Admin" asp-action="Viewed" method="post">
<input type="hidden" value="#report.ReportID" name="ReportID" />
/* for example */
<input type="hidden" asp-for="model.Comment" />
<button type="submit" class="btn btn-primary">SendComment</button>
</form>
No Problem if you have another view but must return View(new AdminReport());
If you want remove validation for comment prop use below code.
// remove all key
foreach (var key in ModelState.Keys).ToList())
ModelState.Remove(key);
// or for one
ModelState.Remove("comment ");
You put this [Requiried] attribute on the Comment:
[Required]
public string Comment { get; set; }
You will have to include that input in your form in order for the validation to pass.
You can add that field like this:
<div class="card-footer">
<form asp-controller="Admin" asp-action="Viewed" method="post">
<input type="hidden" value="#report.ReportID" name="ReportID" />
<input type="text" name="Comment" />
<button type="submit" class="btn btn-primary">SendComment</button>
</form>
Related
What is my mistake? AllFindedBrands property is not passing to SearchBrandResult Action of Controller
Controller:
public async Task<IActionResult> Search(string Articul, int idClient)
{
List<BrandList> findedBrands = new List<BrandList>();
#ViewBag.list = woDupes;
SearchViewModel model = new SearchViewModel();
model.Articul = Articul;
model.idClient = idClient;
model.AllFindedBrands = new List<BrandList>(findedBrands);
return View(model);
}
[HttpPost]
public async Task<IActionResult> SearchBrandResult(SearchViewModel model)
{
return View();
}
View:
<form asp-controller="Search" asp-action="SearchBrandResult" asp-route-
Articul="#Model.Articul"
asp-route-AllFindedBrands="#Model.AllFindedBrands" asp-route-
idClient="#Model.idClient" method="post" enctype="multipart/form-data">
<select asp-for="SelectedBrand" asp-items="#(new SelectList(#ViewBag.list,
nameof(FindedBrand.Name),
nameof(FindedBrand.Name)))"
multiple="true" class="form-control brand-chosen">
</select>
<input type="submit" />
All other properties of ViewModel is successfully passed to th Action
AllFindedBrands is type of complex model and asp-route-* cannot dynamic bind the value. You can F12 in the browser to check the generated url in the form.
Two ways you can follow:
1.By using asp-all-route-data and foreach the AllFindedBrands to bind the value which passes the value by route data.
Assume your model like below:
public class SearchViewModel
{
public string Articul { get; set; }
public string idClient { get; set; }
public List<BrandList> AllFindedBrands { get; set; }
public List<string> SelectedBrand { get; set; }
}
public class BrandList
{
public string Name { get; set; }
}
View(For easy testing, I just hard-coded the dropdownlist):
#model SearchViewModel
#{
var data = new Dictionary<string, string>();
for(int i=0;i<Model.AllFindedBrands.Count();i++)
{
data.Add("AllFindedBrands[" + i + "].Name", Model.AllFindedBrands[i].Name);
}
}
<form asp-action="SearchBrandResult" asp-route-Articul="#Model.Articul" asp-all-route-data="#data" asp-route-idClient="#Model.idClient" method="post" enctype="multipart/form-data">
<select asp-for="SelectedBrand" multiple="true" class="form-control brand-chosen">
<option value="aaa">aaa</option>
<option value="bbb">bbb</option>
<option value="ccc">ccc</option>
</select>
<input type="submit" />
</form>
2.By listing the property and make them hidden inputs which passes the value by form data:
#model SearchViewModel
<form asp-action="SearchBrandResult" asp-route-Articul="#Model.Articul" asp-route-idClient="#Model.idClient" method="post" enctype="multipart/form-data">
#for (int i = 0; i < Model.AllFindedBrands.Count(); i++)
{
<input asp-for="#Model.AllFindedBrands[i].Name" hidden />
}
<select asp-for="SelectedBrand" multiple="true" class="form-control brand-chosen">
<option value="aaa">aaa</option>
<option value="bbb">bbb</option>
<option value="ccc">ccc</option>
</select>
<input type="submit" />
</form>
I am very new to this and I am trying to show multiple entries to show and have a single button for each entry to edit them. I thought it would be really easy but For some reason I am not getting the clicked entity. Is there way of getting modified entity without running javascript?
Any help will be appreciated. I couldn't find any example code that does this. There are many examples that returns all the entries but not the single element.
Here is my entity class Resource:
public class Resource
{
[Required]
public string title { get; set; }
[Required]
public int value { get; set; }
[Key]
[Required]
public int id { get; set; }
}
On the controller side I have:
[HttpGet]
public IActionResult Index()
{
return View(resources);
}
[HttpPost]
public IActionResult Index(Resource resource)
{
return View(resource);
}
Here is the View and EditorTemplates
#model learningMVC.Models.Resource[]
#{
ViewData["Title"] = "index";
}
<h1>index</h1>
<fieldset>
#Html.EditorFor(x => x);
</fieldset>
#addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"
#model learningMVC.Models.Resource
<div>
First Name:<br />
<form asp-action="Index" asp-controller="Home">
<input asp-for="id" class="form-controller" />
<input asp-for="value" class="form-controller" />
<input asp-for="title" class="form-controller" />
<input type="submit" value="Save" class="btn btn-primary" id="btnSubmit_#Model.id" />
</form>
</div>
In your case, you should use particalview instead of editfor, you can see my demo below.
_ResourcesPartical.cshtml:
#model Resource
<div>
<form method="post" asp-action="Index">
First Name:<br />
<input asp-for="id" class="form-controller" />
<input asp-for="value" class="form-controller" />
<input asp-for="title" class="form-controller" />
<input type="submit" value="save" />
</form>
</div>
Your Index view:
#model List<Resource>
#foreach(var m in Model)
{
#await Html.PartialAsync("_ResourcesPartical", m)
}
Controller:
[HttpGet]
public IActionResult Index()
{
//here you get your data.below is my fake data.
var resources= new List<Resource>
{
new Resource
{
id = 1,
title = "aa",
value = 3
},
new Resource
{
id = 2,
title = "bb",
value = 4
}
};
return View(resources);
}
[HttpPost]
public IActionResult Index(Resource resource)
{
return RedirectToAction("Index");
}
Test result:
I am using an if statement which should perform some operations when the model state is valid, but apparently ModelState.IsValid does not return true. I have tried clearing the previous ModelState using ModelState.Clear() but it did not work as well.
Here is my Controller
// This is the first action for which I'm using the model state
[HttpPost]
public async Task<IActionResult> Register(userModel model)
{
if (ModelState.IsValid)
{
userData lcl_userr = new userData
{
username = model.username,
password = model.password,
email = model.email
};
_context.users.Add(lcl_userr);
await _context.SaveChangesAsync();
ViewBag.Success = "Registered successfully";
ModelState.Clear();
return View();
}
return View(model);
}
// And this is the second one
[HttpPost]
public IActionResult Index(userModel model)
{
if (ModelState.IsValid)
{
var findValue = _context.users.Any(o => o.username == model.username);
var findValue2 = _context.users.Any(o => o.password == model.password);
if (findValue && findValue2)
ViewBag.Name = "Success";
}
return View(model);
}
And here's the form
<form method="post" asp-action="Index" asp-controller="Portal">
<div class="text-danger"></div>
<div class="text-warning">#ViewBag.Name</div>
<div class="form-group">
<label class="mt-4 asp-for="username"">Username</label>
<input class="form-control" type="text" required="required" asp-for="username" />
<span></span>
</div>
<div class="form-group">
<label class="mt-4" asp-for="password">Password</label>
<input type="password" class="form-control" required="required" asp-for="password"/>
<span></span>
</div>
<center>Don't have an account? <a asp-controller="Portal" asp-action="Register">Register here</a>.</center>
<center><button value="login" class="btn btn-primary mt-3 w-25 mb-3 align-content-center">Login</button></center>
</form>
The model class being called inside the action and the class members work fine and the values it gets from the form are also working fine, it's just the model state which does not work.
The userModel class
public class userModel
{
[Display(Name = "username")]
[Required]
public string username { get; set; }
[Required]
[Display(Name = "password")]
public string password { get; set; }
[Required]
[Display(Name = "email")]
public string email { get; set; }
}
The second request to public IActionResult Index(userModel model) whose model doesn't contais email. IsValid is false.
[Required]
[Display(Name = "email")]
public string email { get; set; }
The ModelState instance for the email address has an error in the Errors collection.
When MVC creates the model state for the submitted properties, it also goes through each property in the ViewModel and validates the property using attributes associated to it. If any errors are found, they are added to the Errors collection in the property's ModelState.
Solution
Just reomve if (ModelState.IsValid) in Index action and there is no need to add it at all.
or if you insist to keep if (ModelState.IsValid), you need to add email inside form.
<input type="hidden" asp-for="email" />
One of my asp.net core pages isn't passing its model back to the controller. I've investigated similar threads in stackoverflow but none could solve my issue - what's different in this particular case?
In the attached MVC, I fill the input box "Enter here some text", then I click on button "CLICK HERE". The debugger enters correctly the controller but the variable "TEST" returns null.
Any geniuses out there able to help me out?
My Model:
namespace MyProgram.Models._04_ModuleTasker
{
public class TaskerViewModel
{
public SelectList SelectListLocations;
public SelectList SelectListUsers;
public SelectList SelectListFilters;
public string SelectedCompanyLocationDesc;
public string SelectedUserId;
public string SelectedFilter;
}
}
My View:
#model MyProgram.Models._04_ModuleTasker.TaskerViewModel
#{
ViewData["Title"] = "AllTasks";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container-fluid">
<div class="PageTitle">
Tasker
<hr class="TitleHR" />
</div>
<div style="text-align:center;margin-top:20px" class="text-body">
<form asp-controller="Tasker" asp-action="ShowActiveTasksPOST" method="post" role="form">
<input type="text" asp-for="SelectedUserId" /> Enter here some text <br />
<input type="submit" class="btn btn-success InputShortWidth LoginButton" value="CLICK HERE" />
</form>
</div>
</div>
My Controller:
[HttpPost]
public async Task<IActionResult> ShowActiveTasksPOST(TaskerViewModel taskerViewModel)
{
string TEST = taskerViewModel.SelectedUserId;
return RedirectToAction("Index", "Home");
}
To make the binding works, you need to convert the fields to properties with with setters and getters. E.g.:
public string SelectedCompanyLocationDesc { get; set; }
public string SelectedUserId { get; set; }
public string SelectedFilter { get; set; }
I try to bind an object like this in a Action
public class MonthDataViewModel
{
public int Year { get; set; }
public int Month { get; set; }
public IEnumerable<MoneyDataItemViewModel> MoneyCosts { get; set; }
}
public class MoneyDataItemViewModel
{
public string Title { get; set; }
public decimal Cost { get; set; }
}
Is that possible? How do i design the form?
I try a few times but the property MoneyCosts won't be bind , and this is the data i submited:
Year=2016
Moneh=8
MoneyCosts.Title=ABC
MoneyCosts.Cost=100
MoneyCosts.Title=DEF
MoneyCosts.Cost=200
I saw a modelbinder called ArrayModelBinder<T> , how do i use it?
If you use x-www-url-formencoded content type then try to change(if possible) your post data like below:
Year=2016&Month=8&MoneyCosts[0].Title=ABC&MoneyCosts[0].Cost=100&MoneyCosts[1].Title=DEF&MoneyCosts[1].Cost=200
How do i design the form?
<form asp-controller="Home" asp-action="AccountName" method="post">
<input type="text" name="Year" />
<input type="text" name="Month" />
#for(var i = 0; i < count; i++)
{
<input type="text" name="#("MoneyCosts["+ i + "].Title")" />
<input type="text" name="#("MoneyCosts["+ i + "].Cost")" />
}
<input type="submit" value="Submit" />
</form>
If you use json content type, your data should be something like this:
{"Year": "2016", "Month":"8", "MoneyCosts":[{"Title":,"ABC"}, ...]}
in the case of json request you should use FromBody in action method.
[HttpPost]
public IActionResult ActionName([FromBody]MonthDataViewModel model)