I have a model property who's value can be required or not required on the view based on the value of another property. I have implemented it in the view as follows.
<input #Html.Raw(Model.IsRequired ? "required data-val=true' data-val-required='" + Model.Name + " selection is required.'" : "") asp-for="Name" class="form-control" />
if (Model.IsRequired)
{
<span asp-validation-for="Name" class="text-danger"></span>
}
As indicated based on the Required field value, the validation is applied or not applied.
I also had to add this bit of code.
$("#btnSubmit").on("click", function () {
$("#form").submit();
});
The code works fine in validation of the code, however the message does not get displayed. What am I missing?
I also tried using this answer and changed my validation span to as below, but it did not work either.
<span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
If you do not want to add Data Annotations for validation.Here is a simple workaound like below:
1.Model:
public class TestModel
{
public string Name { get; set; }
public bool IsRequired { get; set; }
}
2.View(You need to change your #Html.Raw() and be sure you have added#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}):
#model TestModel
<form id="form">
<input #Html.Raw(Model.IsRequired ? "data-val='true' data-val-required='selection is required.'" : "") id="Name" name="Name" type="text" class="input-validation-error" />
#if (Model.IsRequired)
{
<span asp-validation-for="Name" class="text-danger"></span>
}
<input id="btnSubmit" type="submit" />
</form>
#section Scripts{
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
3.Controller:
public IActionResult Index()
{
var test = new TestModel() { IsRequired = true };
return View(test);
}
4.Result:
Related
If a user submits an empty value, I would like the following validation error to be displayed: "The Comment field is required."
However, the actual validation error produced is: "The value '' is invalid".
Here is my ViewModel:
public class CommentsViewModel
{
public int TranslationSetId { get; set; }
[Required]
public string NewComment { get; set; }
public IEnumerable<TranslationSetComment> Comments { get; set; }
}
Here is my POST action method:
[IgnoreAntiforgeryToken]
[HttpPost]
public async Task<ActionResult> AddCommentFromTranslationSetDetailView(
CommentsViewModel commentsViewModel,
[FromServices] ITranslationSetDetailBuilderService builderService)
{
if (!ModelState.IsValid)
{
TranslationSetDetailViewModel model = await builderService.BuildTranslationSetDetailViewModelAsync(commentsViewModel.TranslationSetId);
model.CommentsViewModel = commentsViewModel;
return View("TranslationSetDetail", model);
}
else
{
await _translationSetService.AddCommentAsync(_userLocator.CurrentUserId, commentsViewModel.TranslationSetId, commentsViewModel.NewComment);
return RedirectToAction(nameof(TranslationSetDetail), new { TranslationSetId = commentsViewModel.TranslationSetId.ToString() });
}
}
Here is the HTML Partial:
<a data-toggle="collapse"
href="#string.Concat("#add-comment-collapse", Model.TranslationSetId.ToString())"
aria-expanded="false"
aria-controls="#string.Concat("add-comment-collapse", Model.TranslationSetId.ToString())">
<p>Add a comment</p>
</a>
<div class="collapse" id="#string.Concat("add-comment-collapse", Model.TranslationSetId.ToString())">
<form class="add-comment-form"
asp-controller="#nameof(Home)"
asp-action="#nameof(Home.AddCommentFromTranslationSetDetailView)"
method="post">
<input type="hidden" asp-for="TranslationSetId" value="#Model.TranslationSetId" />
<span asp-validation-for="NewComment" class="text-danger"></span>
<textarea asp-for="NewComment" class="form-control"></textarea>
<button type="submit" class="btn btn-primary my-2">Add</button>
<button type="reset" class="btn btn-light my-2">Cancel</button>
<div asp-validation-summary="All"></div>
</form>
</div>
Please note: I have put my form inside of partial. I don't see a reason why this should have an effect, but just in case, below is the line of code where I use the partial:
<div class="row">
<div class="col-sm-12">
<hr />
<h4>Comments:</h4>
<partial name="_TranslationSetDetailCommentsPartial" for="CommentsViewModel" />
</div>
</div>
Here is a screenshot from my running application. In the image you can see the validation error message that is produced after I tried to submit an empty form:
Here is a screenshot of the ModelState from a form submitted without entering a value into the text field.
Thank you to anyone who takes the time to look at this issue and please let me know if you would like any further code snippets etc.
In the example below, a complex ViewModel contains the property "ExampleEntity.Name". How can this nested property from a complex view model be retrieved from a controller in ASP.NET Core?
Form field with nested property "Entity1.Name"
<div class="form-group col-md-6">
<label asp-for="#Model.ExampleEntity.Name" class="control-label"></label>
<input asp-for="#Model.ExampleEntity.Name" class="form-control" />
<span asp-validation-for="#Model.ExampleEntity.Name" class="text-danger"></span>
</div>
Controller
public async Task<IActionResult> Update(string ExampleEntity.Name) // This does not work
{
}
Assuming you have a form like this:
<form method="POST">
<input asp-for="#Model.ExampleEntity.Name" />
</form>
you can read the value of that field with:
1. [FromForm] attribute:
Annotate an action parameter of suitable type with FromForm and denote which field its value should be sourced from.
You can accept a class parameter with a prefix:
public void OnPost([FromForm(Name = "ExampleEntity")] ExampleEntity model)
{
// model is filled with form fields that start with "ExampleEntity."
}
Or specify a particular field and read its value:
public void OnPost([FromForm(Name = "ExampleEntity.Name")] string name)
{
// name is populated from the form's `ExampleEntity.Name` field
}
2. IFormCollection:
You can go deeper and accept a IFormCollection inside your action and read the form values from it:
public void OnPost(IFormCollection form)
{
var exampleEntityName = form["ExampleEntity.Name"];
}
or even deeper:
public void OnPost()
{
var exampleEntityName = Request.Form["ExampleEntity.Name"]
}
In my project,using string ExampleEntity.Name will get error.Asp.net core bind data with name attribute,so if you only want to bind the value of <input asp-for="#Model.ExampleEntity.Name" class="form-control" />,you can change the name attribute of Input.
Here is a demoļ¼
View:
<div class="form-group col-md-6">
<label asp-for="#Model.ExampleEntity.Name" class="control-label"></label>
<input asp-for="#Model.ExampleEntity.Name" name="Name" class="form-control" />
<span asp-validation-for="#Model.ExampleEntity.Name" class="text-danger"></span>
</div>
Action:
public async Task<IActionResult> Update(string Name)
{
}
Method in Model:
public void OnPost()
{
var inputName = Request.Form["inputName"];
// do something with inputName
ViewData["test"] = inputName;
}
How it can be used in view:
<form method="post"><input type="text" name="inputName" value="123" class="form-control" /><button type="submit">submite</button><div>#ViewData["test"]</div></form>
In the ASP.NET Core 3.1 webapp I have a check box, "Food", which is of a boolean type and should be bind to a property HasFood, and I'd like to know how to manage this:
If the check box is checked:
A dropdown list Caterer becomes a required field.
A request cannot be submitted unless the Caterer option is selected from the list.
If the check box is not checked:
The Caterer dropdown list is not a required field.
I am total new to razor, I even dont know how to implement a checkbox. so if you could give me the whole code for this problem, I would be very very thankful
If the check box is checked: A dropdown list Caterer becomes a required field
If the check box is not checked: The Caterer dropdown list is not a required field.
To achieve the requirement, you can try to implement remote validation, like below.
//...
public bool HasFood { get; set; }
[Remote(action: "RequiredOrNot", controller: "Home", AdditionalFields = nameof(HasFood))]
public string SelectedCaterer { get; set; }
//other properties
//...
Action method
[AcceptVerbs("GET", "POST")]
public IActionResult RequiredOrNot(string selectedCaterer, bool hasFood)
{
if (hasFood && selectedCaterer == "0")
{
return Json("The SelectedCaterer field is required.");
}
return Json(true);
}
View page
<form asp-action="CreateCaterer">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="HasFood" /> #Html.DisplayNameFor(model => model.HasFood)
</label>
</div>
<div class="form-group">
<label asp-for="SelectedCaterer" class="control-label"></label>
<select asp-for="SelectedCaterer" class="form-control" asp-items="ViewBag.Caterers">
<option value="0">---Select---</option>
</select>
<span asp-validation-for="SelectedCaterer" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Test Result
Update:
Above example would works well within ASP.NET Core MVC application. If your project is an ASP.NET Core Razor Pages, you can achieve same remote validation using PageRemote attribute, like below.
public bool HasFood { get; set; }
[PageRemote(ErrorMessage = "The SelectedCaterer field is required.",
AdditionalFields = "HasFood,__RequestVerificationToken",
HttpMethod = "post",
PageHandler = "RequiredOrNot")]
public string SelectedCaterer { get; set; }
The handler method
public JsonResult OnPostRequiredOrNot(string selectedCaterer, bool hasFood)
{
if (hasFood && selectedCaterer == "0")
{
return new JsonResult(false);
}
return new JsonResult(true);
}
You can check the following doc to know more about implementing Remote Validation in Razor Pages:
https://www.learnrazorpages.com/razor-pages/validation/remote-validation
Im working on html content to disply data in mvc view binding data from model class, my requirement is to set values to input fields to html content from c#.
i want final content should come up with html content and values from model.
EXAMPLE:
<form action="/action_page.php">
<label for="fname">First name:</label>
<input type="text" id="fname" name="fname"><br><br>
<label for="lname">Last name:</label>
<input type="text" id="lname" name="lname"><br><br>
<input type="submit" value="Submit">
</form>
This is my html content which is coming from text file. i've data in my model, i.e,
public class EmployeeModel
{
public string fname { get; set; } = "Stack";
public string lname { get; set; } = "OverFlow";
}
In View :
#Html.Raw(ViewBag.htmlContent)
This is what the HtmlHelper class is for.
Set the view model in your view file and create a form around it.
#model Models.EmployeeModel
#using (Html.BeginForm("Edit", "Employees", FormMethod.Post))
{
#Html.LabelFor(m => m.fname)
#Html.TextBoxFor(m => m.fname)
<input type="submit" value="Submit"/>
}
Invoke the view from your controller with an instance of the model to edit.
public IActionResult Edit(int id)
{
...
employee = service.GetEmployeeById(id);
return View(employee);
}
one thig you could try would be to set values in Razor:
// your controller
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View(new EmployeeModel());// pass the actual viewmodel instance to the view here
}
}
#model EmployeeModel
.......
<form action="/action_page.php">
<label for="fname">First name:</label>
<input type="text" id="fname" name="fname" value="#Model.fname"><br><br> <!-- reference #Model fields as usual -->
<label for="lname">Last name:</label>
<input type="text" id="lname" name="lname" value="#Model.lname"><br><br><!-- reference #Model fields as usual -->
<input type="submit" value="Submit">
</form>
and a fiddle for you to play with: https://dotnetfiddle.net/37asAw
I have a form with 3 inputs using tag helpers and a data transfer object with these 3 properties.
When I add the object to my database the values are empty. I set the properties to [Required] and even this doesn't give me an error.
I declared this as model in the form cshtml file:
#model CRM_Collect.Dtos.ClientDto
Form:
<form asp-controller="Client" asp-action="AddClient" method="post">
<div class="form-group">
<label for="companyName">Company</label>
<input asp-for="Company" class="form-control" id="companyName" placeholder="Company name">
</div>
<div class="form-group">
<label for="comment">Comment</label>
<textarea asp-for="Comment" class="form-control" id="comment" rows="3"></textarea>
</div>
<div class="form-group">
<label for="companyWebsite">Website</label>
<input asp-for="Website" class="form-control" id="companyWebsite" placeholder="www.example.com">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
Data transfer class
[Required]
public String Company { get; set; }
[Required]
public String Website { get; set; }
[Required]
public String Comment { get; set; }
Post controller
[HttpPost]
public ActionResult AddClient(ClientDto client)
{
ClientContext clientContext = new ClientContext();
Client clientToAdd = new Client { Comment = client.Comment, Company = client.Company, Website = client.Website };
clientContext.Clients.Add(clientToAdd);
clientContext.SaveChanges();
return View();
}
Explicitly use the FromBody attribute on the action's parameter. Also consider check ing model state as the model is using [Required] validation attribute.
[HttpPost]
public ActionResult AddClient([FromBody]ClientDto client) {
if(ModelState.IsValid) {
using(var clientContext = new ClientContext()) {
var clientToAdd = new Client {
Comment = client.Comment,
Company = client.Company,
Website = client.Website
};
clientContext.Clients.Add(clientToAdd);
clientContext.SaveChanges();
}
}
return View();
}
Turns out I am using a version that doesn't support the helper tags. I am not using ASP.NET Core which is the issue.
This is the most common mistake I have seen when people try to post a form to a controller. You need to have the name attribute set on all your inputs of the form so the controller will process the data inside of the input field and correspond that to the properties of the model serving as the parameter of your action.
Your form should look like this:
<form asp-controller="Client" asp-action="AddClient" method="post">
<div class="form-group">
<label for="companyName">Company</label>
<input asp-for="Company" name="company" class="form-control" id="companyName" placeholder="Company name">
</div>
<div class="form-group">
<label for="comment">Comment</label>
<textarea asp-for="Comment" name="comment" class="form-control" id="comment" rows="3"></textarea>
</div>
<div class="form-group">
<label for="companyWebsite">Website</label>
<input asp-for="Website" name="website" class="form-control" id="companyWebsite" placeholder="www.example.com">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>